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

将c字符串中的字符转换为其转义序列,c,escaping,C,Escaping,我需要一个类似于字符串ToLiteral(字符串输入)from的函数。以致 char *literal = to_literal("asdf\r\n"); 将产生文本==>“asdf\\r\\n” 我在谷歌上搜索过,但没有找到任何东西(我猜我一定用错了词)。但是,我假设一个具有此功能的库一定在某个地方 谢谢你的问答。顺便说一句,谷歌搜索“c字符串转义函数”似乎是获得更多示例的关键,GLIB提供了g_strescape(),这似乎正是我所需要的。我认为你混淆了术语,你可以像这样初始化指向char

我需要一个类似于字符串ToLiteral(字符串输入)from的函数。以致

char *literal = to_literal("asdf\r\n");
将产生文本==>“asdf\\r\\n”

我在谷歌上搜索过,但没有找到任何东西(我猜我一定用错了词)。但是,我假设一个具有此功能的库一定在某个地方


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

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

char *literal = "asdf\r\n"
// 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';
}
修改:但是,C字符串可以使用转义引号,例如:

char *literal = "\basdf\x1b\r\n\v\t";
那会打印出来的

<backspace>asdf<escape-character><carriage-return><linefeed><vertical-tab><tab>
类似于以下代码的代码就足够了:

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

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

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

我想我应该做这样的转换:

char *literal = "asdf\r\n"
// 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语句的使用允许(但不要求)对正确路径进行恒定时间的选择。实际上,考虑到所涉及的值的稀疏性,您可能无法获得恒定时间选择,而且所涉及的字符串非常短,因此在任何情况下,差异通常都非常小。另一方面,我希望这更容易维护(例如,如果您想支持更多转义序列,只要表单保持不变,添加它们应该非常容易)。

查看参考文章,我认为这并不能回答他的问题。他想将“asdf\r\n”之类的字符串转换为一个字符串,该字符串将生成字符串“asdf\\r\\n”的预期输出。是的,这是真的,但查看他正在引用的帖子。他显然想把标签和换行符之类的东西转换成各自的转义序列,我想是这样的:“Hello\nworld”=>“Hello\\nworld”警告清空者:我承认代码并不完全是傻瓜式的-这是我的想法。。。所以小心点!:)“字符串文字”不是这里要使用的正确短语。您需要的是一个函数,该函数可以转换字符串,使具有C转义序列的字符替换为这些序列。
literal==“asdf\r\n”
永远不会为真。我猜您的意思是strcmp(字面意思是“asdf\\r\\n”)==0。否。Literal==“asdf\\r\\n”因为to\u Literal应将“asdf\r\n”转换为“asdf\\r\\n”。但是,从答案中,我了解到更好的函数名(在c中)应该是char*escape(char*)。post first read literal==“asdf\r\n”(这是错误的)的原因是stackoverflow出于某种原因将带引号的\\r转换为\r。现在通过编写\\\\r.all来修复它,以便于调用方调用错误-我将malloc结果并返回它这是另一种编写方法,但几乎所有的C标准库字符串函数都是这样编写的。这可能对
expand\u escapes()很友好
将任何其他非打印字符编码为八进制转义。将常用ASCII ESC字符处理为
\033
。当然,您的输出缓冲区的大小可能是输入的4倍,因此在返回之前分配realloc的大小可能是有意义的。您还可以使用长度参数处理嵌入的NUL字符,其中负长度意味着在第一个NUL处停止。所有这些都是好主意,但我将把其中的一些作为练习留给OP.;)(提示:您可以使用
ctype.h
中的
isprint
功能来确定字符是否可打印)我现在将详细信息留作练习。。。我只是觉得它们值得一提,因为我对其他字符串转义逻辑感到恼火,这些逻辑只做了最少的工作,实际上并没有给您一些可以安全地打印在终端上或粘贴到C源文件中的内容。“以下两个数组必须以匹配的顺序维护”-所以用
{}初始化它们
语法,并垂直排列相应的条目;-)