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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    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
    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 confirmé

    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 : 44
    Localisation : Etats-Unis

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

    Informations forums :
    Inscription : Décembre 2005
    Messages : 5 121
    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 confirmé
    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
    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 confirmé
    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
    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