comment remplacer la sous-chaîne en c?

Cet exemple fonctionne mais je pense que la mémoire manque. La fonction utilisée dans le module de serveur Web simple et donc la mémoire partagée augmente si vous utilisez cette fonction.

char *str_replace ( const char *ssortingng, const char *substr, const char *replacement ){ char *tok = NULL; char *newstr = NULL; char *oldstr = NULL; if ( substr == NULL || replacement == NULL ) return strdup (ssortingng); newstr = strdup (ssortingng); while ( (tok = strstr ( newstr, substr ))){ oldstr = newstr; newstr = malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 ); memset(newstr,0,strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1); if ( newstr == NULL ){ free (oldstr); return NULL; } memcpy ( newstr, oldstr, tok - oldstr ); memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) ); memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) ); memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) , 0, 1 ); free (oldstr); } return newstr; } 

Un problème que je peux voir est que si la chaîne de remplacement contient la chaîne de recherche, vous bouclez pour toujours (jusqu’à ce que vous manquiez de mémoire).

Par exemple:

 char *result = str_replace("abc", "a", "aa"); 

De plus, faire un autre malloc / free à chaque fois que vous remplacez une instance coûte assez cher.

Une meilleure approche serait de faire exactement 2 passages sur la chaîne d’entrée:

  • Au premier passage, comptez le nombre d’instances de la chaîne de recherche présentes.

  • Maintenant que vous savez combien de correspondances, calculez la longueur de votre résultat et malloc une fois:

    strlen (chaîne) + correspond à * (strlen (remplacement) -strlen (sous)) + 1

  • faire un deuxième passage dans la chaîne source, en copiant / remplaçant

Expliquez cette partie:

if ( substr == NULL || replacement == NULL ) return strdup (ssortingng);

Pourquoi retournez-vous une copie de la chaîne existante? Cela va perdre de la mémoire, et c’est inutile.

De plus, vous ne libérez jamais le duplicata si la boucle while est ignorée (la condition n’est jamais remplie).

Ceci remplacera toute occurrence de “str” ​​par “rep” dans “src” …

 void strreplace(char *src, char *str, char *rep) { char *p = strstr(src, str); do { if(p) { char buf[1024]; memset(buf,'\0',strlen(buf)); if(src == p) { strcpy(buf,rep); strcat(buf,p+strlen(str)); } else { strncpy(buf,src,strlen(src) - strlen(p)); strcat(buf,rep); strcat(buf,p+strlen(str)); } memset(src,'\0',strlen(src)); strcpy(src,buf); } }while(p && (p = strstr(src, str))); } 
  • strdup n’est pas C89 / C99, donc votre code => no ANSI C
  • mieux faire le test NULL directement après malloc

Voici un exemple, avec un seul nouveau bloc mémoire:

 /* precondition: s!=0, old!=0, new!=0 */ char *str_replace(const char *s, const char *old, const char *new) { size_t slen = strlen(s)+1; char *cout = malloc(slen), *p=cout; if( !p ) return 0; while( *s ) if( !strncmp(s, old, strlen(old)) ) { p -= cout; cout= realloc(cout, slen += strlen(new)-strlen(old) ); p += strlen( strcpy(p=cout+(int)p, new) ); s += strlen(old); } else *p++=*s++; *p=0; return cout; }