Reputation: 952
I need a function to convert "explicit" escape sequences into the relative non-printable character. Es:
char str[] = "\\n";
cout << "Line1" << convert_esc(str) << "Line2" << endl:
would give this output:
Line1
Line2
Is there any function that does this?
Upvotes: 14
Views: 19042
Reputation: 54899
Here's a cute way to do it on Unixy platforms.
It calls the operating system's echo
command to make the conversion.
string convert_escapes( string input )
{
string buffer(input.size()+1,0);
string cmd = "/usr/bin/env echo -ne \""+input+"\"";
FILE * f = popen(cmd.c_str(),"r"); assert(f);
buffer.resize(fread(&buffer[0],1,buffer.size()-1,f));
fclose(f);
return buffer;
}
Upvotes: 0
Reputation: 1464
You can do that fairly easy, using the boost string algorithm library. For example:
#include <string>
#include <iostream>
#include <boost/algorithm/string.hpp>
void escape(std::string& str)
{
boost::replace_all(str, "\\\\", "\\");
boost::replace_all(str, "\\t", "\t");
boost::replace_all(str, "\\n", "\n");
// ... add others here ...
}
int main()
{
std::string str = "This\\tis\\n \\\\a test\\n123";
std::cout << str << std::endl << std::endl;
escape(str);
std::cout << str << std::endl;
return 0;
}
This is surely not the most efficient way to do this (because it iterates the string multiple times), but it is compact and easy to understand.
Update: As ybungalobill has pointed out, this implementation will be wrong, whenever a replacement string produces a character sequence, that a later replacement is searching for or when a replacement removes/modifies a character sequence, that should have been replaced.
An example for the first case is "\\\\n"
-> "\\n"
-> "\n"
. When you put the "\\\\"
-> "\\"
replacement last (which seems to be the solution at a first glance), you get an example for the latter case "\\\\n"
-> "\\\n"
. Obviously there is no simple solution to this problem, which makes this technique only feasible for very simple escape sequences.
If you need a generic (and more efficient) solution, you should implement a state machine that iterates the string, as proposed by davka.
Upvotes: 5
Reputation: 14692
I think that you must write such function yourself since escape characters is a compile-time feature, i.e. when you write "\n"
the compiler would replace the \n
sequence with the eol character. The resulting string is of length 1 (excluding the terminating zero character).
In your case a string "\\n"
is of length 2 (again excluding terminating zero) and contains \
and n
.
You need to scan your string and when encountering \
check the following char. if it is one of the legal escapes, you should replace both of them with the corresponding character, otherwise skip or leave them both as is.
string unescape(const string& s)
{
string res;
string::const_iterator it = s.begin();
while (it != s.end())
{
char c = *it++;
if (c == '\\' && it != s.end())
{
switch (*it++) {
case '\\': c = '\\'; break;
case 'n': c = '\n'; break;
case 't': c = '\t'; break;
// all other escapes
default:
// invalid escape sequence - skip it. alternatively you can copy it as is, throw an exception...
continue;
}
}
res += c;
}
return res;
}
Upvotes: 15
Reputation: 385194
I'm sure that there is, written by someone, but it's so trivial that I doubt it's been specifically published anywhere.
Just recreate it yourself from the various "find"/"replace"-esque algorithms in the standard library.
Upvotes: 1