C: chaîne remplacer en boucle (c débutant)

Je dois remplacer une chaîne dans un texte. J’ai trouvé cette fonction ici chez stackoverflow:

char *replace(const char *s, const char *old, const char *new) { char *ret; int i, count = 0; size_t newlen = strlen(new); size_t oldlen = strlen(old); for (i = 0; s[i] != '\0'; i++) { if (strstr(&s[i], old) == &s[i]) { count++; i += oldlen - 1; } } ret = malloc(i + count * (newlen - oldlen)); if (ret == NULL) exit(EXIT_FAILURE); i = 0; while (*s) { if (strstr(s, old) == s) { strcpy(&ret[i], new); i += newlen; s += oldlen; } else ret[i++] = *s++; } ret[i] = '\0'; return ret; } 

Cette fonction fonctionne très bien pour un remplacement simple. Mais je dois remplacer tout un tableau “str2rep” par “remplacement”. Donc, ce que j’essaie de faire (je suis juste un débutant)

 **** #define MAXTEXT 39016 int l; int j; char *newsms = NULL; char text[MAXTEXT]; char *str2rep[] = {":q:",":n:"}; char *replacement[] = {"?","\n"}; strcpy((char *)text,(char *)argv[5]); l = sizeof(str2rep) / sizeof(*str2rep); for(j = 0; j < l; j++) { newsms = replace(text,(char *)str2rep[j],(char *)replacement[j]); strcpy(text,newsms); free(newsms); } textlen = strlen(text); 

Ce code fonctionne même localement, si je le construis à partir d’un seul fichier … Mais c’est un module astérisque, donc quand il est exécuté, l’astérisque s’arrête avec:

* glibc détectée * / usr / sbin / asterisk: double libération ou corruption (! prev): 0x00007fa720006310 *

Problèmes:

  1. ret = malloc(i + count * (newlen - oldlen)); c’est trop petit. Besoin + 1.
    Considérez ce qui se passe avec replace("", "", "") . Si votre référence est la suivante , elle est également mauvaise.

  2. Résultats discutables mélangeant signé / non signé. count est signé. newlen, oldlen sont pas signés.
    Je pense que le code original fonctionne correctement, mais je n’aime pas utiliser la nature enveloppante des mathématiques non signées lorsque cela peut être évité, ce qui se produit lorsque newlen < oldlen .

     // i + count * (newlen - oldlen) size_t newsize = i + 1; // + 1 for above reason if (newlen > oldlen) newsize += count * (newlen - oldlen); if (newlen < oldlen) newsize -= count * (oldlen - newlen); ret = malloc(newsize); 
  3. Assurez-vous d'avoir assez d'espace. @hyde Différentes approches disponibles ici.

     // strcpy(text, newsms); if (strlen(newsms) >= sizeof text) Handle_Error(); strcpy(text, newsms); 

Mineur

  1. Pas besoin de lancer

     // newsms = replace(text, (char *) str2rep[j], (char *) replacement[j]); newsms = replace(text, str2rep[j], replacement[j]); 
  2. Mieux vaut utiliser size_t pour i . Une solution pédante utiliserait également size_t count .

     // int i; size_t i; 

Je vais suggérer quelque chose qui me semble un peu plus clair comme alternative, à la place d’une implémentation dynamic de chaîne appropriée. La gestion des exceptions rest un exercice à append pour le lecteur. 🙂

 #include  #include  #include  char *appendn(char *to, char *from, int length) { return strncat(realloc(to, strlen(to) + length + 1), from, length); } char *replace(char *ssortingng, char *find, char *sub) { char *result = calloc(1, 1); while (1) { char *found = strstr(ssortingng, find); if (!found) break; result = appendn(result, ssortingng, found - ssortingng); result = appendn(result, sub, strlen(sub)); ssortingng = found + strlen(find); } return appendn(result, ssortingng, strlen(ssortingng)); } int main() { const char text[] = "some [1] with [2] to [3] with other [2]"; char *find[] = {"[1]", "[2]", "[3]", NULL}; char *sub[] = {"text", "words", "replace"}; char *result, *s; int i; result = malloc(sizeof(text)); (void) strcpy(result, text); for (i = 0; find[i]; i ++) { s = replace(result, find[i], sub[i]); free(result); result = s; } (void) printf("%s\n", result); free(result); }