OVH Cloud OVH Cloud

remplacement de chaine

4 réponses
Avatar
KorHeve
bonjour à tous,
Je suis debutant en C et je cherche une fonction permettant de remplcer une sou-chaine par une autre daans une chaine principale.
Un truc du style : char* remplacer(char* string, char* search, char* replace)

Avez vous une solution ?

Merci

4 réponses

Avatar
Cyrille \cns\ Szymanski
bonjour à tous,
Je suis debutant en C et je cherche une fonction permettant de
remplcer une sou-chaine par une autre daans une chaine principale. Un
truc du style : char* remplacer(char* string, char* search, char*
replace)

Avez vous une solution ?


C'est compliqué parce que cette opération modifie généralement la taille
des chaînes et il n'y a pas de telle fonction dans la libc.

Tout dépend du niveau de performance que tu cherches à obtenir. Une méthode
acceptable consiste à saucissonner la chaîne en segments qui sont soit du
texte, soit la chaîne à remplacer, puis à calculer la nouvelle taille
(allouer de la place pour cette chaîne) et enfin réitérer sur les segments
en les copiant à leur nouvel emplacement.

Tu peux peut-être regarder si iMatix SFL ont implémenté qqch à ce sujet, ou
une bibliothèque d'expressions régulières.

Si programmer une telle fonction est d'intérêt pédagogique fais-le, sinon
ne réinvente pas la roue.

a+
--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/

Avatar
KorHeve
Merci pour la réponse.
Je ne connaissais pas iMatric SFL, il y a des choses tres interessantes.
j'ai notamment ce bout de code :

#include "sflstr.h"
char *
searchreplace (
char *strbuf,
char *strtofnd,
char *strtoins)
{
char *offset, *strbase;

ASSERT (strbuf);
ASSERT (strtofnd);
ASSERT (strtoins);

offset = strbase = (char *)NULL;

while (*strbuf)
{
offset = stricstr (!offset ? strbuf : strbase, strtofnd);
if (offset)
{
strbase = (offset + strlen (strtoins));
strcpy (offset, (offset + strlen (strtofnd)));
memmove (offset + strlen (strtoins),
offset, strlen (offset) + 1);
memcpy (offset, strtoins, strlen (strtoins));
}

else
break;
}

return strbuf;
}

A priori cela fait ce que je recherche !
Une derniere (?) petite question, à quoi correspnd le ASSERT ???

Merci



On 2 Sep 2003 20:14:19 GMT
"Cyrille "cns" Szymanski" wrote:

bonjour à tous,
Je suis debutant en C et je cherche une fonction permettant de
remplcer une sou-chaine par une autre daans une chaine principale. Un
truc du style : char* remplacer(char* string, char* search, char*
replace)

Avez vous une solution ?


C'est compliqué parce que cette opération modifie généralement la taille
des chaînes et il n'y a pas de telle fonction dans la libc.

Tout dépend du niveau de performance que tu cherches à obtenir. Une méthode
acceptable consiste à saucissonner la chaîne en segments qui sont soit du
texte, soit la chaîne à remplacer, puis à calculer la nouvelle taille
(allouer de la place pour cette chaîne) et enfin réitérer sur les segments
en les copiant à leur nouvel emplacement.

Tu peux peut-être regarder si iMatix SFL ont implémenté qqch à ce sujet, ou
une bibliothèque d'expressions régulières.

Si programmer une telle fonction est d'intérêt pédagogique fais-le, sinon
ne réinvente pas la roue.

a+
--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/



Avatar
Cyrille \cns\ Szymanski
A priori cela fait ce que je recherche !
Une derniere (?) petite question, à quoi correspnd le ASSERT ???





--
_|_|_| CnS
_|_| for(n=0;b;n++)
_| b&=b-1; /*pp.47 K&R*/

Avatar
informiciel
KorHeve a écrit le 02/09/2003 à 21h53 :
bonjour à tous,
Je suis debutant en C et je cherche une fonction permettant de remplcer une
sou-chaine par une autre daans une chaine principale.
Un truc du style : char* remplacer(char* string, char* search, char* replace)

Avez vous une solution ?

Merci


Bonjour, c'est bien tard pour répondre mais comme je suis tombé dessus en cherchant une solution je me suis dit que ça peut servir à d'autres. Voir un code qui fait le travail, sans limite de taille en mémoire.
Juste la fonction "remplacer" est nécessaire, les exemples (fonction main) sont à titre pédagogique:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/*-------------------------------------------------------------------*
| remplacer : Cherche et remplace une sous-chaine par une autre |
|-------------------------------------------------------------------|
| Parametres : |
| str_orig: Chaine de caractères dans laquelle on fouille |
| cherche : Sous-chaine recherchée |
| remp : Sous-chaine de remplacement |
| nbr_remplace : Pointeur vers un entier ou NULL si optionnel |
| Entrée: Nombre de remplacements maximum à faire. |
| Si < 1 ou NULL, fait des remplacements illimités |
| Sortie: Nombre de remplacements faits ou -1 si erreur |
|-------------------------------------------------------------------|
| Retour : Pointeur vers une nouvelle chaine de caractères |
| avec les remplacements faits ou NULL si erreur |
|-------------------------------------------------------------------|
| Notes: |
| - Tient compte des majuscules/minuscules (case sensitive) |
| Autrement, remplacez les fonctions "strstr" par "strcasestr" |
| - Fait systématiquement une copie de la chaine en entrée |
| comme résultat de la fonction (pointeur sur nouvelle chaine) |
|-------------------------------------------------------------------|
| Auteur: Thierry Husson, Sept 2010 |
*-------------------------------------------------------------------*/

