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 :

Comparaison sur liste chainée


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Février 2007
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 39
    Points : 12
    Points
    12
    Par défaut Comparaison sur liste chainée
    bonjour à tous,
    Je suis en ce moment sur un projet d'IA qui utilise 2 structures:
    base de règle et base de faits:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    typedef struct BDF
    {
    	char nom_du_fait [20];
    	struct BDF *suiv;
     
    }ST_BDF;
     
     
    typedef struct BDR
    {
    	char nom_poisson[15];
    	struct BDR *suiv;
    	ST_BDF *fait;
    }ST_BDR;
    voici mon petit soucis:
    je commence par créer une règle, tout se passe bien à l'affichage.
    je créer des fait, pareil pas de soucis .
    mon proble intervient dans la fonction qui vient faire le chainage avant.
    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
    void test(ST_BDR *r_tete, ST_BDF *f_tete)
    {
    	ST_BDR *r_courant;
    	ST_BDF *f_courant;
    	r_courant=r_tete;
    	f_courant=f_tete;
    	int trouve=0;
    	do
    	{
    		trouve=comparif(r_courant,f_tete);	/*le pb intervien dans cette fonction*/
    		if (trouve==1)
    		{
    			f_tete=insertnouvofait(f_tete,r_courant);
    			printf("\nconclusion:%s",r_courant->nom_poisson);
    		}
    		r_courant=r_courant->suiv;
    	}while(r_courant!=NULL);
    	printf("\ntoutes les règles ont été parcourues\n");
    }
    voici la fonction de comparatif:
    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
    int comparif(ST_BDR *r_courant, ST_BDF *f_tete)
    {
    	ST_BDF*f_courant=f_tete;
    	ST_BDR*regle=r_courant;
    	int trouve=0;
    	int ok=0;
    	do
    	{
    		ok=0;
    		regle=r_courant;
    		do
    		{
    			if((strcmp(regle->fait->nom_du_fait,f_courant->nom_du_fait))==0)
    			{
    				ok=1;
    			}
    			else
    			{
    				ok=0;
    				f_courant=f_courant->suiv;/*pas de modif dans f_tete*/
    			}
    		}while( f_courant!=NULL && ok==0);
    		if (ok==0)
    		{
    			return 0;
    		}
     
    		f_courant=f_tete;
    		regle->fait=regle->fait->suiv;/*le pb est localisé ici, il modifie mon paramètre r_courant que je passe à la fonction*/
    	}while(regle->fait!=NULL);
    	regle=r_courant;
    	return 1;
    }
    comme je l'ai indiqué, lorsque j'effecture cette instruction ma variable r_courant est elle aussi modifiée. je ne comprend pas pourquoi (vérifier en débug et lors de l'affichage de la base de règle). f_tete(correspondant à ma base de fait n'est pas modifié) lors f_courant=f_courant->suiv;

    merci pour vos réponses, si je n'ai pas assez expliqué faite moi part de ce que vous n'avez pas compris.

  2. #2
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		regle->fait=regle->fait->suiv;/*le pb est localisé ici, il modifie mon paramètre r_courant que je passe à la fonction*/
    c'est normal, il te faut travailler avec une copie de regle->fait si tu ne veux pas modifier sa valeur.
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  3. #3
    Membre à l'essai
    Inscrit en
    Février 2007
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 39
    Points : 12
    Points
    12
    Par défaut
    salut et merci pour la réponse mais je ne comprend pas se que tu veux dire.
    pourrai tu me donner un exemple, j'ai essayer de recréer une variable r_regle=regle;
    en agissant sur r_regle mais sa me modifie toujour le paramètre r_courant de ma fonction.


    Citation Envoyé par Dark_Ebola
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		regle->fait=regle->fait->suiv;/*le pb est localisé ici, il modifie mon paramètre r_courant que je passe à la fonction*/
    c'est normal, il te faut travailler avec une copie de regle->fait si tu ne veux pas modifier sa valeur.

  4. #4
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    Par défaut
    en fait, soit tu retournes une valeur en copiant l'argument en entrée par valeur ( tu renvois une copie modifiée, pas la variable d'entrée, qui elle ne sera jamais modifiée) ou alors tu passes ça par pointeur en modifiant la valeur pointée dans le bloc de la fonction.

    Le C ne change pas les arguments des fonctions passés par valeur, ce qui fait que la valeur initiale de n'importe quel objet ne sera pas modifié après n'importe quel appel de la fonction si celui ci est passé par valeur et non par référence.

    D'après DarkEbolah, j'ai l'impression que le problème vient de là.

  5. #5
    Membre à l'essai
    Inscrit en
    Février 2007
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 39
    Points : 12
    Points
    12
    Par défaut
    Citation Envoyé par kromartien
    en fait, soit tu retournes une valeur en copiant l'argument en entrée par valeur ( tu renvois une copie modifiée, pas la variable d'entrée, qui elle ne sera jamais modifiée) ou alors tu passes ça par pointeur en modifiant la valeur pointée dans la fonction.

    Le C ne change passe les arguments des fonctions en les copiant par valeur, ce qui fait que la valeur initiale de n'importe quel objet ne sera pas modifié à la sortie de la fonction si celui ci est passé par valeur et non par référence.

    D'après DarkEbolah, j'ai l'impression que le problème vient de là.
    oups c'est sympa comme théorie mais désolé il me faut un exemple pour comprendre sinon je risque de resté bloqué:
    voici ma 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
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    int comparif(ST_BDR *r_courant, ST_BDF *f_tete)
    {
    	ST_BDF*f_courant=f_tete;
    	ST_BDR*regle = NULL;
    	regle=r_courant;
    	int trouve=0;
    	int ok=0;
    	do
    	{
    		ok=0;
    		regle=r_courant;
    		do
    		{
    			if((strcmp(regle->fait->nom_du_fait,f_courant->nom_du_fait))==0)
    			{
    				ok=1;
    			}
    			else
    			{
    				ok=0;
    				f_courant=f_courant->suiv;//pas de modif de mon parametre
    			}
    		}while( f_courant!=NULL && ok==0);
    		if (ok==0)
    		{
    			return 0;
    		}
     
    		f_courant=f_tete;
    		regle->fait=regle->fait->suiv; // le parametre r_courant est modifié
    	}while(regle->fait!=NULL);
    	return 1;
    }
    comme j'ai pu le constater lorsque j'arrive ici mon parametre d'entrée r_courant est modier ainsi que regle:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    regle->fait=regle->fait->suiv;
    alors que lorsque j'effectue
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    f_courant=f_courant->suiv;;
    mon parametre f_tete n'est pas modifier.

    ces deux actions sont pourtant identique non??

    j'ai du mal à saisir j'aprécierai une illustration.

    merci pour votre attention.

  6. #6
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    Citation Envoyé par kromartien
    en fait, [...]

    D'après DarkEbolah, j'ai l'impression que le problème vient de là.
    j'ai rien compris

    simplement: en C, il n'existe que des passages d'arguments par copie
    copie d'un int, d'un char, d'un pointeur ...

    pour ton probléme:
    f_courant est une variable locale de type pointeur sur ST_BDF initialisée a la valeur passée en argument f_tete.
    quand tu modifie f_courant, tu modifie une variable locale.

    ST_BDR*regle = r_courant; <= même chose qu'au dessus.

    regle est bien une variable locale.
    tu peux modifier regle pour qu'il pointe sur une structure differente, par contre les membres de la structure regle sont LES MEMES que celle de la structure r_courant !
    regle->fait, n'est pas du tout une variable locale!
    donc en modifiant regle->fait, tu modifie ta structure

    j'espere que c'est clair.
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  7. #7
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    Par défaut
    oui , en fait l'exemple, c'est que si on veut modifier la valeur d'une variable, par exemple on veut faire x=x².

    La première méthode c'est le passage par valeur, on est obligé de faire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    double carre(double x)
    {
            return x*x;
    }
     
    int main(void)
    {
            double x = 2;
            x=carre(x);
    }
    Il n'y a pas le choix, il faut faire l'affectation.

    Sinon, la deuxième solution est le passage par référence (ou par adresse, ou par pointeur) :
    code strictement équivalent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void carre(double * x)
    {
            *x= (*x) * (*x);
    }
     
    int main(void)
    {
            double x = 2;
            carre(x);
    }
    Le résultat est le même, mais pas la méthode. La première implique des recopis de valeurs multiples.

    En fait, cette erreur est courant en voulant classer un tableau par exemple.
    On veut échanger deux cases d'un tableu avec une fonction echange.

    La bonne méthode est de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void echange(int * val_1, int * val_2)
    {
            int var_temp = *val_1;
            *val_1 = *val_2;
            *val_2 = var_temp;
    }
    Cette fonction marchera, et les deux éléments du tableau passés par adresse seront auront bien échangés leur place.

    Par contre, en faisant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void echange(int val_1, int val_2)
    {
            int var_temp = val_1;
            val_1 = val_2;
            val_2 = var_temp;
    }
    Le tableau qui contient les entiers val_1 et val_2 n'aura pas changé d'un iota, car les variables val_1 et val_2 dans la fonction sont complètement séparées du reste du programme, à cause de la recopie des arguments par valeur du langage C.

    Les valeurs de val_1 et de val_2 qui sont définies dans le corps du programme ne seront jamais modifiées à l'intérieur d'une fonction si val_1 et val_2 sont directement passés en argument par valeur, et non par référence.

    C'est tout ce que je voulais dire.

  8. #8
    Membre expérimenté
    Avatar de granquet
    Profil pro
    Étudiant
    Inscrit en
    Octobre 2005
    Messages
    1 201
    Détails du profil
    Informations personnelles :
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2005
    Messages : 1 201
    Points : 1 421
    Points
    1 421
    Par défaut
    en C il n'y as pas de passage par référence, on "simule" le passage par référence en faisant un passage par valeur de l'adresse de la variable, qu'on réceptionne dans un pointeur.
    click my www
    ............|___
    ...................\
    .................._|_
    ..................\ /
    ..................."

  9. #9
    Membre éprouvé

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 116
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 116
    Points : 1 111
    Points
    1 111
    Par défaut
    Oui, c'est bien la recopie systématique par valeur des arguments, et les variables locales à la fonction invisibles dans le reste du programme qu'il faut retenir. C'est toujours une recopie par valeur.

  10. #10
    Membre à l'essai
    Inscrit en
    Février 2007
    Messages
    39
    Détails du profil
    Informations forums :
    Inscription : Février 2007
    Messages : 39
    Points : 12
    Points
    12
    Par défaut
    bonsoir à tous, je suis passer vous remercier pour l'aide ainsi que les explications qui m'ont aidés à comprendre mon erreur et surtout comment y remédier.

    voila merci le pb est résolu

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

Discussions similaires

  1. Exercice sur liste chainée
    Par manou756011 dans le forum C
    Réponses: 1
    Dernier message: 04/05/2014, 21h16
  2. aide sur liste chainé
    Par hamma2009 dans le forum Langage
    Réponses: 2
    Dernier message: 11/05/2010, 12h05
  3. Tri sur liste chainée
    Par SevSof dans le forum C
    Réponses: 16
    Dernier message: 27/05/2007, 00h45
  4. [Débutant] Pointeur sur liste chainée
    Par HaTnuX dans le forum C
    Réponses: 2
    Dernier message: 02/12/2006, 17h53

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