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

时间:2010-08-20 21:30:10

标签: c escaping

我需要this post中的字符串ToLiteral(字符串输入)这样的函数。这样

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

会产生文字==> “ASDF \\ř\\ N”即可。

我已经搜索过了,但却找不到任何东西(猜测我必须使用错误的条款)。但是,我认为具有此功能的库必须在某处...

感谢有趣的答案。谷歌搜索“c字符串转义函数”似乎是获得更多示例的关键,GLIB提供了g_strescape(),这似乎正是我所需要的。

3 个答案:

答案 0 :(得分:8)

没有内置功能,但你可以鞭打一个:

/* 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 */
}

请注意,我已经省略了“转义”字符的转义序列的转换,因为这在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;
}

答案 1 :(得分:1)

我想我会做这样的转换:

// 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';
}

理论上,这可能比Tyler McHenry的代码慢一点(例如)。特别是,他使用switch语句允许(但不要求)正确路径的恒定时间选择。实际上,考虑到所涉及的值的稀疏性,您可能无法获得恒定的时间选择,并且所涉及的字符串非常短,以至于差异通常在任何情况下都非常小。在另一个方向,我希望这更容易维护(例如,如果你想支持更多的转义序列,只要形式保持不变,添加它们应该很容易)。 / p>

答案 2 :(得分:0)

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

char *literal = "asdf\r\n"

修正案但是,C Strings能够使用转义引号,例如:

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

那将打印出来

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

根据控制台功能,这些字符不会显示,您可能会看到转义的箭头和选项卡的间距......您可以使用一个简单的逻辑来解决这个问题,每{{1} }遇到,插入另一个\,使其显示

\

类似下面的代码就足够了:

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