2010-08-06 6 views
4

J'écris une application fastcgi pour mon site en C. Ne demandez pas pourquoi, laissez toute cette partie. Aidez-moi simplement avec ce problème, je veux remplacer les espaces dans la chaîne de requête avec% 20. Voici le code que j'utilise, mais je ne vois pas 20 dans la sortie, seulement%. Où est le problème?Remplacer des espaces avec% 20 en C

code:

unsigned int i = 0; 

/* 
* Replace spaces with its hex %20 
* It will be converted back to space in the actual processing 
* They make the application segfault in strtok_r() 
*/ 

char *qstr = NULL; 
for(i = 0; i <= strlen(qry); i++) { 
    void *_tmp; 
    if(qry[i] == ' ') { 
    _tmp = realloc(qstr, (i + 2) * sizeof(char)); 
    if(!_tmp) error("realloc() failed while allocting string memory (space)\n"); 
    qstr = (char *) _tmp; 
    qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0'; 
    } else { 
    _tmp = realloc(qstr, (i + 1) * sizeof(char)); 
    if(!_tmp) error("realloc() failed while allocating string memory (not space)\n"); 
    qstr = (char *) _tmp; 
    qstr[i] = qry[i]; 
    } 
} 

Dans le code, qry est char *, vient comme un paramètre réel à la fonction. J'ai essayé avec i + 3, 4, 5 dans realloc() dans le bloc remplaçant l'espace, sans succès.

+0

Pour que votre code fonctionne, vous devez ajouter 'i + = 2' au corps de l'instruction if. Cependant, le code dans ma réponse ci-dessous évite d'autres pièges de gestion de chaîne C dans lesquels vous êtes impliqués. – David

Répondre

15

La manipulation de chaînes en C peut être difficile. Je suggère de passer d'abord par la chaîne, en comptant les espaces, puis d'allouer une nouvelle chaîne de la taille appropriée (taille de la chaîne d'origine + (nombre d'espaces * 2)). Parcourez ensuite la chaîne d'origine, en conservant un pointeur (ou un index) sur la position dans la nouvelle chaîne et dans la chaîne d'origine. (Pourquoi deux pointeurs Parce que chaque fois que vous rencontrez un espace, le pointeur dans la nouvelle chaîne sera obtenir deux caractères avant le pointeur dans l'ancien.)

est ici un code qui devrait faire l'affaire:

int new_string_length = 0; 
for (char *c = qry; *c != '\0'; c++) { 
    if (*c == ' ') new_string_length += 2; 
    new_string_length++; 
} 
char *qstr = malloc((new_string_length + 1) * sizeof qstr[0]); 
char *c1, *c2; 
for (c1 = qry, c2 = qstr; *c1 != '\0'; c1++) { 
    if (*c1 == ' ') { 
     c2[0] = '%'; 
     c2[1] = '2'; 
     c2[2] = '0'; 
     c2 += 3; 
    }else{ 
     *c2 = *c1; 
     c2++; 
    } 
} 
*c2 = '\0'; 
+0

Hmm, bonne solution. Attendre que d'autres répondent. – Nilesh

+2

Si la vitesse est préférée à l'utilisation de la mémoire, allouez une chaîne avec 3 fois l'espace de la chaîne d'origine et passez la recherche des espaces pour déterminer la longueur de la nouvelle chaîne. Comme la méthode trouvée dans le lien dans la réponse de Kangkan. –

+0

Bonne approche mais la chaîne mallocée est un caractère trop court (vous ne comptez pas le '\ 0' final) donc il vaut mieux commencer par 'int new_string_length = 1;'. – x4u

0

Ceci est appelé encodage url. Vous pouvez vous référer à cette page pour voir la mise en œuvre similaire: http://www.geekhideout.com/urlcode.shtml

+1

Oh non. Je suis assez nouveau à C et j'aimerais apprendre plutôt que d'utiliser des trucs prédéfinis. – Nilesh

1

Vous assignez en utilisant le même compteur que je vous aurai besoin d'avoir 2 compteurs puisque les chaînes ont des longueurs différentes

votre cas autre RQCT attribue [i] = qry [i]; après avoir écrit le% 20, vous êtes au moins éteint par 2 sur la chaîne de résultat.

2

Je suis d'accord avec David.

Il est conseillé de le faire en deux étapes: dans la première boucle que vous comptez seulement les espaces:

int spaceCounter=0; 
const int sourceLen = strlen(qry); 
for(int i = 0; i < sourceLen; ++i) 
    if (qry[i] == ' ') 
     ++spaceCounter; 

char* newString = (char*)malloc(sourceLen + 3*spaceCounter*sizeof(char) + 1) 
//check for null! 
for(int i = 0; i < sourceLen; ++i) 
    if (qry[i] == ' ') 
    { 
     *newString++ = '%'; 
     *newString++ = '2'; 
     *newString++ = '0'; 
    } 
    else 
     *newString++ = qry[i]; 

*newString = '\0'; 

Attention: le code non testé.

+0

notez que 'sizeof (char)' est requis par la norme pour être 1. –

+1

En outre, vous placez un espace dans newString, ce qui annule le but de cette fonction. Il devrait ajouter juste le caractère '% 20' –

+0

@James: Bien que vous ayez raison, je pense que l'intention possible ici pourrait être de le rendre plus portable à Unicode. –

6
qstr[i] = '%'; qstr[i + 1] = '2'; qstr[i + 2] = '0'; 

Cette ligne écrit trois caractères à votre tampon de sortie, de sorte que le caractère suivant que vous écrivez doit être écrit au RQCT [i + 3]. Cependant, vous ne faites que passer par i, donc le caractère suivant est écrit dans qstr [i + 1], écrasant le '2'.

Vous devrez conserver des index séparés pour passer à travers qry & qstr.

0
char* toHexSpace(const char *s) 
{ 
    char *b=strcpy(malloc(3*strlen(s)+1),s),*p; 
    while(p=strchr(b,' ')) 
    { 
    memmove(p+3,p+1,strlen(p)); 
    strncpy(p,"%20",3); 
    } 
    return b; 
} 

besoins "libres" dans le contexte d'appel.

Questions connexes