28

In my C++ program, I have the string

string s = "/usr/file.gz";

Here, how to make the script to check for .gz extention (whatever the file name is) and split it like "/usr/file"?

5
  • stackoverflow.com/a/874160/276994 Commented May 10, 2012 at 10:48
  • @Vlad you should close vote, instead of linking Commented May 10, 2012 at 10:50
  • @shiplu.mokadd.im: well, it's not a full duplicate: the said question only checks for the ending, but doesn't remove it. I'm vague about it. Commented May 10, 2012 at 10:51
  • 1
    "the script"? do you want an answer in some scripting language? Commented May 10, 2012 at 10:53
  • There's like hundreds of different ways you can do this. Have you really not tried/found anything? Like here: en.cppreference.com/w/cpp/string/basic_string Commented May 10, 2012 at 11:38

6 Answers 6

65

You can use erase for removing symbols:

str.erase(start_position_to_erase, number_of_symbols);

And you can use find to find the starting position:

start_position_to_erase = str.find("smth-to-delete");
Sign up to request clarification or add additional context in comments.

Comments

12

How about:

// Check if the last three characters match the ext.
const std::string ext(".gz");
if ( s != ext &&
     s.size() > ext.size() &&
     s.substr(s.size() - ext.size()) == ".gz" )
{
   // if so then strip them off
   s = s.substr(0, s.size() - ext.size());
}

5 Comments

substr() always creates new object. It's not sounds well by performance reasons.
@Alexander: True, but there was no mention of performance considerations in the question.
With very similar code, I managed to wipe 3 complete PCs(*). You probably want s.size() > 3, as ".gz" is a hidden file and should not be stripped to "". ( * I stripped too much, added * and then did a rm -rf /* )
@MSalters: An impressive achievement! Tell me you didn't run it as root? :) I only really intended this as a simple example for the OP but I think your point is very important in context and I've changed accordingly. Thanks for sharing it!
This code looks more complicated than necessary. Doesn't C++ have an ends_with method like in Java or Python? And what is the point of s != ext? The code would work equally well without that comparison.
4

If you're able to use C++11, you can use #include <regex> or if you're stuck with C++03 you can use Boost.Regex (or PCRE) to form a proper regular expression to break out the parts of a filename you want. Another approach is to use Boost.Filesystem for parsing paths properly.

1 Comment

regex should be an overkill for such a simple task
3

Since C++17, you can use the built-in filesystem library to treat file paths, which is derived from the BOOST filesystem library. Note that the operator / has been overloaded to concatenate std::filesystem::paths.

#include <filesystem>

std::string stripExtension(const std::string &path_str) {
  std::filesystem::path p{path_str};
  if (p.extension() == ".gz") {
    return p.parent_path() / p.stem();
  }
  return {};
}

Comments

2
void stripExtension(std::string &path)
{
    int dot = path.rfind(".gz");
    if (dot != std::string::npos)
    {
        path.resize(dot);
    }
}

Comments

2

Or shorter version of another answer (C++11)

std::string stripExtension(const std::string &filePath) {
    return {filePath, 0, filePath.rfind('.')};
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.