Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to replace all occurrences of one character with two characters using std::string?

Is there a nice simple way to replace all occurrences of "/" in a std::string with "\/" to escape all the slashes in a std::string?

like image 535
WilliamKF Avatar asked Apr 09 '11 18:04

WilliamKF


People also ask

How do you replace all occurrences of a char in a string C++?

In C++, the STL provides a function to replace() to change the contents of an iterable container. As string is a collection of characters, so we can use the std::replace() function to replace all the occurrences of character 'e' with character 'P' in the string.

How do you replace all occurrences of a character in a string?

To replace all occurrences of a substring in a string by a new one, you can use the replace() or replaceAll() method: replace() : turn the substring into a regular expression and use the g flag.


5 Answers

Probably the simplest way to get this done is with boost string algorithms library.

  boost::replace_all(myString, "/", "\\/");

  std::string result = boost::replace_all_copy(myString, "/", "\\/");
like image 99
UncleBens Avatar answered Oct 23 '22 08:10

UncleBens


The answer is no... there is no "easy" way if you mean an one-liner already provided by the standard library. However it's not hard to implement that function.

First of all I think that probably you will also need to replace \ with \\ and other special characters. In this case using the replaceAll implementation given by ildjarn is going to be annoying (you'll need to replace the same string several times).

In my opinion there are many cases of string processing where nothing beats using an explicit char * approach. In this specific case however probably just using an index is fine:

std::string escape(const std::string& s)
{
    int n = s.size(), wp = 0;
    std::vector<char> result(n*2);
    for (int i=0; i<n; i++)
    {
        if (s[i] == '/' || s[i] == '\\')
            result[wp++] = '\\';
        result[wp++] = s[i];
    }
    return std::string(&result[0], &result[wp]);
}

Basically the idea is to move over the string and adding an extra \ character before any special character (in the above I just handled / and \, but you get the idea). The result is known to be at maximum 2*n in lenght, so I preallocate it making the whole processing O(n) (the replaceAll approach instead keeps moving the rest of the string to the right, making it O(n^2)). Even for short strings like "this is a test with /slashes/ that should be /escaped/" the above function is on my PC more efficient (1.3x in speed) even if calling replaceAll just once and handling instead two special chars in escape.

Note also that this function naturally returns a separate string instead of modifying the string in place (IMO a better interface) and in the timing comparison I had to create a string for each call so the results are even shifted toward equality because of that added constant time.

The above read/write approach can also be easily extended to more complex substitutions (e.g. replacing > with &gt; or characters not in printable range with %xx encoding) still maintaining a good efficiency for big strings (just one pass).

like image 28
6502 Avatar answered Oct 23 '22 07:10

6502


An example on how to do this is given on the cppreference.com std::string::replace page:

std::string& replaceAll(std::string& context, std::string const& from, std::string const& to)
{
    std::size_t lookHere = 0;
    std::size_t foundHere;
    while((foundHere = context.find(from, lookHere)) != std::string::npos)
    {
          context.replace(foundHere, from.size(), to);
          lookHere = foundHere + to.size();
    }
    return context;
}
like image 32
ildjarn Avatar answered Oct 23 '22 08:10

ildjarn


std::string::replace

like image 36
Dr McKay Avatar answered Oct 23 '22 07:10

Dr McKay


To replace all the occurences of a sub-string in a string by another sub-string:

#include <iostream>

void replace_all(std::string& input, const std::string& from, const std::string& to) {
  size_t pos = 0;
  while ((pos = input.find(from, pos)) != std::string::npos) {
    input.replace(pos, from.size(), to);
    pos += to.size();
  }
}

int main() {
  std::string str("i am a geek/nerd/crazy person.");
  replace_all(str, "/", "\\/");
  std::cout << str << '\n';
}

Output:

$ g++-6.1.0 -std=c++17 -g -Og -Werror -Wall -Wextra -pedantic -Wold-style-cast -Wnon-virtual-dtor -Wshadow -Wcast-align -Wunused -Woverloaded-virtual -Wconversion -Wsign-conversion -Wmisleading-indentation -fsanitize=address,leak,undefined; ./a.out
i am a geek\/nerd\/crazy person.
like image 28
Christophe Saugé Avatar answered Oct 23 '22 07:10

Christophe Saugé