Problème liste chainée

Problème liste chainée - C - Programmation

Marsh Posté le 05-04-2005 à 10:54:13    

Je n'arrive pas à comprendre pourquoi j'ai une erreur sous dev-c++ avec mon programme utilisant des listes simplement chainées.
 
Mon code :
 
Déclaration de mon pointeur :

Code :
  1. typedef struct candidature {
  2.     chaine nom,prenom,mail,tel;
  3.     int numero, num_offre,num_secteur;
  4.     date dt_cand;
  5.     struct candidature * suiv;
  6. }candidature;
  7. candidature *tete_cand = NULL;


 
Ma fonction d'ajout :

Code :
  1. void ajout_cand(){
  2.      candidature *c;
  3.      c=(candidature*)malloc(sizeof(candidature)); 
  4.      header_menu("AJOUT D'UNE CANDIDATURE" );
  5.      printf("Num de la candidature : " );
  6.      scanf("%d", &c->numero);
  7.      printf("Votre nom : " );
  8.      scanf("%s", &c->nom);
  9.      printf("Votre prenom : " );
  10.      scanf("%s", &c->prenom);
  11.      printf("Votre tel : " );
  12.      scanf("%s", &c->tel);
  13.      printf("Votre mail : " );
  14.      scanf("%s", &c->mail);
  15.    
  16.      // S'il n'y a aucun élément dans la liste
  17.      if (tete_cand==NULL) {
  18.         // La tête de la liste prend la valeur du nouvel élément inséré
  19.         tete_cand = c ;
  20.         // L'élément suivant celui inséré est nul
  21.         c->suiv = NULL;
  22.         printf("Premier element enregistre" );
  23.         system("PAUSE" );                                     
  24.      }
  25.      // S'il y a déjà des éléments dans la liste
  26.      else if (tete_cand!=NULL) {
  27.         // Utilisation d'un nouveau pointeur
  28.         candidature *cCourant;
  29.         cCourant=(candidature*)malloc(sizeof(candidature));
  30.         // On parcour la liste jusqu'a ce que l'on arrive au dernier élément
  31.         while (cCourant->suiv!=NULL) {
  32.               cCourant = cCourant->suiv;
  33.         }
  34.         // Une fois arrivé au dernier élément, le suivant est le nouveau pointeur
  35.         // et le suivant du nouveau pointeur est null
  36.         cCourant->suiv = c;
  37.         c->suiv = NULL;
  38.         printf("Element enregistre" ); 
  39.         system("PAUSE" );     
  40.      }
  41. }


 
 
Lors de l'ajout du premier élément, tout se passe bien. Mais lorsque je veux insérer un deuxième élément, j'ai une "erreur du programme, truc.exe a généré une erreur..."
 
Je vois bien que c'est ma boucle while qui pose problème, mais je ne comprend pas pourquoi.
 
Merci bien  :jap:


---------------
Cptn.Barberousse
Reply

Marsh Posté le 05-04-2005 à 10:54:13   

Reply

Marsh Posté le 05-04-2005 à 10:56:30    

scanf("%s", &c->nom);
 
....
 
 
fgets(c->nom, sizeof c->nom, stdin);
 
 
et d'ailleurs, c'est quoi 'chaine' ?

Reply

Marsh Posté le 05-04-2005 à 11:01:15    

Chaine c'est :
 

Code :
  1. typedef char chaine[30];


 
Et date :
 

Code :
  1. typedef struct date {
  2.     int jj,mm,aa;
  3. }date;


Message édité par Sinan le 05-04-2005 à 11:20:10

---------------
Cptn.Barberousse
Reply

Marsh Posté le 05-04-2005 à 12:10:56    

J'ai déjà eu le même problème :
 

Code :
  1. printf("Votre nom : " );
  2.       scanf("%s", c->nom);
  3.       printf("Votre prenom : " );
  4.       scanf("%s", c->prenom);
  5.       printf("Votre tel : " );
  6.       scanf("%s", c->tel);
  7.       printf("Votre mail : " );
  8.       scanf("%s", c->mail);


 
Essaie en enlevant les "&" pour les "%s". Cela ne va que pour les variables numériques, pas les chaînes de caractères.
 
"c->nom" est déjà une adresse...


Message édité par calogerogigante le 05-04-2005 à 12:14:14
Reply

Marsh Posté le 05-04-2005 à 12:15:39    

calogerogigante a écrit :

Essaie en enlevant les "&" pour les "%s". Cela ne va que pour les variables numériques, pas les chaînes de caractères.


Ton "explication" va beaucoup l'aider...
C'est surtout qu'un scanf (cf. man) demande l'adresse de la variable dans laquelle stocker la valeur.

Reply

Marsh Posté le 05-04-2005 à 12:19:15    

Tu chicanes là...
C'est ce que j'ai voulu dire...
Juste avant ton post, j'ai rajouté

Code :
  1. "c->nom" est déjà une adresse...


 
Si c'est pas clair pour celui qui a posé la question, il suffit de redemander...
 
Et je détaillerai... Mais je ne vois pas en quoi j'étais pas clair..


Message édité par calogerogigante le 05-04-2005 à 12:20:05
Reply

Marsh Posté le 05-04-2005 à 12:20:16    

calogerogigante a écrit :

J'ai déjà eu le même problème :
 

Code :
  1. printf("Votre nom : " );
  2.       scanf("%s", c->nom);
  3.       printf("Votre prenom : " );
  4.       scanf("%s", c->prenom);
  5.       printf("Votre tel : " );
  6.       scanf("%s", c->tel);
  7.       printf("Votre mail : " );
  8.       scanf("%s", c->mail);


 
Essaie en enlevant les "&" pour les "%s". Cela ne va que pour les variables numériques, pas les chaînes de caractères.
 
"c->nom" est déjà une adresse...


 
Ca ne change rien :(
Mon erreur ne concernerait pas plutôt l'utilisation des pointeurs ?


---------------
Cptn.Barberousse
Reply

Marsh Posté le 05-04-2005 à 12:20:52    

typiquement: un char peut ne pas être considéré comme une variable numérique, et pourtant on est obligé de passer son adresse

Reply

Marsh Posté le 05-04-2005 à 12:24:42    

Y'a pas un problème dans ta structure des if ??

Code :
  1. if (tete_cand==NULL) {
  2.     ...                                     
  3.      }
  4. else if (tete_cand!=NULL) {


 
Si c'est NULL, on va dans le 1er if,
 
si c'est pas NULL, tu testes (tete_cand != NULL)
mais à cet endroit, tete_cand est déjà différent de NULL.
 
Sinon, à part ça, je vois rien qui pourrait déconner... Je regarde encore...
 
J'essaie juste de t'aider... hein ? J'espère que je suis un peu plus clair...
;-)


Message édité par calogerogigante le 05-04-2005 à 12:32:27
Reply

Marsh Posté le 05-04-2005 à 12:26:29    

Enfin.. Là c'est vrai que je suis peut-être pas clair...
;-)

Reply

Marsh Posté le 05-04-2005 à 12:26:29   

Reply

Marsh Posté le 05-04-2005 à 12:28:41    

Cela ne fait-il pas double emploi ?
 

Code :
  1. candidature *cCourant;
  2.          cCourant=(candidature*)malloc(sizeof(candidature));


 
Ou je dis encore des bêtises ?
 
Et je ne vois pas où, dans ton programme, le pointeur
"cCourant"
lors de sa création, à quel endroit est-il rattaché à la liste chaînée ?
Du coup, il se plante pour les "cCourant->Suiv" !!


Message édité par calogerogigante le 05-04-2005 à 13:16:00
Reply

Marsh Posté le 05-04-2005 à 13:12:03    

N'alloue rien pour cCourant
égale-le plutot à tete_cand car comme calogerogigante, je dis que ta variable à beau être initialisée, elle n'en est pas pour le moins non rattachée à ta liste chainée...


---------------
iteme.free.fr | Mon feedback
Reply

Marsh Posté le 05-04-2005 à 13:25:22    

Moktar1er a écrit :

typiquement: un char peut ne pas être considéré comme une variable numérique, et pourtant on est obligé de passer son adresse


Ben si. Un char est une variable numérique entière. Seul problème, on ne sait pas si il est signé ou non signé. Si c'est important, on ajoute signed ou unsigned.
 
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-04-2005 à 13:52:54    

Sinan a écrit :

Je n'arrive pas à comprendre pourquoi j'ai une erreur sous dev-c++ avec mon programme utilisant des listes simplement chainées.

Code :
  1. candidature *tete_cand = NULL;




Pas besoin de globale. Si tu dois faire 2 listes, tu vas écrire le code 2 fois ?


#include <stdlib.h>
#include <stdio.h>
 
typedef char chaine[30];
 
typedef struct date
{
   int jj, mm, aa;
}
date;
 
typedef struct candidature
{
   chaine nom, prenom, mail, tel;
   int numero, num_offre, num_secteur;
   date dt_cand;
   struct candidature *suiv;
}
candidature;
 
 
static void header_menu (char const *s)
{
   puts (s);
}
 
 
candidature *ajout_cand (candidature * tete_cand)
{
   candidature *c = malloc (sizeof *c);
   if (c != NULL)
   {
      header_menu ("AJOUT D'UNE CANDIDATURE" );
      printf ("Num de la candidature : " );
      scanf ("%d", &c->numero);
      printf ("Votre nom : " );
      scanf ("%s", c->nom);
      printf ("Votre prenom : " );
      scanf ("%s", c->prenom);
      printf ("Votre tel : " );
      scanf ("%s", c->tel);
      printf ("Votre mail : " );
      scanf ("%s", c->mail);
       
      c->suiv = NULL;
 
      // S'il n'y a aucun élément dans la liste
      if (tete_cand == NULL)
      {
         // La tête de la liste prend la valeur du nouvel élément inséré
         tete_cand = c;
         // L'élément suivant celui inséré est nul
         printf ("Premier element enregistre\n" );
      }
      // S'il y a déjà des éléments dans la liste
      else
      {
         // Utilisation d'un nouveau pointeur
         candidature *cCourant = tete_cand;
         // On parcour la liste jusqu'a ce que l'on arrive au dernier élément
         while (cCourant->suiv != NULL)
         {
            cCourant = cCourant->suiv;
         }
         // Une fois arrivé au dernier élément, le suivant est le nouveau pointeur
         // et le suivant du nouveau pointeur est null
         cCourant->suiv = c;
         printf ("Element enregistre\n" );
      }
   }
   return tete_cand;
}
 
void list (candidature * c)
{
   if (c != NULL)
   {
      printf ("%d\n", c->numero);
      list (c->suiv);
   }
}
 
void clean (candidature * c)
{
   if (c != NULL)
   {
 
      clean (c->suiv);
      free (c);
   }
}
 
int main (void)
{
   /* 1er */
   candidature *tete_cand = ajout_cand (NULL);
   
   /* autres */
   ajout_cand (tete_cand);
   ajout_cand (tete_cand);
 
   list (tete_cand);
   clean (tete_cand);
 
   return 0;
}


 
Et pour les saisies, je te conseille ceci:
 
http://mapage.noos.fr/emdel/notes.htm#saisie


Message édité par Emmanuel Delahaye le 05-04-2005 à 14:25:06

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-04-2005 à 13:53:51    

le pb vient du 2ème malloc qui ne devrait pas y être et dont le cCourant->suiv vaut n'importe quoi (non initialisé)...  
 
il faut à la place de :

Code :
  1. cCourant=(candidature*)malloc(sizeof(candidature));


juste faire :

Code :
  1. cCourant=tete_cand;


 
Sinon regroupe ton c->suiv=NULL dans l'initialisation de ta struct candidature...
 
++
 
EDIT : ouuupppss grillé


Message édité par dreameddeath le 05-04-2005 à 13:55:13
Reply

Marsh Posté le 05-04-2005 à 14:06:52    

Emmanuel Delahaye a écrit :

Ben si. Un char est une variable numérique entière. Seul problème, on ne sait pas si il est signé ou non signé. Si c'est important, on ajoute signed ou unsigned.


merde tu me casses mon coup là :D
nan je voulais qu'il détaille un peu plus ce qu'il voyait comme différence entre une "variable numérique" et une variable de type chaîne de caractères

Reply

Marsh Posté le 05-04-2005 à 14:22:09    

dreameddea th -> pas compris ta 2eme remarque  
 
J'ai fait les modifs et j'ai toujours la même erreur. Jme demande si ça vient pas de dev c++ parce que là je bloque :o
 
 

