用于转义字符串的标准c库

是否有标准的C库函数来转义C字符串?

例如,如果我有C字符串:

char example[] = "first line\nsecond line: \"inner quotes\""; 

我想要打印

 "first line\nsecond line: \"inner quotes\"" 

是否有一个库函数可以为我做这个转换? 滚动我自己似乎有点傻。

奖励积分,如果我可以给它一个长度逃脱(所以它停止在\0之前或之外)。

如果您正在编写GPL内容,可以使用http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/quotearg.c;hb=HEAD

这没有标准的C库函数。

当您使用声明时

 char example[] = "first line\nsecond line: \"inner quotes\""; 

转义序列将由编译器解释和替换。 你将不得不“解释”C逃脱的角色。 这是一个快速的例子:

 #include  #include  void print_unescaped(char* ptr, int len) { if (!ptr) return; for (int i = 0; i < len; i++, ptr++) { switch (*ptr) { case '\0': printf("\\0"); break; case '\a': printf("\\a"); break; case '\b': printf("\\b"); break; case '\f': printf("\\f"); break; case '\n': printf("\\n"); break; case '\r': printf("\\r"); break; case '\t': printf("\\t"); break; case '\v': printf("\\v"); break; case '\\': printf("\\\\"); break; case '\?': printf("\\\?"); break; case '\'': printf("\\\'"); break; case '\"': printf("\\\""); break; default: if (isprint(*ptr)) printf("%c", *ptr); else printf("\\%03o", *ptr); } } } 

您刚才提到要打印字符串。

 char example[] = "first line\nsecond line: \"inner quotes\""; size_t len = strlen(example); size_t i; static const char *simple = "\\\'\""; static const char *complex = "\a\b\f\n\r\t\v"; static const char *complexMap = "abfnrtv"; for (i = 0; i < length; i++) { char *p; if (strchr(simple, example[i])) { putchar('\\'); putchar(example[i]); } else if ((p = strchr(complex, example[i])) { size_t idx = p - complex; putchar('\\'); putchar(complexMap[idx]); } else if (isprint(example[i])) { putchar(example[i]); } else { printf("\\%03o", example[i]); } } 

没有标准的Cfunction,但不是很难自己滚动

没什么太漂亮但是: –

 void escape_str(char *dest, char *src) { *dest = 0; while(*src) { switch(*src) { case '\n' : strcat(dest++, "\\n"); break; case '\"' : strcat(dest++, "\\\""); break; default: *dest = *src; } *src++; *dest++; *dest = 0; } } 
 #include  /* int c_quote(const char* src, char* dest, int maxlen) * * Quotes the string given so that it will be parseable by ac compiler. * Return the number of chars copied to the resulting string (including any nulls) * * if dest is NULL, no copying is performed, but the number of chars required to * copy will be returned. * * maxlen characters are copied. If maxlen is negative, * strlen is used to find the length of the source string, and the whole string * including the NULL-terminator is copied. * * Note that this function will not null-terminate the string in dest. * If the string in src is not null-terminated, or maxlen is specified to not * include the whole src, remember to null-terminate dest afterwards. * */ int c_quote(const char* src, char* dest, int maxlen) { int count = 0; if(maxlen < 0) { maxlen = strlen(src)+1; /* add 1 for NULL-terminator */ } while(src && maxlen > 0) { switch(*src) { /* these normal, printable chars just need a slash appended */ case '\\': case '\"': case '\'': if(dest) { *dest++ = '\\'; *dest++ = *src; } count += 2; break; /* newlines/tabs and unprintable characters need a special code. * Use the macro CASE_CHAR defined below. * The first arg for the macro is the char to compare to, * the 2nd arg is the char to put in the result string, after the '\' */ #define CASE_CHAR(c, d) case c:\ if(dest) {\ *dest++ = '\\'; *dest++ = (d);\ }\ count += 2;\ break; /* -------------- */ CASE_CHAR('\n', 'n'); CASE_CHAR('\t', 't'); CASE_CHAR('\b', 'b'); /* ------------- */ #undef CASE_CHAR /* by default, just copy the char over */ default: if(dest) { *dest++ = *src; } count++; } ++src; --maxlen; } return count; } 

我觉得我之前的回答是作弊,因为写入缓冲区的函数比只写入stdout的函数更有用,所以这里有一个替代解决方案,可以计算出dstNULL需要多少内存,并且还停止在根据要求dstLen

所有if(dst)检查都可能有点效率低下。

 #include  #include  #include  size_t str_escape(char *dst, const char *src, size_t dstLen) { const char complexCharMap[] = "abtnvfr"; size_t i; size_t srcLen = strlen(src); size_t dstIdx = 0; // If caller wants to determine required length (supplying NULL for dst) // then we set dstLen to SIZE_MAX and pretend the buffer is the largest // possible, but we never write to it. Caller can also provide dstLen // as 0 if no limit is wanted. if (dst == NULL || dstLen == 0) dstLen = SIZE_MAX; for (i = 0; i < srcLen && dstIdx < dstLen; i++) { size_t complexIdx = 0; switch (src[i]) { case '\'': case '\"': case '\\': if (dst && dstIdx <= dstLen - 2) { dst[dstIdx++] = '\\'; dst[dstIdx++] = src[i]; } else dstIdx += 2; break; case '\r': complexIdx++; case '\f': complexIdx++; case '\v': complexIdx++; case '\n': complexIdx++; case '\t': complexIdx++; case '\b': complexIdx++; case '\a': if (dst && dstIdx <= dstLen - 2) { dst[dstIdx++] = '\\'; dst[dstIdx++] = complexCharMap[complexIdx]; } else dstIdx += 2; break; default: if (isprint(src[i])) { // simply copy the character if (dst) dst[dstIdx++] = src[i]; else dstIdx++; } else { // produce octal escape sequence if (dst && dstIdx <= dstLen - 4) { dst[dstIdx++] = '\\'; dst[dstIdx++] = ((src[i] & 0300) >> 6) + '0'; dst[dstIdx++] = ((src[i] & 0070) >> 3) + '0'; dst[dstIdx++] = ((src[i] & 0007) >> 0) + '0'; } else { dstIdx += 4; } } } } if (dst && dstIdx <= dstLen) dst[dstIdx] = '\0'; return dstIdx; } 
 while(*src++) { if(*src == '\\' || *src == '\"' || *src == '\'') *dest++ = '\\'; *dest++ = *src++; }