IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

[String]Bug Remplacer une sous chaine par une chaine


Sujet :

C

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 85
    Points : 62
    Points
    62
    Par défaut [String]Bug Remplacer une sous chaine par une chaine
    Bonjour,

    J'ai un problème au niveau d'une fonction appelée str_remplace, je lui donne les bonnes valeurs mais elle me renvoie une chaine erronée.
    Comme j'ai pompée cette fonction sur internet je reussi pas à la débuggée.
    Le code est en dessous.
    Cette fonction remplace dans le chaine s la sous chaine qui commence à start et qui a pour taille lenght par la chaine ct.

    Je donne à ma fonction ceci :

    s : 1.000000+e(x)-1+s(x)
    start : 11
    lenght : 1
    ct : 1.000000

    Elle me renvoie ceci : 1.000000+e(1.000000)-1+s(x)!á
    Au lieu de ceci : 1.000000+e(1.000000)-1+s(x)
    il y a !á en trop

    Avec les paramètres fournies cette fonction doit remplacer dans la chaine s le 12 caractères par la valeur ct.
    Elle le fait mais les rajoute le ziguigui à la fin.

    Voici la fonction :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    char *str_remplace (const char *s, unsigned int start, unsigned int lenght, const char *ct){
            printf("entree : %s - %d - %d - %s\n",s,start,lenght,ct);
            char *new_s = NULL;
        if (s && ct && start >= 0 && lenght >= 0){
                    size_t size = strlen (s);
                    new_s = malloc (sizeof (*new_s) * (size - lenght + strlen (ct)));
                    if (new_s){
                            memmove (new_s, s, start);
                            memmove (&new_s[start], ct, strlen (ct));
                            memmove (&new_s[start + strlen (ct)], &s[start + lenght],size - lenght - start + 1);
                    }
            }
            else{
                    fprintf (stderr, "Memoire insuffisante\n");
                    exit (EXIT_FAILURE);
            }
            printf("faux:%s\n",new_s);
            return new_s;
    }
    -------------------------------------------------------------------------

    OPTIONNEL :

    Je vais vous expliquer ce que le programme fait en globalité si vous voulez tester la fonction.
    Tout le programme marche sauf la foncion str_remplace.
    J'ai un programme qui affiche le résultat d'une expression mathématique.
    J'utilise pour cela la calculatrice en ligne de commande unix bc.
    L'expression mathématique a des inconnues x et je doit remplacer ces x par un float (très important ceci n'est qu'une partie d'un programme qui fournit un float ou double).

    Exemple :
    Expresion mathematique : x+exp(x)-1+sin(x)
    Pour x=0.001 je dois obtenir ceci 0.001+exp(0.001-1+sin(0.001))
    Ensuite le programme donne à bc l'expression et bc renvoie le résultat.
    echo "0.001+exp(0.001-1+sin(0.001))" | bc -l

    Lorsque l'expression mathématique est simple ça marche mais pour x+exp(x)-1+sin(x) au milieu de la conversion j'obtient ceci 1.000000+e(1.000000)-1+s(x)!á au lieu de ceci 1.000000+e(1.000000)-1+s(x)
    Biensûr après c'est l'enchainement d'erreurs.

    Voici mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/stat.h>
    #include <fcntl.h>
     
    /*Fonction de remplacement de chaine*/
    char *str_remplace (const char *s, unsigned int start, unsigned int lenght, const char *ct){
    	char *new_s = NULL;
        if (s && ct && start >= 0 && lenght >= 0){
    		size_t size = strlen (s);
    		new_s = malloc (sizeof (*new_s) * (size - lenght + strlen (ct)));
    		if (new_s){
    			memmove (new_s, s, start);
    			memmove (&new_s[start], ct, strlen (ct));
    			memmove (&new_s[start + strlen (ct)], &s[start + lenght],size - lenght - start + 1);
    		}
    	}
    	else{
    		fprintf (stderr, "Memoire insuffisante\n");
    		exit (EXIT_FAILURE);
    	}
    	return new_s;
    }
     
    /*Position de la chaine ct dans cs dans la chaine*/
    int str_istr (const char *cs, const char *ct){
    	int index = -1;
        if (cs && ct){
    		char *ptr_pos = NULL;
            ptr_pos = strstr (cs, ct);
            if (ptr_pos){
    			index = ptr_pos - cs;
    		}
    	}
    	return index;
    }
     
    /*Mise en forme de l'expression pour etre interpretee par bc*/		
    char * convert_bc (char * chaine,float x){
    	char old_chaine[255];
    	char new_chaine[255];
    	int pos; 
        	int tai;
    	int sig=5;/* significant digits */
    	int match;
     
    	while(strstr(chaine,"sin")||strstr(chaine,"cos")||strstr(chaine,"arg")||strstr(chaine,"exp")||strstr(chaine,"x")){
    		match=0;
    		if((strstr(chaine,"sin"))&&(match==0)){
    			strcpy(old_chaine,"sin");
    			strcpy(new_chaine,"s");
    			match=1;
    		}
    		if((strstr(chaine,"cos"))&&(match==0)){
    			strcpy(old_chaine,"cos");
                            strcpy(new_chaine,"c");
    			match=1;
    		}
    		if((strstr(chaine,"arct"))&&(match==0)){
    			 strcpy(old_chaine,"arct");
                            strcpy(new_chaine,"a");
    			match=1;
    		}
    		if((strstr(chaine,"exp"))&&(match==0)){
     			strcpy(old_chaine,"exp");
                            strcpy(new_chaine,"e");	 
    			match=1;
    		}
     
    		if((strstr(chaine,"x"))&&(match==0)){
    			strcpy(old_chaine,"x");
    		/* a regular number */
    			sprintf(new_chaine, "%f", x);
    			match=1;
    		//gcvt(x, sig,new_chaine);
    		}
    		if(match==1){
    			pos = str_istr(chaine, old_chaine);
    			tai = strlen(old_chaine);
    			chaine=str_remplace(chaine,pos,tai,new_chaine);
    			printf("A nc %s - oc %s - pos %d - tai %d -ch %s\n",new_chaine, old_chaine,pos,tai,chaine);
    		//	printf("resultat %s\n",chaine);
    		}
     	printf("B %s\n",chaine);
    	}
    	return chaine;
    }
     
    /*Calcul de l'ordonne en focntion de l'expression*/
    float eval(char * chaine,float x){	
    	char * cmd = malloc (sizeof (*cmd) * 256);
    	char * c_resultat = malloc (sizeof (*c_resultat) * 256);
    	float f_resultat;
    	char * chaine_clean = malloc (sizeof (*chaine_clean) * 256);	
    	//printf("exprB:%s\n",chaine);	
    	chaine_clean=convert_bc(chaine,x);
    	 printf("exprA:%s\n",chaine_clean);
     
    	strcat(cmd,"echo \"");
    	strcat(cmd,chaine_clean);
    	strcat(cmd,"\" | bc -l");
    	printf("%s\n",cmd);
    	FILE * f;
        // Ouverture du shell et lancement de gnuplot
        f = popen(cmd, "r");
    	fgets(c_resultat,255,f);
    	fflush(f);
    	pclose(f);
    	f_resultat=atof(c_resultat);
    	return f_resultat;
    }	
     
    int main(int argc, char** argv){
    	float x=1;
    	//for(x=0.0;x<10.0;x+=0.001){
    	printf("resul pour :%f = %f\n",x,eval("x+exp(x)-1+sin(x)",x));
    	//}		
    	return 0;
    }

    Merci

  2. #2
    Expert éminent sénior

    Avatar de fearyourself
    Homme Profil pro
    Ingénieur Informaticien Senior
    Inscrit en
    Décembre 2005
    Messages
    5 121
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Ingénieur Informaticien Senior
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    Points : 11 877
    Points
    11 877
    Par défaut
    Voici une solution qui semble fonctionner...

    La fonction ne copier pas tout le temps (voir jamais) le '\0'... (et ne l'allouer pas la place non plus)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
     
    char * str_remplace (const char *s, unsigned int start, unsigned int length, const char *ct)
    {
        char *new_s = NULL;
     
        if (s && ct) {
            size_t size = strlen (s);
     
            /* Tester start, length >= 0 est inutile, ils sont unsigned... */
            if ( start + length < size) {
     
                /* Allocation de la nouvelle taille -> +1 pour le \0 de fin */
                new_s = malloc (size - length + strlen (ct) + 1);
     
                if (new_s) {
                    /* Copie du debut */
                    memmove (new_s, s, start);
     
                    /* Copie du remplacement */
                    memmove (new_s + start, ct, strlen (ct));
     
                    /* Copie de la fin -> +1 pour le '\0' */
                    memmove (new_s + (start + strlen (ct)), 
                             s + (start + length),
                             strlen(s+start+length) + 1);
                }
                else {
                    fprintf (stderr, "Memoire insuffisante\n");
                    return NULL;
                }
            }
        }
        return new_s;
    }
     
    int main()
    {
        const char *s = "hello ca  bien ?";
        const char *r = "1.000000+e(x)-1+s(x)";
     
        char *s2 = str_remplace(s , 9, 1, "va ");
        char *r2 = str_remplace(r, 11, 1, "1.000000");
     
        printf("%s\n",s2);
        printf("%s\n",r2);
        return EXIT_SUCCESS;
    }
    Pose des questions si quelque chose semble bizarre,
    Jc

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 85
    Points : 62
    Points
    62
    Par défaut
    Voici une autre fonction qui marche
    Je préfère ta fonction elle est beaucoup mieux.

    Merci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    #include <stdio.h>
    #include <stdlib.h>
     
    int RemplacerFragment (char *source, const char *vieux, const char *nouveau)
    {
      char *original = source;
      char temp[4096];
      int ancienne_long = strlen (vieux);
      int i, j, k, place = -1;
      for (i = 0; source[i] && (place == -1); ++i)
        for (j = i, k = 0; source[j] == vieux[k]; j++, k++)
          if (!vieux[k+1])
            place = i;
      if (place != -1) 
      {
        for (j=0; j<place; j++)
          temp[j] = source[j];
        for (i=0; nouveau[i]; i++, j++)
          temp[j] = nouveau[i];
        for (k = place + ancienne_long; source[k]; k++, j++)
          temp[j] = source[k];
        temp[j] = 0;
        for (i=0; source[i] = temp[i]; i++)
          ;
      }
      return place;
    }
     
    //Code qui fonctionne à coup sûr (je l'utilise depuis plusieurs mois dans ma calto) :
    //-----------------------------------------------------------------------------
    // Remplace toutes les occurances de Avant par Apres dans la chaine txt, puis
    // renvoie un pointeur sur la nouvelle chaine créée. Renvoie NULL s'il txt
    // ne contient aucune occurance de Avant.
    char* str_replace (const char* txt, const char* Avant, const char* Apres)
    {
    const char* pos; // Position d'une occurance de Avant dans txt
    char* TxtRetour; // La chaine retournée
    size_t PosTxtRetour; // Position du prochain caractère à écrire
    // dans TxtRetour
    size_t Long; // Long d'une chaine à écrire dans TxtRetour
    size_t TailleAllouee; // Taille allouée à TxtRetour
     
    // Cherche la première occurancce
    pos = strstr (txt,Avant);
     
    // Aucune occurance : renvoie simplement une copie de la chaine
    if (pos == NULL) return NULL;
     
    // Alloue une nouvelle chaine
    Long = (size_t)pos -(size_t)txt;
    TailleAllouee = Long +strlen(Apres)+1;
    TxtRetour = (char *)malloc(TailleAllouee);
    PosTxtRetour = 0;
     
    // Copie la première partie de la chaîne sans occurance
    strncpy (TxtRetour+PosTxtRetour,txt,Long); PosTxtRetour += Long;
    txt = pos+strlen(Avant);
     
    // Ajoute la chaîne de remplacement Apres
    Long = strlen(Apres);
    strncpy (TxtRetour+PosTxtRetour,Apres,Long); PosTxtRetour += Long;
     
    // Cherche la prochaine occurance
    pos = strstr (txt,Avant);
    while (pos != NULL)
    {
    // Agrandit la chaine
    Long = (size_t)pos -(size_t)txt;
    TailleAllouee += Long+strlen(Apres);
    TxtRetour = (char *)realloc(TxtRetour,TailleAllouee);
     
    // Copie ce qu'il y a entre la dernier occurance et la nouvelle
    strncpy (TxtRetour+PosTxtRetour,txt,Long); PosTxtRetour += Long;
     
    // Passe l'occurance
    txt = pos+strlen(Avant);
     
    // Ajoute la chaîne de remplacement
    Long = strlen(Apres);
    strncpy (TxtRetour+PosTxtRetour,Apres,Long); PosTxtRetour += Long;
     
    // Cherche la prochaine occurance
    pos = strstr (txt,Avant);
    }
     
    // Ajoute le reste de la chaîne (il reste au moins '\0')
    Long = strlen(txt)+1;
    TailleAllouee += Long;
    TxtRetour = (char*)realloc(TxtRetour,TailleAllouee);
    strncpy (TxtRetour+PosTxtRetour,txt,Long);
    return TxtRetour;
    }
     
     
     
    int main(){
    char source[255]="1.000000+e(x)-1+s(x)";
    char vieux[255]="x";
    char nouveau[255]="1.000000";
    char * titi;
    titi = str_replace (source,vieux,nouveau);
    printf("%s",titi);
    return 0;
    }

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    85
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 85
    Points : 62
    Points
    62
    Par défaut
    J'ai testé ça marche nickel merci.
    Maintenant j'ai un interpreteur qui marche.
    Je vais l'integrer à mon programme qui trace la courbe en SDL de l'expression mathématique.
    Au final ca donnera un truck pas mal.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Peut-on remplacer une sous-requête par une jointure ?
    Par shimomura22 dans le forum Développement
    Réponses: 13
    Dernier message: 14/01/2015, 09h46
  2. Réponses: 8
    Dernier message: 05/04/2011, 08h06
  3. Remplacer une sous-requête par une jointure
    Par MPQuatre dans le forum Requêtes
    Réponses: 6
    Dernier message: 05/12/2007, 17h28
  4. Remplacer une sous chaîne par une autre
    Par Erakis dans le forum Général JavaScript
    Réponses: 15
    Dernier message: 10/11/2006, 09h16
  5. copie d'une table Y d'une base A vers une table X d'une base
    Par moneyboss dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 30/08/2005, 21h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo