Problem
You want to remove a substring from a string.
Solution
Use the find, erase, and length member functions of basic_string:
std::string t = "Banana Republic"; std::string s = "nana"; std::string::size_type i = t.find(s); if (i != std::string::npos) t.erase(i, s.length( ));
This will erase s.length( ) elements starting at the index where find found the first occurrence of the substring.
Discussion
There are lots of variations on the theme of finding a substring and removing it. For example, you may want to remove all instances of a substring instead of just one. Or just the last one. Or the seventh one. Each time the steps are the same: find the index of the beginning of the pattern you want to remove, then call erase on that index for the next n characters, where n is the length of the pattern string. See Recipe 4.9 for the different member functions for finding things in strings.
Chances are you also want to make your substring-removal function generic, so you can use it on strings of any kind of character. Example 4-19 offers a generic version that removes all instances of the pattern from a string.
Example 4-19. Remove all substrings from a string (generic version)
#include #include using namespace std; template void removeSubstrs(basic_string& s, const basic_string& p) { basic_string::size_type n = p.length( ); for (basic_string::size_type i = s.find(p); i != basic_string::npos; i = s.find(p)) s.erase(i, n); } int main( ) { string s = "One fish, two fish, red fish, blue fish"; string p = "fish"; removeSubstrs(s, p); cout << s << ' '; }
The basic_string member function erase is what does the important work here. In , it is overloaded three times. The version I used in Example 4-19 accepts the index to begin erasing at and the number of characters to erase. Another version accepts starting and ending iterator arguments, and there is a version that takes a single iterator and erases the element at that location. To ensure optimal performance, prefer the first two when you plan to delete multiple contiguous elements instead of repeatedly calling s.erase(iter) for each element you want to erase. In other words, use member functions that operate on ranges instead of single elementsespecially for those member functions that modify the contents of the string (or sequence). By doing so, you will avoid the extra function calls to erase for each element in the sequence, and you will permit the string implementation to more intelligently manage its data.
Building C++ Applications
Code Organization
Numbers
Strings and Text
Dates and Times
Managing Data with Containers
Algorithms
Classes
Exceptions and Safety
Streams and Files
Science and Mathematics
Multithreading
Internationalization
XML
Miscellaneous
Index