【问题标题】:How to convert a c string into its escaped version in c?如何将c字符串转换为c中的转义版本?
【发布时间】:2010-07-08 07:27:08
【问题描述】:

是否有任何内置函数或替代的简单快速的方法来转义 C 字符数组,如果与例如 printf 一起使用应该再次产生原始字符数组。

char* str = "\tHello World\n";
char* escaped_str = escape(str); //should contain "\tHello World\n" with char \ ,t.
printf(escaped_str); //should print out [TAB]Hello World[nextline] similar to if str was printed.

c 中有没有一种简单的方法可以用 c 转义字符转义字符串。

更新

我有一个包含带有转义字符的字符串的缓冲区。我想包含在一个 C 文件中。为此,我需要将其转义,以便可以遵守。我只需要知道是否有简单的方法来代替扫描缓冲区以查找 \n \t 等并在那里生成 c 转义字符。

for(int i=0; i< strlen(buffer);i++)
    if(buffer[i]=='\n')
      sprintf(dest,"\\n")
    else ....

更新 2

我写了这个函数。它工作正常。

char* escape(char* buffer){
    int i,j;
    int l = strlen(buffer) + 1;
    char esc_char[]= { '\a','\b','\f','\n','\r','\t','\v','\\'};
    char essc_str[]= {  'a', 'b', 'f', 'n', 'r', 't', 'v','\\'};
  char* dest  =  (char*)calloc( l*2,sizeof(char));
    char* ptr=dest;
    for(i=0;i<l;i++){
        for(j=0; j< 8 ;j++){
            if( buffer[i]==esc_char[j] ){
              *ptr++ = '\\';
              *ptr++ = essc_str[j];
                 break;
            }
        }
        if(j == 8 )
      *ptr++ = buffer[i];
    }
  *ptr='\0';
    return dest;
}

【问题讨论】:

  • 我很好奇:printf("%s", str); 怎么了? ?
  • 不,我需要转义字符串。这只是一个例子。
  • 查看编译器将 \t \n 等转换为 ascii 等价物。我有我需要转义的 ascii 字符串。
  • 您是否正在寻找一种方法来生成要包含在 C 源代码中的字符串?正如@Ben 回答的那样,printf() 与反斜杠转义无关。
  • 您应该在下面发布自己的解决方案作为答案,以便可以像其他答案一样对其进行投票,而不是将其编辑到您的问题中。 (此外,您的解决方案无法正确转义任意控制字​​符,例如 '\4''\177'。)

标签: c


【解决方案1】:

不,没有任何标准函数可用于创建字符串的源代码版本。但是您可以使用iscntrl 函数来编写一个,或者只使用switch 关键字。

但是,除非您的程序写出旨在通过编译器运行的 C 源文件,否则您不需要使用转义字符串。 printf 不处理字符转义序列,只处理变量插入(%d%s 等)

具体来说,以下产生相同的输出:

printf("\tHello World\n");

const char* str = "\tHello World\n";
printf(str);

const char* str = "\tHello World\n";
printf("%s", str);

第二个不是一个好主意,因为如果 str 包含 % 您的程序会产生错误的输出并可能崩溃。

编辑:为了生成源代码版本,有几种方法:

更简单,但可读性较差的输出:

if (iscntrl(ch) || ch == '\\' || ch == '\"' || ch == '\'') {
   fprintf(outf, "\\%03o", ch);
}
else
   fputc(ch, outf);

更具可读性的结果:

switch (ch) {
  case '\"':
    fputs("\\\"", outf);
    break;
  case '\'':
    fputs("\\\'", outf);
    break;
  case '\\':
    fputs("\\\\", outf);
    break;
  case '\a':
    fputs("\\a", outf);
    break;
  case '\b':
    fputs("\\b", outf);
    break;
  case '\n':
    fputs("\\n", outf);
    break;
  case '\t':
    fputs("\\t", outf);
    break;
  // and so on
  default:
    if (iscntrl(ch)) fprintf(outf, "\\%03o", ch);
    else fputc(ch, outf);
}

【讨论】:

  • 是的,这会起作用。与此同时,我也写了自己的。检查一下逻辑与你的非常相似。但它打印出实际的 \n 而不是十六进制等价物。但您的第二个解决方案非常相似
  • 我们都忽略了"',如果你忘记转义它们,编译器会很困惑。现在在我的示例中修复。
  • @Fraxtil:感谢您发现错误的参数顺序。为什么哦为什么标准库不能一致地将流放在开头或结尾。 (我猜它是可变参数函数的开头,而几乎所有其他函数的结尾?)无论如何,抱歉我没有及时看到您的建议接受它;这是正确的。
  • 如果您使用十六进制转义序列和未转义的十六进制数字,请小心。 strlen("\x0123456789abcdef")1
  • isctrl -&gt; iscntrl 如提到的here
【解决方案2】:

如果您不要求生成的字符串是人类可读的,并且您的编译时字符集与您的执行字符集相同,那么最简单的方法是使用代码点逃避一切:

int print_string_literal(char *s)
{
    putchar('\"');

    while (*s)
    {
        unsigned cp = (unsigned char)*s++;
        printf("\\x%.2x", cp);
    }

    putchar('\"');
}

您可以对此进行一些处理以生成更好看的字符串,但您确实要求简单...

【讨论】:

  • 我认为使用“(unsigned char)*s++”是错误的。字符串不一定存储在一个大的顺序内存块中。它可以分成几个块存储在不同的内存位置,所以你不能简单地增加指针。
  • @papajony:一个普通的C字符串存储在一个大的顺序内存块中。除了在讨论 C 时除非另有说明,否则假定这种字符串是假定的,我们还知道这就是提问者的想法,因为他们在示例中使用了普通的字符串文字 printf()strlen()
  • 对不起,你不能假设这个。如果您使用 malloc 分配一个字符串,则不能保证它将位于一个连续的内存块中。这取决于操作系统的内存管理。
  • @papajony:你错了。无论幕后发生什么,实现都必须使其显示为一个连续的块。这源于malloc() 和加法运算符的定义,因为它们适用于 C 标准中的指针类型。
【解决方案3】:

如果您要生成一个用作 C 源文件的一部分的字符串,那么引用是相当复杂的(您必须处理换行符、其他几个控制字符、引号、反斜杠等)。使用字符串只是类似整数值的数组这一事实更快更容易 - 而不是

char generated_file_str[] = "ABC\n\";

生成

char generated_file_str[] = {65,66,67,10,0};

这很容易写 - 类似于:

printf("char generated_string[] = {");
for (i = 0; i < length; i++) {
    printf("%d, ", str[i]);
}
printf("0};\n");

【讨论】:

    【解决方案4】:

    您需要做的唯一转义是将每次出现的“%”替换为“%%”; "%" 是 printf 特殊处理的 ONLY 字符。 "\" 转义与 printf 无关;它们是 C 编译器对字符串文字的编译时处理的一部分。

    【讨论】:

    • 随着您的问题的更新描述(您试图转义字符串以用于 C 源代码,而不是用于 printf)我的答案不是那么有用。
    【解决方案5】:

    请在printf查看论文

    您需要了解有关转义序列的更多信息。

    【讨论】:

    • 论文具有误导性。整个第一页和第二页的一部分与 printf 无关,而是与 C 编译器和字符串文字有关。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-28
    • 1970-01-01
    • 2011-04-01
    • 1970-01-01
    • 2011-02-03
    相关资源
    最近更新 更多