我需要一个函数将“显式”转义序列转换为相对不可打印的字符。 ES:
char str[] = "\\n";
cout << "Line1" << convert_esc(str) << "Line2" << endl:
会给出这个输出:
Line1
Line2
有没有这样做的功能?
答案 0 :(得分:14)
我认为你必须自己编写这样的函数,因为转义字符是编译时功能,即当你编写"\n"
时,编译器将用\n
替换"\\n"
序列。 eol角色。结果字符串的长度为 (不包括终止的零字符)。
在您的情况下,字符串\
长度为2 (同样不包括终止为零)并包含n
和\
。
您需要扫描字符串,并在遇到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;
}
时检查以下字符。如果它是合法的转义之一,你应该用相应的字符替换它们,否则跳过或保留原样。
{{1}}
答案 1 :(得分:4)
使用boost字符串算法库,您可以非常轻松地完成此操作。例如:
#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;
}
这肯定不是最有效的方法(因为它多次迭代字符串),但它很紧凑,易于理解。
更新: 正如ybungalobill指出的那样,每当替换字符串产生一个字符序列,后来的替换正在搜索或替换删除/修改一个应该被替换的字符序列时,这个实现都是错误的。
第一种情况的一个例子是"\\\\n"
- &gt; "\\n"
- &gt; "\n"
。当您放置"\\\\"
- &gt;最后替换"\\"
(乍一看似乎是解决方案),你得到后一种情况的例子"\\\\n"
- &gt; "\\\n"
。显然,这个问题没有简单的解决方案,这使得这种技术仅适用于非常简单的转义序列。
如果您需要通用(且更有效)的解决方案,则应该按照davka的建议实现迭代字符串的状态机。
答案 2 :(得分:1)
我确信有人写的,但它是如此微不足道,我怀疑它是在任何地方专门发布的。
只需从标准库中的各种“find”/“replace”-esque算法中重新创建它。
答案 3 :(得分:0)
你考虑过使用printf吗? (或其亲属之一)
答案 4 :(得分:0)
在Unixy平台上,这是一种可爱的方式。
它调用操作系统的echo
命令进行转换。
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;
}