Code :
  1. void ajout_cand(){
  2.      candidature *c;
  3.    
  4.      c=(candidature*)malloc(sizeof(candidature)); 
  5.      header_menu("AJOUT D'UNE CANDIDATURE" );
  6.      printf("Num de la candidature : " );
  7.      scanf("%d", &c->numero);
  8.      printf("Votre nom : " );
  9.      fgets(c->nom, sizeof c->nom, stdin);
  10.      scanf("%s", c->nom);
  11.      printf("Votre prenom : " );
  12.      scanf("%s", c->prenom);
  13.      printf("Votre tel : " );
  14.      scanf("%s", c->tel);
  15.      printf("Votre mail : " );
  16.      scanf("%s", c->mail);
  17.      // S'il y a déjà des éléments dans la liste
  18.      if (tete_cand!=NULL) {
  19.         // Utilisation d'un nouveau pointeur
  20.         candidature *cCourant;
  21.         cCourant=tete_cand;
  22.         // On parcour la liste jusqu'a ce que l'on arrive au dernier élément
  23.         while (cCourant!=NULL) {
  24.               cCourant = cCourant->suiv;
  25.         }
  26.         // Une fois arrivé au dernier élément, le suivant est le nouveau pointeur
  27.         // et le suivant du nouveau pointeur est nul
  28.         cCourant->suiv = c;
  29.         c->suiv = NULL;
  30.         printf("Element enregistre" ); 
  31.         system("PAUSE" );     
  32.      }
  33.      // S'il n'y a aucun élément dans la liste
  34.      else if (tete_cand==NULL) {
  35.         // La tête de la liste prend la valeur du nouvel élément inséré
  36.         tete_cand = c ;
  37.         // L'élément suivant celui inséré est nul
  38.         c->suiv = NULL;
  39.         printf("Premier element enregistre" );
  40.         system("PAUSE" );                                     
  41.      }
  42. }


Message édité par Sinan le 05-04-2005 à 14:22:33

---------------
Cptn.Barberousse
Reply

Marsh Posté le 05-04-2005 à 14:27:21    

Sinan a écrit :

J'ai fait les modifs et j'ai toujours la même erreur. Jme demande si ça vient pas de dev c++ parce que là je bloque :o


Aucun problème avec le code que j'ai posté (Testé avec Dev-C++ 4.9.9.0)
 
Compare ton code:


        // On parcour la liste jusqu'a ce que l'on arrive au dernier élément
        while (cCourant!=NULL) {
              cCourant = cCourant->suiv;
        }


avec le mien:


         // On parcour la liste jusqu'a ce que l'on arrive au dernier élément
         while (cCourant->suiv != NULL)
         {
            cCourant = cCourant->suiv;
         }


Vu la différence ? On cherche le dernier élément, pas celui qui vaut NULL...
 
sinon la suite ...

cCourant->suiv = c;


...invoque un comportement indéfini car 'cCourant' vaut NULL...
 
D'ailleurs, à cet endroit, ton code original était bon. Pourquoi l'as-tu modifié ?


Message édité par Emmanuel Delahaye le 05-04-2005 à 14:34:36

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-04-2005 à 14:29:01    

Code :
  1. while(cCourant!=NULL){
  2.     cCourant=cCourant->suiv;
  3. }
  4. // A ton avis ici que vaut cCourant si tu es sorti du while?


Message édité par Moktar1er le 05-04-2005 à 14:29:43
Reply

Marsh Posté le 05-04-2005 à 14:43:55    

boulaÿ [:tinostar]  
 
Effectivement, avec un
 
        while (cCourant->suiv!=NULL) {
              cCourant = cCourant->suiv;
        }
 
J'ai aucun soucis. Jcomprend pas pourquoi j'ai pas tilté avant :o
J'ai perdu 1/2 journée avec ste connerie  [:tinostar]  
 
Merci à vous  :jap:


---------------
Cptn.Barberousse
Reply

Marsh Posté le 05-04-2005 à 14:45:15    

Par contre emmanuel ton code marche pas avec mon dev-c++ 4.9.9.1 j'ai une erreur sur la ligne 30
candidature *c = malloc (sizeof(*c));


---------------
Cptn.Barberousse
Reply

Marsh Posté le 05-04-2005 à 14:54:07    

Sinan a écrit :

Par contre emmanuel ton code marche pas avec mon dev-c++ 4.9.9.1 j'ai une erreur sur la ligne 30
candidature *c = malloc (sizeof(*c));


Vérifie que tu es bien en C et non en C++. L'extension du source doit être '.c' (et non '.C' ni '.cpp').


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le 05-04-2005 à 15:15:37    

autant pour moi, c'était enregistré en cpp :jap:


---------------
Cptn.Barberousse
Reply

Marsh Posté le 05-04-2005 à 16:35:06    

Sinan a écrit :

autant pour moi, c'était enregistré en cpp :jap:


LE FOUET !!!


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed