将具有显式转义序列的字符串转换为相对字符

时间:2011-04-10 13:52:43

标签: c++ escaping

我需要一个函数将“显式”转义序列转换为相对不可打印的字符。 ES:

char str[] = "\\n";
cout << "Line1" << convert_esc(str) << "Line2" << endl:

会给出这个输出:

Line1

Line2

有没有这样做的功能?

5 个答案:

答案 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; } 时检查以下字符。如果它是合法的转义之一,你应该用相应的字符替换它们,否则跳过或保留原样。

http://ideone.com/BvcDE):

{{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;
   }