стандартная библиотека 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\""; 

escape-последовательности будут интерпретироваться и заменяться компилятором. Вам придется «не интерпретировать» символы, которые 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]); } } 

Нет стандартной функции C, но не слишком сложно катить

ничего слишком красивого, но: –

 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; } } в 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 , поэтому вот альтернативное решение, которое определяет, сколько памяти нужно, если dst равно NULL , а также останавливается на 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++; } в while(*src++) { if(*src == '\\' || *src == '\"' || *src == '\'') *dest++ = '\\'; *dest++ = *src++; }