代码之家  ›  专栏  ›  技术社区  ›  Christian Madsen

将C字符串中的字符转换为转义序列

  •  5
  • Christian Madsen  · 技术社区  · 14 年前

    我需要一个像 字符串toliteral(字符串输入) this post . 这样

    char *literal = to_literal("asdf\r\n");
    

    会屈服 literal==>“asdf\\r\\n” .

    我到处搜索,但找不到任何东西(我猜我一定用错了词)。但是,我假设具有此功能的库必须存在于某个地方…

    感谢您提供相关的答案。顺便说一下,谷歌搜索“c字符串转义函数”似乎是获得更多示例的关键,glib提供了g_strescape(),这正是我需要的。

    3 回复  |  直到 14 年前
        1
  •  8
  •   Tyler McHenry    14 年前

    这没有内置的功能,但您可以创建一个:

    /* Expands escape sequences within a C-string
     *
     * src must be a C-string with a NUL terminator
     *
     * dest should be long enough to store the resulting expanded
     * string. A string of size 2 * strlen(src) + 1 will always be sufficient
     *
     * NUL characters are not expanded to \0 (otherwise how would we know when
     * the input string ends?)
     */
    
    void expand_escapes(char* dest, const char* src) 
    {
      char c;
    
      while (c = *(src++)) {
        switch(c) {
          case '\a': 
            *(dest++) = '\\';
            *(dest++) = 'a';
            break;
          case '\b': 
            *(dest++) = '\\';
            *(dest++) = 'b';
            break;
          case '\t': 
            *(dest++) = '\\';
            *(dest++) = 't';
            break;
          case '\n': 
            *(dest++) = '\\';
            *(dest++) = 'n';
            break;
          case '\v': 
            *(dest++) = '\\';
            *(dest++) = 'v';
            break;
          case '\f': 
            *(dest++) = '\\';
            *(dest++) = 'f';
            break;
          case '\r': 
            *(dest++) = '\\';
            *(dest++) = 'r';
            break;
          case '\\': 
            *(dest++) = '\\';
            *(dest++) = '\\';
            break;
          case '\"': 
            *(dest++) = '\\';
            *(dest++) = '\"';
            break;
          default:
            *(dest++) = c;
         }
      }
    
      *dest = '\0'; /* Ensure nul terminator */
    }
    

    注意,我省略了“escape”字符转义序列的翻译,因为这在C语言中没有标准化(一些编译器使用 \e 其他使用 \x )您可以添加任何适用于您的内容。

    如果需要为您分配目标缓冲区的函数:

    /* Returned buffer may be up to twice as large as necessary */
    char* expand_escapes_alloc(const char* src)
    {
       char* dest = malloc(2 * strlen(src) + 1);
       expand_escapes(dest, src);
       return dest;
    }
    
        2
  •  1
  •   Jerry Coffin    14 年前

    我想我会做这样的转换:

    // warning: untested code.
    void make_literal(char const *input, char *output) { 
        // the following two arrays must be maintained in matching order:
        static char inputs[] = "\a\b\f\n\r\t\v\\\"\'";
        static char outputs[] = "abfnrtv\\\"\'";
    
        char *p, *pos;
    
        for (;*input;input++) {
            if (NULL!= (pos=strchr(inputs, *input))) {
                *output++ = '\\';
                *output++ = outputs[pos-inputs];
            }
            else
                *output++ = *input;
        }
        *output = '\0';
    }
    

    理论上,这可能比(例如)泰勒·麦克亨利的代码慢一点。特别是,他使用switch语句可以(但不需要)持续选择正确路径。实际上,考虑到所涉及的值的稀疏性,您可能无法获得恒定的时间选择,而且所涉及的字符串非常短,因此在任何情况下,差异通常都非常小。在另一个方向上,我希望这样更容易维护(例如,如果您希望支持更多的转义序列,那么添加它们应该非常容易,只要 形式 保持不变)。

        3
  •  0
  •   t0mm13b    14 年前

    我认为您混淆了术语,可以这样初始化指向char(acter)的指针:

    char *literal = "asdf\r\n"
    

    修正案: 但是,C字符串可以使用转义引号,例如:

    char *literal = "\basdf\x1b\r\n\v\t";
    

    那就打印出来

    <backspace>asdf<escape-character><carriage-return><linefeed><vertical-tab><tab>
    

    根据控制台的功能,这些字符将不会显示,您可能会看到转义箭头,以及选项卡的间距…你可以通过使用一个简单的逻辑来解决这个问题, \ 遇到,插入另一个 \ 以便显示

    asdf\\r\\n
    

    类似下面的代码应该足够了:

    void ToLiteral(const char *pStr){
        char *p = (char*)pStr;
        while (*p){
           /* if (*p == '\\') putchar('\\');  */
           /* PERFORM THE LOOK UP */
           putchar(*p++);
        }
    }
    

    但是看着它,它感觉不太对劲,因为指针正握着 \n \r 因此,使用查找表比较转义序列的实际十六进制代码并显示适当的代码可能更容易…查阅表格可以是这样的

    struct LookUp{
        int codeLiteral;
        char *equivCodeLiteral;
    };
    
    struct LookUp look[] = { { 0xa, "\\r"}, { 0xd, "\\n" }, { 0x9, "\\t" } };