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 :

{[L chaînées] premier élément}


Sujet :

C

  1. #1
    Membre confirmé Avatar de arkham55
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2010
    Messages : 179
    Par défaut {[L chaînées] premier élément}
    Bien le bonjour tout le monde!

    Alors voilà, j'ai tenté de créer une petite application simple afin de démarrer avec les listes chaînées, j'aimerai bien que vous y jetiez un oeil car j'ai dû bidouiller mon code pour qu'il fonctionne correctement. Notamment lorsque l'on ajoute des contacts à ma liste, j'ai du bidouiller car apparemment mon adresse de début (deb) posait problème. On pouvait le vérifier lors de la consultation, le premier contact était toujours un contact null (rien en guise de paramètres sous mandriva avec gcc, et il affichait des caractères et chemins d'accès avec CodeBlocks).
    J'utilise un fichier projet.dat afin de sérialiser mes contacts pour pouvoir les lire par la suite.
    Je vous laisse voyager à l'intérieur de ce petit monde :

    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
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
     
    struct contact
    {
    	char nom [22];
    	char prenom [22];
    	char adressenum [42];
    	char localitecp [32];
    	char email [22];
    	struct contact *suivant;
    };
     
    int main(){
        //Déclaration du fichier d'entrée et de résultat
        	FILE *fdat;
    	fdat = fopen("projet.dat", "r+"); //+r permet d'écrire et lire le meme fichier sans supprimer l'ancien
     
        	int proposition();
        	void consultation();
     
    	//Déclaration des variables et structures.
    	int choix, compteur=0, i,n=0;
        	char aide[22], x[1]; //variable d'aide à l'utilisation de la fct gets()
    	typedef struct contact contact;
     
        // typedef on définit la structure contact sous l'alias "contact", comme un nouveau type.
    	contact *deb;
    	contact *courant;
    	contact *suivant;
    	contact *nouveau;
    	//déclaration de la liste chaînee, avec un élément de début 'courant'
    	courant=malloc(sizeof(contact));
    	//on sauve l'adresse de l'élément de début de la liste.
    	deb=courant;
     
    	//Lecture anticipée
           	fscanf(fdat,"%s",&aide);
    	while(!feof(fdat))
    	{
     
    		suivant=malloc(sizeof(contact));
    		(*courant).suivant=suivant;
     
          	  	compteur++;
     
    		strcpy(courant->nom,aide);
              	fscanf(fdat,"%s",&courant->prenom);
                	fscanf(fdat,"%s",&courant->adressenum);
                	fscanf(fdat,"%s",&courant->localitecp);
                	fscanf(fdat,"%s",&courant->email);
     
    		fscanf(fdat,"%s",&aide);
    		if (feof(fdat))
    		{
    			(*courant).suivant=NULL;
    		}
    		else
    		{
    			courant=suivant;
    		}
         	} 
     
    	choix=proposition();
      	while (choix != 0){ //while de lecture, tq on entre pas 0, le pgm ne cesse de fonctionner
     
    		switch (choix){
     
    			case 1: //Consultation du carnet
     
                    	consultation();
                    	printf("Il y a %d contact(s) dans votre repertoire.\n", compteur);
                    	if(compteur!=0)//ne rien afficher s'il est vide.
    			{
    				courant = deb;
                    		n=1;
    				courant=courant->suivant;
                            	while(courant->suivant!=NULL)
                            	{
    					printf("Contact %d :\n-----------\n",n);
                                		printf ("Nom : %-20s ", courant->nom);
                                		printf ("Prenom : %-20s\n", courant->prenom);
                                		printf ("Adresse : %-40s ", courant->adressenum);
                                		printf ("%-30s\n", courant->localitecp);
                                		printf ("Mail : %-20s\n", courant->email);
                                		printf ("\n");
     
                                		courant=courant->suivant;
                                		n++;
                    		}
    				printf("Contact %d :\n-----------\n",n);
                                	printf ("Nom : %-20s ", courant->nom);
                                	printf ("Prenom : %-20s\n", courant->prenom);
                                	printf ("Adresse : %-40s ", courant->adressenum);
                                	printf ("%-30s\n", courant->localitecp);
                                	printf ("Mail : %-20s\n", courant->email);
                                	printf ("\n");
     
    			}
                            printf("-------------------------------------\n");
                            //le pgm est en pause.
    			system("pause");
     
                    	break;
     
    			case 2://Ajout d"un contact
     
    			/*if(compteur==1)
    			{*/
                   			nouveau = malloc(sizeof(contact));
    				courant->suivant=nouveau;
    				courant=nouveau;
     
    				courant->suivant=NULL;
     
    				printf("   __________________________________________  \n");
                    		printf("*/             *   *           *            \\*\n");
                    		printf("*|            * *     *** * * ***            |*\n");
                    		printf("*|            ***  *  * * * *  *             |*\n");
                   	 		printf("*|            * *  *  *** ***  **            |*\n");
                    		printf("*|            * * *                          |*\n");
               		     	printf("*|-------------------------------------------|*\n");
                    		printf("\n");
                    		printf ("Entrez son nom: (20) ");
                    		gets (x);// /n lu.
    				//gets (courant->nom);
    				scanf("%s",&courant->nom);
    				printf ("Entrez son prenom: (20) ");
    				gets(x);
    				//gets (courant->prenom);
    				scanf("%s",&courant->prenom);
    				printf ("Entrez son adresse et le numero: (40) ");
    				gets(x);
    				//gets (courant->adressenum);
    				scanf("%s",&courant->adressenum);
    				printf ("Entrez son code postal et sa localite: (30) ");
    				gets(x);
    				//gets (courant->localitecp);
    				scanf("%s",&courant->localitecp);
    				printf ("Entrez son adresse email: (20)");
    				gets(x);
    				//gets (courant->email);
    				scanf("%s",&courant->email);
     
    				printf("\n");
                    		printf("*|      Le contact %s %s bien enregistre     |*\n",courant->nom,courant->prenom);
    				compteur++;
    			break;
     
    			case 3://Suppression d"un contact
                    	printf("Supprimer un contact :");
    			break;
     
    			case 4://Rechercher un contact
    			    printf("Rechercher un contact :");
    			break;
     
    		}
    		choix=proposition();
    	}
     
     
    	if(compteur!=0)//rien a écrire si le répertoire est vide, soit compteur=0.
    	{
       		courant=deb;
    		courant=courant->suivant;
    		while(courant->suivant!=NULL)
    		{
    			fprintf(fdat,"%-s\n",courant->nom);
    			fprintf(fdat,"%-s\n",courant->prenom);
    			fprintf(fdat,"%-s\n",courant->adressenum);
    			fprintf(fdat,"%-s\n",courant->localitecp);
    			fprintf(fdat,"%-s\n",courant->email);
    			courant=courant->suivant;
    		}
    		fprintf(fdat,"%-s\n",courant->nom);
    		fprintf(fdat,"%-s\n",courant->prenom);
    		fprintf(fdat,"%-s\n",courant->adressenum);
    		fprintf(fdat,"%-s\n",courant->localitecp);
    		fprintf(fdat,"%-s\n",courant->email);
    		courant=courant->suivant;
     
    	}
     
    	return (0); //arret propre du pgm.
    }
     
    void consultation(){
        FILE *fdat;
        fdat=fopen("projet.dat", "r");
        printf("   ________________________________________________  \n");
        printf("*| * *                          *           *      |*\n");
        printf("*| * * ***  **     *** *** **  ***  ** *** ***  ** |*\n");
        printf("*| * * * *  *      *   * * * *  *  * * *    *   *  |*\n");
        printf("*| * * *** **      *** *** * *  ** *** ***  ** **  |*\n");
        printf("*|  *                                              |*\n");
        printf("  \\_______________________________________________/\n");
    }
     
    int proposition(){
        int res;
    	printf("   __________________________________________  \n");
    	printf("*|               * *                         |*\n");
    	printf("*|               *** *** **  * *             |*\n");
    	printf("*|               *** **  * * * *             |*\n");
    	printf("*|               * * *** * * ***             |*\n");
    	printf("*|               * *                         |*\n");
    	printf("*|-------------------------------------------|*\n");
    	printf("*|                                           |*\n");
    	printf("*| 1 ~  Consultation.                        |*\n");
    	printf("*| 2 ~  Ajout d'un contact.                  |*\n");
    	printf("*| 3 ~  Suppression d'un contact.            |*\n");
    	printf("*| 4 ~  Rechercher un contact.               |*\n");
    	printf("*| 0 ~  Quitter.                             |*\n");
    	printf("*\\___________________________________________/*\n");
    	printf("~  Entrez le numero correspondant votre choix:\n");
        scanf("%d",&res);
        //tant que l'ur ne rentre pas un nombre entre 1 et 5, il lui repose la question.
     
        while(res>5){
    	    printf("Entrez un numero entre 1 et 5: ");
            scanf("%d",&res);
        }
        return res;
    }

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    - Remet un peu d'ordre dans ton code : les prototypes et définitions de type sont mieux placés en tête.

    - Pourquoi consultation() utilise t-il fdat ? (Apparemment, la fonction ne sert à rien)

    - Tu procèdes de façon illogique avec ta lecture anticipée :
    Tu crées un contact avant de savoir si il existe ce qui va laisser le dernier créé dans la nature et occasionner une fuite mémoire (ou obliger sa destruction, ce que tu ne fais pas).

    - Il est intéressant d'améliorer la structure des données en regroupant les données concernant la liste.
    Comme tu insères en queue de liste, on peut conserver la tête et la queue de la liste pour la décrire ainsi que, pourquoi ne pas en profiter, le nombre d'éléments :
    (j'ai renommé le type contact en Contact)
    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
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    //----Prototypes ----------------------
    //...
    //-------------------------------------
    typedef struct contact
    {
    	char nom [22];
    	char prenom [22];
    	char adressenum [42];
    	char localitecp [32];
    	char email [22];
    	struct contact *suivant;
    }Contact;
    typedef struct
    {
       Contact * premier;
       Contact * dernier;
       int compteur;
    } Carnet;
    - Essaye de structurer un peu ton code en faisant des fonction assez courtes, il sera plus lisible et plus facile à travailler que ce main éléphantesque qui va encore grossir.
    Par exemple, en regroupant l'essentiel de ton code (commentaires dans le code)

    Pour la sortie :
    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
    //-------------------------------------
    void sauveContact (FILE * f, Contact const * contact)
    {
       // dans le fichier f
       fprintf(f,"%-s\n",contact->nom);
       fprintf(f,"%-s\n",contact->prenom);
       fprintf(f,"%-s\n",contact->adressenum);
       fprintf(f,"%-s\n",contact->localitecp);
       fprintf(f,"%-s\n",contact->email);
    }
    //-------------------------------------
    void afficheContact(Contact const * contact, int indice)
    {
      // sur la console
      printf("Contact %d :\n-----------\n",indice);
      printf ("Nom : %-20s ", contact->nom);
      printf ("Prenom : %-20s\n", contact->prenom);
      printf ("Adresse : %-40s ", contact->adressenum);
      printf ("%-30s\n", contact->localitecp);
      printf ("Mail : %-20s\n", contact->email);
      printf ("\n");
    }
    //-------------------------------------
    void listeCarnet (FILE * f, Carnet const * carnet)
    {
      // si f != stdout ou de NULL, la sortie a lieu sur le fichier f
      // et sinon sur la console
      Contact * courant ;
      int indice = 1;
      for(courant = carnet->premier ; courant != NULL; courant = courant->suivant)
      {
        if(f == stdout || f == NULL) afficheContact(courant, indice);
        else sauveContact(f,courant);
        indice ++;
      }
    }
    //-------------------------------------
    void ecrireFichier( char* nom, Carnet const * carnet)
    {
      FILE* fdat = fopen(nom, "w");
      if(fdat != NULL) // vérifier l'ouverture
      {
         listeCarnet(fdat, carnet);
         fclose(fdat); // Ecriture terminée
      }
      else {/* erreur d'ouverture à traiter */}
    }
    Et pour l'entrée :

    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
    //-------------------------------------
    void entrerContact(Contact  * contact)
    {
       // A partir du clavier
       // cette fonction est à travailler pour améliorer la sécurité de la 
       // lecture des données.
       printf("   __________________________________________  \n");
       printf("*/             *   *           *            \\*\n");
       printf("*|            * *     *** * * ***            |*\n");
       printf("*|            ***  *  * * * *  *             |*\n");
       printf("*|            * *  *  *** ***  **            |*\n");
       printf("*|            * * *                          |*\n");
       printf("*|-------------------------------------------|*\n");
       printf("\n");
       printf ("Entrez son nom: (20) ");
       scanf("%20s",contact->nom);
       printf ("Entrez son prenom: (20) ");
       scanf("%20s",contact->prenom);
       printf ("Entrez son adresse et le numero: (40) ");
       scanf("%40s",contact->adressenum);
       printf ("Entrez son code postal et sa localite: (30) ");
       scanf("%30s",contact->localitecp);
       printf ("Entrez son adresse email: (20)");
       scanf("%20s",contact->email);
       printf("\n");
       printf ("Nouveau contact : \n");
       afficheContact(contact, 0);
    }
    //-------------------------------------
    void lireContact(FILE * f, Contact * contact, char * nom)
    {
       // sur un fichier
       strcpy(contact->nom,nom);
       fscanf(f,"%s",contact->prenom);
       fscanf(f,"%s",contact->adressenum);
       fscanf(f,"%s",contact->localitecp);
       fscanf(f,"%s",contact->email);
    }
    //-------------------------------------
    Contact * nouveauContact(FILE * f, Carnet * carnet)
    {
      // si f != stdin ou de NULL, la lecture a lieu sur le fichier f
      // et sinon sur la console
      char aide[22];
      Contact * nouveau = NULL;
      if(f == stdin || f == NULL || fscanf(f,"%21s",aide)!= EOF)
      {
         // Allouer un nouveau contact
         nouveau = malloc(sizeof(Contact));
         if(nouveau != NULL)   // allocation réussie
         {  
            // mettre les champs à jour
            if( f == stdin || f == NULL) entrerContact(nouveau);
            else lireContact(f,nouveau,aide);
            // faire le chainage
            nouveau->suivant = NULL;  
            if(carnet->premier == NULL) carnet->premier = nouveau;
            else carnet->dernier->suivant = nouveau;
            carnet->dernier = nouveau;
            carnet->compteur ++;
         }
         else {/* erreur d'allocation à traiter*/}
      }
      return nouveau;  // NULL en cas de EOF ou d'erreur d'allocation
    }
    //-------------------------------------
    void lireFichier( char* nom, Carnet * carnet)
    {
     FILE*  fdat = fopen(nom, "r");
     if(fdat != NULL) // vérifier l'ouverture
     {
       while(nouveauContact(fdat, carnet)!= NULL) {}
       fclose(fdat); // lecture terminée
     }
     else {/* erreur d'ouverture à traiter */}
    }
    ce qui nous donne :

    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
    int main(void)
    {
     int choix;
     Carnet  carnet = {NULL, NULL, 0};
     lireFichier("projet.dat",&carnet);
     do
     {
        choix = proposition();
        switch(choix)
        {
           case 0 : break;
           case 1 : listeCarnet(NULL,&carnet); // NULL ou stdout -> sur la console
                    break;
           case 2 : nouveauContact(NULL, &carnet);  // NULL ou stdin ->sur le clavier
                    break;
     
           //....
        }
      } while(choix != 0);
      ecrireFichier("projet.dat",&carnet);
      return 0;
    }

  3. #3
    Membre confirmé Avatar de arkham55
    Profil pro
    Inscrit en
    Mars 2010
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2010
    Messages : 179
    Par défaut
    Effectivement mon code est énorme ce qui s'expliquait pas mon ignorance quant aux passage de structure en argument de fonction ^^"
    J'ai retravaillé sur le code ce week-end, j'ai remis de l'ordre dans tout ça et je vais simplifier le tout grâce aux fonctions. Merci pour ton code, je vais en faire un moi-même ce qui me familiarisera avec les en-têtes et les déclarations des fonctions. En tout cas je te remercie bien pour ton aide, elle m'est précieuse pour avancer dans le bon sens =)
    Je posterai bientôt mon code et ferai part des difficultés que j'aurai pu croiser.
    En tout cas, pour le passage de structure en argument, ça devrait aller maintenant.
    Encore merci, à bientôt!

  4. #4
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    ... ce qui s'expliquait pas mon ignorance quant aux passage de structure en argument de fonction ...
    Une petite précision :
    Dans le code exemple proposé, ce ne sont pas les structures qui sont passées en argument, mais leur adresse.
    Il est possible également de passer les structures elles-mêmes, et on obtient dans la fonction une copie de la structure passée en argument (comme toujours en C, on obtient une copie de l'argument).

    Passer l'adresse de la structure, plutôt que la structure elle-même peut être motivé par deux raisons :
    - On veut modifier la structure
    - On ne veut pas modifier la structure, mais comme une structure est un objet qui peut être volumineux, on veut s'épargner le temps et la place de la recopie de l'argument. Dans ce cas, le qualificatif const est utile.

    Globalement, soit pour une raison ou pour l'autre, il s'en suit que les structures sont le plus souvent passées indirectement par leur adresse.


    ... je vais en faire un moi-même ce qui me familiarisera avec ...
    C'est une bonne idée.

Discussions similaires

  1. Réponses: 10
    Dernier message: 16/01/2011, 22h16
  2. Sélectionner le premier élément d'une ComboBox
    Par deubal dans le forum Composants VCL
    Réponses: 2
    Dernier message: 21/11/2005, 10h32
  3. [xslt] Limiter un for-each aux x premiers éléments
    Par camboui dans le forum XSL/XSLT/XPATH
    Réponses: 13
    Dernier message: 18/11/2005, 16h09
  4. Est-il possible de retourner au premier élément ?
    Par magic8392 dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 28/09/2005, 14h15
  5. Réponses: 2
    Dernier message: 11/01/2005, 14h10

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