27

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"?

roschach
  • 8,390
  • 14
  • 74
  • 124
John
  • 2,035
  • 13
  • 35
  • 44

6 Answers6

64

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");
Aligus
  • 1,585
  • 1
  • 9
  • 11
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());
}
uncletall
  • 6,609
  • 1
  • 27
  • 52
Component 10
  • 10,247
  • 7
  • 47
  • 64
  • substr() always creates new object. It's not sounds well by performance reasons. – Aligus May 10 '12 at 11:01
  • @Alexander: True, but there was no mention of performance considerations in the question. – Component 10 May 10 '12 at 11:28
  • 5
    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 May 10 '12 at 12:51
  • @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! – Component 10 May 10 '12 at 13:27
  • 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. – Roland Illig Oct 10 '19 at 04:09
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.

Dean Michael
  • 3,446
  • 1
  • 20
  • 14
2

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

std::string stripExtension(const std::string &filePath) {
    return {filePath, 0, filePath.rfind('.')};
}
Petr Gladkikh
  • 1,906
  • 2
  • 18
  • 31
2

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 {};
}
wu1meng2
  • 71
  • 6
1
void stripExtension(std::string &path)
{
    int dot = path.rfind(".gz");
    if (dot != std::string::npos)
    {
        path.resize(dot);
    }
}