char* remplacer(const char *str_orig, const char *cherche, const char *remp, int *nbr_remplace)
{
/* Variables locales */
const char *str_tmp, *str_init;
char *str_nouv;
int nbr_remp, nbr_remp_max, longueur, buf_long;

str_tmp = str_orig;
nbr_remp_max = (nbr_remplace != NULL && *nbr_remplace > 0) ? *nbr_remplace : -1;

/* Compte le nombre de fois que la chaine originale est trouvée */
nbr_remp = 0;
while ((str_tmp = strstr(str_tmp, cherche)) != NULL && nbr_remp != nbr_remp_max) {
nbr_remp++;
str_tmp += strlen(cherche); /* Reprend la recherche après la chaine trouvée */
}

if (nbr_remp == 0) { /* Juste faire un double de l'originale */
str_nouv = strdup(str_orig);
} else { /* Il y a des remplacements à faire */
/* Calcule l'espace mémoire nécessaire pour la nouvelle chaine */
longueur = strlen(str_orig) + nbr_remp * (strlen(remp) - strlen(cherche)) + 1;
if ( (str_nouv = (char *)malloc(longueur)) != NULL) {
str_nouv[longueur] = ''; /* Voila c'est fait, on peut oublier qu'on est en C... */
str_tmp = str_init = str_orig;
nbr_remp_max = nbr_remp; /* Compteur à rebours */
buf_long = 0; /* longueur en cours du str_nouv */
/* Pour chaque sous-chaine trouvée, on met celle de remplacement */
while ((str_tmp = strstr(str_tmp, cherche)) != NULL && (nbr_remp_max-- > 0)) {
longueur = (str_tmp - str_init); /* Nombre de caractères inchangés */
strncpy(str_nouv + buf_long, str_init, longueur); /* Copie partie inchangée */
buf_long += longueur;
strcpy(str_nouv + buf_long, remp); /* Ajoute chaine de remplacement */
buf_long += strlen(remp);
str_tmp += strlen(cherche);
str_init = str_tmp;
}
strcpy(str_nouv + buf_long, str_init); /* Ajoute la fin de la chaine inchangée */
}
}

if ( str_nouv == NULL) { /* Si erreur! */
fprintf(stderr, "Pas assez de mémoire!n");
nbr_remp = -1;
}
if (nbr_remplace != NULL) *nbr_remplace = nbr_remp;

return str_nouv;
}


/*-------------------------------------------------------------------*
| Exemples d'utilisation |
*-------------------------------------------------------------------*/
int main(void)
{
char *chaine, *chaine2;
int rpl;

/* Exemple simple */
rpl = 0; /* Remplacements illimités */
chaine = remplacer("Hello World!", "World", "Canada", &rpl);
printf("Remplacements: %dtResultat: [%s]nn", rpl, chaine);
/* Remplacements: 1 Resultat: [Hello Canada!] */
free(chaine);

/* Exemple avec allocation de mémoire dynamique à nettoyer */
rpl = 0; /* Remplacements illimités */
chaine = strdup("abcdef");
if ( (chaine2 = remplacer(chaine, "cd", "1234", &rpl)) != NULL ) {
free(chaine);
chaine = chaine2;
}
printf("Remplacements: %dtResultat: [%s]nn", rpl, chaine);
/* Remplacements: 1 Resultat: [ab1234ef] */
free(chaine);

/* Exemple avec variable statique pas à nettoyer */
rpl = 0; /* Remplacements illimités - Resultat plus grand */
chaine = "select * from employes where age% && niveau=4 && section=2";
chaine = remplacer(chaine, "&&", "AND",&rpl);
printf("Remplacements: %dtResultat: [%s]nn", rpl, chaine);
/* Remplacements: 2 Resultat: [select * from employes where age% AND niveau=4 AND section=2] */
free(chaine);

rpl = 0; /* Remplacements illimités - Resultat plus petit */
chaine = remplacer("XXXHello XXXX world XX salut xxx monde!XXX", "XXX", "-",&rpl);
printf("Remplacements: %dtResultat: [%s]nn", rpl, chaine);
/* Remplacements: 3 Resultat: [-Hello -X world XX salut xxx monde!-] */
free(chaine);

rpl = 0; /* Remplacements illimités - Chaine non trouvée */
chaine = remplacer("ABCdef", "DE", "*", &rpl);
printf("Remplacements: %dtResultat: [%s]nn", rpl, chaine);
/* Remplacements: 0 Resultat: [ABCdef] */
free(chaine);

rpl = 3; /* Remplacements Limités atteints */
chaine = remplacer("AAAAAA", "A", "*", &rpl);
printf("Remplacements: %dtResultat: [%s]nn", rpl, chaine);
/* Remplacements: 3 Resultat: [***AAA] */
free(chaine);

rpl = 10; /* Remplacements Limités non atteints */
chaine = remplacer("BBBAAA", "A", "*", &rpl);
printf("Remplacements: %dtResultat: [%s]nn", rpl, chaine);
/* Remplacements: 3 Resultat: [BBB***] */
free(chaine);

/* Remplacements illimités et on veut pas savoir combien de faits */
chaine = remplacer("BBBAAA", "A", "*", NULL);
printf("Resultat: [%s]nn", chaine);
/* Resultat: [BBB***] */
free(chaine);

return 0;
}