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
?
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.
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.
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, "/", "\\/");
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 >
or characters not in printable range with %xx
encoding) still maintaining a good efficiency for big strings (just one pass).
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;
}
std::string::replace
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With