Y a-t-il une fonction de bibliothèque C standard C pour échapper aux chaînes C?
Par exemple, si j'avais la chaîne C: p> et je voulais imprimer < / p> existe une fonction de bibliothèque qui fera cette transformation pour moi? Rouler mon propre semble juste un peu stupide. P> points bonus si je peux lui donner une longueur pour s'échapper (il s'arrête donc avant ou au-delà du \ 0 code>). P> p>
7 Réponses :
Pas de fonction C standard, mais pas trop difficile à rouler votre propre
rien de trop jolie mais: - p>
while(*src++) { if(*src == '\\' || *src == '\"' || *src == '\'') *dest++ = '\\'; *dest++ = *src++; }
Ce code manque \ r \ n \ f \ a \ b \ t et autres manipulations non empreintes
N'oubliez pas de citations doubles en tête et de fin, vérifiant isprint () code> et produisant des échappes appropriées pour les non-imprimables et espaces communs (
\ n code>,
\ t Code>) et des échappements octals pour d'autres (
\ 0 code>,
\ 377 code>).
cela ne fonctionnera pas comme les personnages d'évacuation ne le font pas réellement dans la chaîne
Pavel, comment ça ne vaut-il pas? Considérez la chaîne «\ r \ 033 \ n», qu'est-ce qui va devenir? (mais le bowvote n'est pas le mien)
@Michael: Qu'est-ce qui va devenir ceci: "\\ r \\ 033 \\ n", ce qui est exactement ce qui est nécessaire.
Non, je parle de la chaîne, composée de retour de chariot, d'échappement et d'alimentation en ligne, pas de barre oblique backslash r, backslash zéro trois trois et backslash n.
Si vous écrivez des choses GPL, vous pouvez utiliser http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/Quoearg.candhb=head p>
Marquant ceci comme accepté car il a suggéré une fonction de bibliothèque (même si elle n'est pas dans la charge standard) et ne faisait pas roulé sa propre (ce qui n'était vraiment pas ce que je demandais).
Vous venez de mentionner que vous vouliez imprimer la chaîne.
char example[] = "first line\nsecond line: \"inner quotes\""; size_t length = 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]); } }
Qu'en est-il des autres non-responsables? \ 033, par exemple?
@Michael Krelin: non testé, mais imprime maintenant des non -tubles comme des fuites octales.
Vous obtenez mon vote comme le premier et le seul qui a pris en compte le problème ;-)
\ E ne va pas mieux que \ 033?
@u_ltd. \ E code> n'est pas une séquence d'évacuation standard dans C. en. CPPrefreence.com/w/c/language/escape
Il n'y a pas de fonction de bibliothèque C standard C pour cela.
Lorsque vous utilisez la déclaration p> Les séquences d'échappement seront interprétées et remplacées par le compilateur. Vous devrez "non interpréter" les caractères que c échappe. Voici un exemple rapide N-sale: P> #include <stdio.h>
#include <ctype.h>
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);
}
}
}
Je ne sais pas si vous êtes au courant, mais met code> appendez une nouvelle ligne de fin.
Qu'est-ce que diable est sinon code> pour un interrupteur
code>?
Ha! Cela me ramène à VB jours avec Sélectionnez case code> et
case d'autre code>.
@dreamlax: Bon point, j'aurais dû noter que dans ma réponse. J'ai utilisé obtient code> car il était plus propre à lire que deux
Putchar code> appels (compte tenu de l'espace fourni) et que j'essayais de communiquer le concept plus que la mise en œuvre. Je vais éditer ma réponse pour clarifier cela. @Michael Krelin: C'est latin pour "Par défaut", je l'ai traduite cependant. Merci d'avoir attrapé ça.
#include <string.h> /* int c_quote(const char* src, char* dest, int maxlen) * * Quotes the string given so that it will be parseable by a c 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; }
Je me sentais comme si ma réponse précédente était la triche car une fonction qui écrit sur un tampon est beaucoup plus utile que celle qui écrit simplement sur C'est probablement un peu inefficace avec tout le stdout code>, alors voici une solution alternative qui fonctionne la quantité de mémoire besoins si
dst code> est
null code> et s'arrête également à
DSTLEN code> selon l'exigence.
Si (DST) code> Vérification. P>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
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;
}
Arrêt au-delà du
\ 0 code> semble dangereux, vous feriez mieux d'être 100% sûr que la longueur est valide ou que le chaos s'ensuivra.
utile si je veux afficher des données binaires semi-en toute sécurité.