7
votes

Bibliothèque C Standard C pour échapper à une chaîne

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: xxx

et je voulais imprimer < / p> xxx

existe une fonction de bibliothèque qui fera cette transformation pour moi? Rouler mon propre semble juste un peu stupide.

points bonus si je peux lui donner une longueur pour s'échapper (il s'arrête donc avant ou au-delà du \ 0 ).


2 commentaires

Arrêt au-delà du \ 0 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é.


7 Réponses :


0
votes

Pas de fonction C standard, mais pas trop difficile à rouler votre propre

rien de trop jolie mais: - xxx


0 commentaires

-3
votes
while(*src++)
{
  if(*src == '\\' || *src == '\"' || *src == '\'')
    *dest++ = '\\';

  *dest++ = *src++;
}

6 commentaires

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 () et produisant des échappes appropriées pour les non-imprimables et espaces communs ( \ n , \ t ) et des échappements octals pour d'autres ( \ 0 , \ 377 ).


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.



6
votes

1 commentaires

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).



1
votes

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]);
    }
}


5 commentaires

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 n'est pas une séquence d'évacuation standard dans C. en. CPPrefreence.com/w/c/language/escape



2
votes

Il n'y a pas de fonction de bibliothèque C standard C pour cela.

Lorsque vous utilisez la déclaration p> xxx pré>

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


4 commentaires

Je ne sais pas si vous êtes au courant, mais met appendez une nouvelle ligne de fin.


Qu'est-ce que diable est sinon pour un interrupteur ?


Ha! Cela me ramène à VB jours avec Sélectionnez case et case d'autre .


@dreamlax: Bon point, j'aurais dû noter que dans ma réponse. J'ai utilisé obtient car il était plus propre à lire que deux Putchar 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.



1
votes
#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;
}

0 commentaires

0
votes

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 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.

C'est probablement un peu inefficace avec tout le 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;
}


0 commentaires