【问题标题】:Rules for C++ string literals escape characterC++ 字符串文字转义字符的规则
【发布时间】:2012-04-30 12:20:53
【问题描述】:

字符串文字中转义字符\的规则是什么?是否有所有转义字符的列表?

特别是,当我在 gedit 的字符串文字中使用 \ 并在其后跟任意三个数字时,它们的颜色会不同。

我试图创建一个 std::string,它由字符 0 后跟空字符 (\0) 和字符 0 构成。但是,语法突出显示提醒我,这可能会创建类似于字符0 后跟空字符(\00,又名\0),也就是说,只有两个字符。

对于这一个问题的解决方案,这是最好的方法吗:

std::string ("0\0" "0", 3)  // String concatenation 

一般来说,转义字符在字符串文字中的作用是否有一些参考?例如,'\a' 是什么?

【问题讨论】:

  • 相关,关于如何escape an escape sequence。最好的解决方案是像以前一样使用串联。
  • 如果您需要单个` just use \`。
  • 看来我也可以使用初始化列表语法:std::string { '0', 0, '0' };
  • 我不仅可以使用初始化列表语法,而且我现在强烈推荐它,而不是任何其他需要您指定大小或使用转义字符的构造字符串的方法。考虑stackoverflow.com/questions/164168/… 中概述的微妙的未定义行为
  • 我现在意识到我在 1:32 的评论完全被混淆了......我不知道我的意思......

标签: c++ string escaping


【解决方案1】:

控制字符:

(十六进制代码假定与 ASCII 兼容的字符编码。)

  • \a = \x07 = 警报(铃声)
  • \b = \x08 = 退格
  • \t = \x09 = 水平制表符
  • \n = \x0A = 换行(或换行)
  • \v = \x0B = 垂直制表符
  • \f = \x0C = 换页
  • \r = \x0D = 回车
  • \e = \x1B = 转义(非标准 GCC 扩展)

标点符号:

  • \" = 引号('"' 不需要反斜杠)
  • \' = 撇号("'" 不需要反斜杠)
  • \? = 问号(用于避免使用三元组)
  • \\ = 反斜杠

数字字符引用:

  • \ + 最多 3 个八进制数字
  • \x + 任意数量的十六进制数字
  • \u + 4 个十六进制数字(Unicode BMP,C++11 中的新功能)
  • \U + 8 个十六进制数字(Unicode 星体平面,C++11 中的新功能)

\0 = \00 = \000 = 空字符的八进制转义符

如果您确实想要在 \0 之后添加一个实际的数字字符,那么是的,我建议使用字符串连接。注意文字部分之间的空格是可选的,所以你可以写"\0""0"

【讨论】:

  • \x 的情况下,十六进制数字将被“贪婪地”读取,直到第一个非十六进制数字(也就是说,不限于您可能期望的 2,以及一些语法高亮显示假设)。您可以使用@dan04 拆分字符串的技巧来标记十六进制的结尾:"\x0020" "FeedDadBeer" 而不是"\x0020FeedDadBeer"
  • 那么\x后面跟奇数个十六进制代表什么?假设对于偶数,每个十六进制表示从最高到最低顺序的一小块内存——因此\x5f01011111 而不是11110101;但这是否意味着\x501010000 而不是00000101?那么\x5f5呢?是01011111 01010000 还是01011111 00000101
  • 我不知道这是否会验证它自己的问题,但我从某个来源收到了带有"\e" 的字符串数据。我没有在任何参考文献中看到它,它是否等同于\x1B
  • @StijnSanders:它不在 C 或 C++ 标准中,但一些编译器使用 \e 来表示转义字符 \x1B。我已将其添加到我的列表中。
  • 您能否提供有关\u\U 用法的参考?它有效,我对它很感兴趣,而 C++ Primer 5th 没有提及它们。我只能找到一两个关于 SO 的问答。
【解决方案2】:

\0 如果后跟其他数字,将被解释为八进制转义序列,因此 \00 将被解释为单个字符。 (\0 在技术上也是一个八进制转义序列,至少在 C 中是这样)。

你的做法:

std::string ("0\0" "0", 3)  // String concatenation 

之所以有效,是因为这个版本的构造函数需要一个 char 数组;如果您尝试将“0\0”“0”作为 const char* 传递,它会将其视为 C 字符串,并且只会复制所有内容,直到出现空字符。

这是list of escape sequences

【讨论】:

    【解决方案3】:

    \a 是铃声/警报字符,在某些系统上会触发声音。 \nnn,表示以八进制为基数的任意 ASCII 字符。但是,\0 的特殊之处在于它无论如何都表示空字符。

    要回答您的原始问题,您也可以转义您的“0”字符,如:

    std::string ("\060\000\060", 3);
    

    (因为 ASCII '0' 是八进制的 60)

    MSDN documentation 有一篇非常详细的文章,还有cppreference

    【讨论】:

    • 该示例使用构造函数字符串 (const char * s),它将 s 视为 C 字符串。 OP 的示例使用字符串 (const char * s, size_t n),它将其视为字符数组。
    【解决方案4】:

    我留下了这样的评论作为评论,但我觉得它可能需要更多的可见性,因为没有一个答案提到这种方法:

    我现在更喜欢用非打印字符(尤其是嵌入的空字符)初始化std::string 的方法是使用初始化列表的 C++11 特性。

    std::string const str({'\0', '6', '\a', 'H', '\t'});
    

    我不需要对我正在使用的字符数进行容易出错的手动计数,因此如果以后我想在中间的某个地方插入一个“\013”,我可以和我的所有代码仍然可以工作。它还完全避免了意外使用错误转义序列的任何问题。

    唯一的缺点是所有这些额外的 ', 字符。

    【讨论】:

      【解决方案5】:

      借助用户定义文字的魔力,我们还有另一种解决方案。 C++14 添加了std::string 文字运算符。

      using namespace std::string_literals;
      auto const x = "\0" "0"s;
      

      构造一个长度为 2 的字符串,其中包含一个 '\0' 字符(null),后跟一个 '0' 字符(数字零)。我不确定它是否比initializer_list<char> constructor approach 更清晰,但它至少摆脱了', 字符。

      【讨论】:

        【解决方案6】:

        ascii 是一个可以下载的 Linux 软件包。 例如 sudo apt-get install ascii ascii

        Usage: ascii [-dxohv] [-t] [char-alias...]
        -t = one-line output  -d = Decimal table  -o = octal table  -x = hex table
        -h = This help screen -v = version information
        Prints all aliases of an ASCII character. Args may be chars, C \-escapes,
        English names, ^-escapes, ASCII mnemonics, or numerics in decimal/octal/hex.`
        

        此代码可以帮助您使用 C/C++ 转义码,例如 \x0A

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-10-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-02-24
          • 2016-10-08
          • 1970-01-01
          相关资源
          最近更新 更多