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 :

Problème de programme


Sujet :

C

  1. #21
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    Dernière faveure, voici mon programme maintenant, voyez-vous d'autres erreurs ou mauvaises syntaxes, à par scanf(), niveau sécurité:

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h>
     
     
    typedef struct Voiture        //Définition de la structure Voiture
    {
            char marque[20];
            char modele[20];
            char puissance[3];
            struct Voiture *suivant;
    }Voiture;
     
     
    void Creer (Voiture **p);
    void Creer_vide (Voiture **p);
    void Ecrire (Voiture *p);
    void Lecture (Voiture **p);
    void Afficher (Voiture *p);
     
    int main(void)                 
    {      
     
          Voiture *tete=NULL;
          Lecture(&tete);
    	  Afficher(tete);
    	  //Creer_vide (&tete);
    	  Creer (&tete);
    	  Afficher(tete);
    	  Ecrire(tete);
          free(tete); tete=NULL; /* il faut liberer la memoire. C'est tres imporant */
    	  return EXIT_SUCCESS;     
     }
     
    void Creer (Voiture **p)        //Définition de la fonction Creer qui est de type Voiture
    {		
    		Voiture *voit=malloc(sizeof *voit);
    		if(voit!= NULL)
    		{
    			printf("Entrez la marque :\n");
    			scanf("%s",(voit->marque));
    			printf("Entrez le modele :\n");
    			scanf("%s",(voit->modele));
    			printf("Entrez la puissance :\n");
    			scanf("%s",(voit->puissance));
    			voit->suivant=*p;
    			*p=voit;
    		}        
    }
    void Ecrire(Voiture *p)
    {	
    	FILE *fic = NULL;
    	fic = fopen("c:\\test.txt", "wb");
    	while(p!=NULL)
    	{
    		fwrite(p,sizeof(*p),1,fic);
    		puts(p->marque);
    		p=p->suivant;
    	}
    	fclose(fic);
    	fic=NULL;
    }
    void Lecture (Voiture **p)
    {	
    	Voiture *voit=malloc(sizeof *voit);
    	FILE *fic = NULL;
    	fic = fopen("c:\\test.txt", "rb");
    	while (fread(voit,sizeof(*voit),1,fic)!=NULL)
    	{
    		puts(voit->marque);
    		voit->suivant=*p;
    		*p=voit;
    		voit=malloc(sizeof *voit);
    	}
    	fclose(fic);
     
    }
     
    void Afficher (Voiture *p)
    {
    	while (p!= NULL)
    	{
    	printf("%s %s %s\n",p->marque,p->modele,p->puissance);
    	p=p->suivant;
    	}
    }
    void Creer_vide (Voiture **p)
    {
    	Voiture *voit=malloc(sizeof *voit);
    	if(voit!= NULL)
    	{
    		printf("Entrez la marque :\n");
    		scanf("%s",(voit->marque));
    		printf("Entrez le modele :\n");
    		scanf("%s",(voit->modele));
    		printf("Entrez la puissance :\n");
    		scanf("%s",(voit->puissance));
    		voit->suivant=NULL;
    		*p=voit;
    	}        
    }

  2. #22
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Voici un petit essai avec des entrées/sorties plus sures, et utilisation d'un fichier texte au format CSV (Comma Separated Value). Les problèmes de portabilité que je vois avec ce type de stratégie sont essentiellement des problèmes d'encodage, ou de différence entre la façon de coder les fins de ligne (sous win32 et unixoïde par exemple). Toutefois, une bonne spécifiaction du format utilisé pour le fichier texte, et quelques aménagements dans le code, gomment la plupart de ces problèmes.

    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
    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
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
     
    #define M_DEBUG 0
     
    typedef struct Voiture_ Voiture;
     
    static void Creer (Voiture **p);
    static void Ecrire (Voiture *p);
    static Voiture * Analyser_ligne_csv(FILE *fic);
    static void Lire (Voiture **p);
    static void Afficher (Voiture *p);
    static void Detruire (Voiture **p);
    static int clean_fgets(char const *s_buffer, FILE *fp);
     
    int main(void)
    {
        int i;
        Voiture *p_liste = NULL;
     
        for (i = 0; i < 2; ++i)
        {
            Creer(&p_liste);
        }
        printf("Affichage de la liste: \n");
        Afficher(p_liste);
        printf("\n");
        Ecrire(p_liste);
        Detruire(&p_liste);
     
        Lire(&p_liste);
        printf("Affichage de la liste après lecture: \n");
        Afficher(p_liste);
        printf("\n");
        Detruire(&p_liste);
        assert(p_liste == NULL);
     
        return EXIT_SUCCESS;
    }
     
     
    struct Voiture_
    {
        char marque[20];
        char modele[20];
        char puissance[6];
        Voiture *suivant;
    };
     
    /* Définition de la fonction Creer qui est de type Voiture */
    static void
    Creer (Voiture **p)
    {
        if (p != NULL)
        {
            Voiture *voit = malloc(sizeof *voit);
            if (voit!= NULL)
            {
                printf("Entrez la marque: ");
                fflush(stdout);
                fgets(voit->marque, sizeof voit->marque, stdin);
                if (clean_fgets(voit->marque, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez le modèle: ");
                fflush(stdout);
                fgets(voit->modele, sizeof voit->modele, stdin);
                if (clean_fgets(voit->modele, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez la puissance: ");
                fflush(stdout);
                fgets(voit->puissance, sizeof voit->puissance, stdin);
                if (clean_fgets(voit->puissance, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
                printf("\n");
     
                voit->suivant = *p;
            }
            else
            {
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
            *p = voit;
        }
    }
     
    static void
    Ecrire(Voiture *p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
     
            fic = fopen("test.txt", "w");
            if (fic != NULL)
            {
                while (p != NULL)
                {
                    fprintf(fic, "%s, %s, %s\n", p->marque, p->modele, p->puissance);
                    p = p->suivant;
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
    static Voiture *
    Analyser_ligne_csv(FILE *fic)
    {
        char *s_mot;
        /* Tampon servant à la lecture. La taille devrait être suffisante */
        static char s_tampon[100];
        Voiture *p_new = NULL;
     
        /* Si le fichier est ouvert, on essaie de lire une ligne */
        if (fic != NULL && fgets(s_tampon, sizeof s_tampon, fic) != NULL)
        {
            /* On s'assure que la saisie n'a pas été tronquée, et on ignore le
               reste de la ligne si nécessaire */
            if (clean_fgets(s_tampon, fic) != 0)
            {
                fprintf(stderr, "ERREUR: La saisie fichier a été tronquée!\n");
            }
     
            p_new = malloc(sizeof *p_new);
            if (p_new != NULL)
            {
                /* On initialise tous les champs de p_new à 0 */
                static Voiture tmp = {0};
                *p_new = tmp;
     
                /* On copie les éléments de la ligne dans le champs correspondant */
                if ((s_mot = strtok(s_tampon, ", ")) != NULL)
                {
                    strncat(p_new->marque, s_mot, sizeof p_new->marque - 1);
                }
     
                if ((s_mot = strtok(NULL, ", ")) != NULL)
                {
                    strncat(p_new->modele, s_mot, sizeof p_new->modele - 1);
                }
     
                if ((s_mot = strtok(NULL, ", ")) != NULL)
                {
                    strncat(p_new->puissance, s_mot, sizeof p_new->puissance - 1);
                }
     
            }
            else
            {
                /* L'allocation de mémoire a échoué */
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
     
        }
        return p_new;
    }
     
    static void
    Lire (Voiture **p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
            Voiture *p_new = NULL;
            Voiture *p_cur = NULL;
     
            fic = fopen("test.txt", "r");
            if (fic != NULL)
            {
                /* Tant qu'il y a des lignes dans le fichier, on lit */
                while ((p_new = Analyser_ligne_csv(fic)) != NULL)
                {
                    if (*p == NULL)
                    {
                        /* La liste est vide */
                        p_new->suivant = *p;
                        *p = p_new;
                    }
                    else
                    {
                        /* La liste contient des éléments: on recherche le dernier */
                        for (p_cur = *p; p_cur != NULL && p_cur->suivant != NULL;
                                p_cur = p_cur->suivant)
                        {
                            continue;
                        }
                        p_new->suivant = p_cur->suivant;
                        p_cur->suivant = p_new;
                    }
     
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
    static void
    Afficher (Voiture *p)
    {
        while (p != NULL)
        {
            printf("%s %s %s\n", p->marque, p->modele, p->puissance);
            p = p->suivant;
        }
    }
     
    static void
    Detruire (Voiture **p)
    {
        if (p != NULL && *p != NULL)
        {
            Voiture *cur = *p;
            Voiture *next = cur;
     
            while (next != NULL)
            {
                next = next->suivant;
                #if M_DEBUG
                fprintf(stderr, "Destruction: %s %s %s\n", cur->marque,
                        cur->modele, cur->puissance);
                #endif
                free(cur);
                cur = next;
            }
            *p = NULL;
        }
    }
     
     
    /**
     * Teste si la ligne du fichier ou l'entrée utilisateur à partir du flux d'entrée
     * standard n'a pas été tronquée par fgets(). Si la saisie est incomplète, le
     * reste de la ligne (si on travail sur un fichier) est ignoré ou le tampon du
     * flux d'entrée standard (si on travail sur stdin) est purgé, et un code
     * d'erreur est retourné.
     *
     * Si la saisie est correcte, le caractère de nouvelle ligne '\n' placé dans
     * le tampon par fgets() et effacé.
     *
     * @param s_buffer tampon contenant la saisie de fgets()
     * @param fp pointeur sur le fichier considéré, ou sur le flux d'entrée standard
     * @return code d'erreur dont la veleur est 1 en cas de saisie tronquée, et 0
     *         en cas de saisie correcte
     */
    static int clean_fgets(char const *s_buffer, FILE *fp)
    {
        int err = 0; /* error code */
        char *pc = strchr(s_buffer,'\n');
     
        if (pc != NULL) /* input OK */
        {
            *pc = '\0';
        }
        else /* input has been truncated */
        {
            int c;
            while ((c = fgetc(fp)) != '\n' && c != EOF)
            {
                /* We ignore all the remaining characters */
                continue;
            }
            /* we report that an error has been encountered */
            err = 1;
        }
        return err;
    }
    et voilà un exemple du fichier test.txt généré:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Fiat, Doblo, 2000
    Renault, Twingo, 1100
    VW, Golf, 1800
    J'ai pas eu le temps de beaucoup commenter.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  3. #23
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    Citation Envoyé par mujigka
    Voici un petit essai avec des entrées/sorties plus sures, et utilisation d'un fichier texte au format CSV (Comma Separated Value). Les problèmes de portabilité que je vois avec ce type de stratégie sont essentiellement des problèmes d'encodage, ou de différence entre la façon de coder les fins de ligne (sous win32 et unixoïde par exemple). Toutefois, une bonne spécifiaction du format utilisé pour le fichier texte, et quelques aménagements dans le code, gomment la plupart de ces problèmes.

    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
    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
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
     
    #define M_DEBUG 0
     
    typedef struct Voiture_ Voiture;
     
    static void Creer (Voiture **p);
    static void Ecrire (Voiture *p);
    static Voiture * Analyser_ligne_csv(FILE *fic);
    static void Lire (Voiture **p);
    static void Afficher (Voiture *p);
    static void Detruire (Voiture **p);
    static int clean_fgets(char const *s_buffer, FILE *fp);
     
    int main(void)
    {
        int i;
        Voiture *p_liste = NULL;
     
        for (i = 0; i < 2; ++i)
        {
            Creer(&p_liste);
        }
        printf("Affichage de la liste: \n");
        Afficher(p_liste);
        printf("\n");
        Ecrire(p_liste);
        Detruire(&p_liste);
     
        Lire(&p_liste);
        printf("Affichage de la liste après lecture: \n");
        Afficher(p_liste);
        printf("\n");
        Detruire(&p_liste);
        assert(p_liste == NULL);
     
        return EXIT_SUCCESS;
    }
     
     
    struct Voiture_
    {
        char marque[20];
        char modele[20];
        char puissance[6];
        Voiture *suivant;
    };
     
    /* Définition de la fonction Creer qui est de type Voiture */
    static void
    Creer (Voiture **p)
    {
        if (p != NULL)
        {
            Voiture *voit = malloc(sizeof *voit);
            if (voit!= NULL)
            {
                printf("Entrez la marque: ");
                fflush(stdout);
                fgets(voit->marque, sizeof voit->marque, stdin);
                if (clean_fgets(voit->marque, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez le modèle: ");
                fflush(stdout);
                fgets(voit->modele, sizeof voit->modele, stdin);
                if (clean_fgets(voit->modele, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez la puissance: ");
                fflush(stdout);
                fgets(voit->puissance, sizeof voit->puissance, stdin);
                if (clean_fgets(voit->puissance, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
                printf("\n");
     
                voit->suivant = *p;
            }
            else
            {
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
            *p = voit;
        }
    }
     
    static void
    Ecrire(Voiture *p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
     
            fic = fopen("test.txt", "w");
            if (fic != NULL)
            {
                while (p != NULL)
                {
                    fprintf(fic, "%s, %s, %s\n", p->marque, p->modele, p->puissance);
                    p = p->suivant;
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
    static Voiture *
    Analyser_ligne_csv(FILE *fic)
    {
        char *s_mot;
        /* Tampon servant à la lecture. La taille devrait être suffisante */
        static char s_tampon[100];
        Voiture *p_new = NULL;
     
        /* Si le fichier est ouvert, on essaie de lire une ligne */
        if (fic != NULL && fgets(s_tampon, sizeof s_tampon, fic) != NULL)
        {
            /* On s'assure que la saisie n'a pas été tronquée, et on ignore le
               reste de la ligne si nécessaire */
            if (clean_fgets(s_tampon, fic) != 0)
            {
                fprintf(stderr, "ERREUR: La saisie fichier a été tronquée!\n");
            }
     
            p_new = malloc(sizeof *p_new);
            if (p_new != NULL)
            {
                /* On initialise tous les champs de p_new à 0 */
                static Voiture tmp = {0};
                *p_new = tmp;
     
                /* On copie les éléments de la ligne dans le champs correspondant */
                if ((s_mot = strtok(s_tampon, ", ")) != NULL)
                {
                    strncat(p_new->marque, s_mot, sizeof p_new->marque - 1);
                }
     
                if ((s_mot = strtok(NULL, ", ")) != NULL)
                {
                    strncat(p_new->modele, s_mot, sizeof p_new->modele - 1);
                }
     
                if ((s_mot = strtok(NULL, ", ")) != NULL)
                {
                    strncat(p_new->puissance, s_mot, sizeof p_new->puissance - 1);
                }
     
            }
            else
            {
                /* L'allocation de mémoire a échoué */
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
     
        }
        return p_new;
    }
     
    static void
    Lire (Voiture **p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
            Voiture *p_new = NULL;
            Voiture *p_cur = NULL;
     
            fic = fopen("test.txt", "r");
            if (fic != NULL)
            {
                /* Tant qu'il y a des lignes dans le fichier, on lit */
                while ((p_new = Analyser_ligne_csv(fic)) != NULL)
                {
                    if (*p == NULL)
                    {
                        /* La liste est vide */
                        p_new->suivant = *p;
                        *p = p_new;
                    }
                    else
                    {
                        /* La liste contient des éléments: on recherche le dernier */
                        for (p_cur = *p; p_cur != NULL && p_cur->suivant != NULL;
                                p_cur = p_cur->suivant)
                        {
                            continue;
                        }
                        p_new->suivant = p_cur->suivant;
                        p_cur->suivant = p_new;
                    }
     
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
    static void
    Afficher (Voiture *p)
    {
        while (p != NULL)
        {
            printf("%s %s %s\n", p->marque, p->modele, p->puissance);
            p = p->suivant;
        }
    }
     
    static void
    Detruire (Voiture **p)
    {
        if (p != NULL && *p != NULL)
        {
            Voiture *cur = *p;
            Voiture *next = cur;
     
            while (next != NULL)
            {
                next = next->suivant;
                #if M_DEBUG
                fprintf(stderr, "Destruction: %s %s %s\n", cur->marque,
                        cur->modele, cur->puissance);
                #endif
                free(cur);
                cur = next;
            }
            *p = NULL;
        }
    }
     
     
    /**
     * Teste si la ligne du fichier ou l'entrée utilisateur à partir du flux d'entrée
     * standard n'a pas été tronquée par fgets(). Si la saisie est incomplète, le
     * reste de la ligne (si on travail sur un fichier) est ignoré ou le tampon du
     * flux d'entrée standard (si on travail sur stdin) est purgé, et un code
     * d'erreur est retourné.
     *
     * Si la saisie est correcte, le caractère de nouvelle ligne '\n' placé dans
     * le tampon par fgets() et effacé.
     *
     * @param s_buffer tampon contenant la saisie de fgets()
     * @param fp pointeur sur le fichier considéré, ou sur le flux d'entrée standard
     * @return code d'erreur dont la veleur est 1 en cas de saisie tronquée, et 0
     *         en cas de saisie correcte
     */
    static int clean_fgets(char const *s_buffer, FILE *fp)
    {
        int err = 0; /* error code */
        char *pc = strchr(s_buffer,'\n');
     
        if (pc != NULL) /* input OK */
        {
            *pc = '\0';
        }
        else /* input has been truncated */
        {
            int c;
            while ((c = fgetc(fp)) != '\n' && c != EOF)
            {
                /* We ignore all the remaining characters */
                continue;
            }
            /* we report that an error has been encountered */
            err = 1;
        }
        return err;
    }
    et voilà un exemple du fichier test.txt généré:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Fiat, Doblo, 2000
    Renault, Twingo, 1100
    VW, Golf, 1800
    J'ai pas eu le temps de beaucoup commenter.

    Thierry
    Merci beaucoup, mais mon prof me demande de le faire avec un fichier texte en binaire, est ce que le code reste le même???

  4. #24
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par poche
    Merci beaucoup, mais mon prof me demande de le faire avec un fichier texte en binaire, est ce que le code reste le même???
    C'est donc ton prof qui te demande t'utiliser un fichier binaire... Non! Le code ne reste pas le même. Il y a d'autres moyens d'enregistrer une structure de manière portable dans un fichier binaire, mais je n'ai pas le temps de rentrer dans les détails de la sérialisation maintenant. Je pense dans ce cas que ton prof attend de toi que tu enregistres tes données selon la méthode que tu as utilisée...

    Pour le code relatif aux saisies sécurisées, tu peux sans soucis t'inspirer de mon code pour réaliser des entrées/sorties robustes. Dans le code ci-dessus, des améliorations sont encore possibles. La vrai solution est toutefois de se construire une fois pour toutes des entrées sécurisées, de mettre le code dans une bibliothèque de fonctions réutilisables, et hop, c'est réglé!. Pour cela, le site d'Emmanuel Delahaye, dont je t'ai passé le lien, est très instructif.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  5. #25
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    stdin et stdout sont de la mémoire!!!
    Je comprends pas trops à quoi ils servent!!!
    car normalement les fonctions ou stdin et stdout sont en argument, normalement l'argument attendu est un fichier texte!!!

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    printf("Entrez le modèle: ");
                fflush(stdout);
                fgets(voit->modele, sizeof voit->modele, stdin);
                if (clean_fgets(voit->modele, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }

  6. #26
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Citation Envoyé par poche
    stdin et stdout sont de la mémoire!!!
    stdin et stdout sont des "FILE *".

  7. #27
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    Citation Envoyé par stephl
    stdin et stdout sont des "FILE *".
    oui, mais je ne vois pas leur chemin, ils viennent de nul part, ils ne sont pas déclarés!!!!Je comprends pas d'ou ils viennent...

  8. #28
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Citation Envoyé par poche
    oui, mais je ne vois pas leur chemin, ils viennent de nul part, ils ne sont pas déclarés!!!!Je comprends pas d'ou ils viennent...
    Ils sont tout simplement prédéfinis et ouverts et fermés automatiquement.
    Regardez dans stdio.h.

  9. #29
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    Je vois pas à quoi ils servent, je vois pas pourquoi on copie ce qu'on reçois dans un fichier.
    sinon, je vois pas à quoi sert fflush, à part de vider la mémoire tampon de stdout. En plus on ne se sert pas autre part de ces fichiers, je comprend rien...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    fflush(stdout);
                fgets(voit->marque, sizeof voit->marque, stdin);

  10. #30
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Citation Envoyé par poche
    Je vois pas à quoi ils servent, je vois pas pourquoi on copie ce qu'on reçois dans un fichier.
    sinon, je vois pas à quoi sert fflush, à part de vider la mémoire tampon de stdout. En plus on ne se sert pas autre part de ces fichiers, je comprend rien...
    stdin est l'entrée standard (soit généralement le clavier) et stdout est la sortie standard (soit généralement l'écran). Alors, même si ce n'est pas de façon explicite, vous les utilisez tout de même (en mode console).

  11. #31
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    ok je comprends stdin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    fgets(voit->modele, sizeof voit->modele, stdin);
    la fonction permet de lire se qu'on a écrit à l'écran et la mettre dans "voit->modele"

    Mais sinon je vois pas à quoi sert le code ci dessous, je l'ai enlevé et sa marche pareil, pourquoi???

  12. #32
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Citation Envoyé par poche
    Mais sinon je vois pas à quoi sert le code ci dessous, je l'ai enlevé et sa marche pareil, pourquoi???
    fflush(stdout) force l'écriture du texte à l'écran. En effet, les sorties peuvent être bufferisées et le texte n'est pas alors écrit nécessairement "tout de suite". J'utilise très rarement fflush(stdout) comme il a été utilisé ici, mais faut croire que c'est peut-être nécessaire sur certaines implémentations.

  13. #33
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    petite dernière question, la fonction créé gère tout même si le fichier texte est vide. Donc moi sa sert à rien que j'ai fais ça:
    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
    void Creer_vide (Voiture **p)
    {
    	Voiture *voit=malloc(sizeof *voit);
    	if(voit!= NULL)
    	{
    		printf("Entrez la marque :\n");
    		scanf("%s",&(voit->marque));
    		printf("Entrez le modele :\n");
    		scanf("%s",&(voit->modele));
    		printf("Entrez la puissance :\n");
    		scanf("%s",&(voit->puissance));
    		voit->suivant=NULL;
    		*p=voit;
    	}        
    }
    juste la fonction créé suffirai? car je vois nul part dans le code "voit->suivant=NULL;" lorsque le fichier est vide et qu'on veux créer le premier maillon!!

    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
    Creer (Voiture **p)
    {
        if (p != NULL)
        {
            Voiture *voit = malloc(sizeof *voit);
            if (voit!= NULL)
            {	
                printf("Entrez la marque: ");
    			do
    			{
                //fflush(stdout);
                fgets(voit->marque, sizeof voit->marque, stdin); 
     
    			}while (clean_fgets(voit->marque, stdin)!= 0);
     
                printf("Entrez le modèle: ");
                //fflush(stdout);
                fgets(voit->modele, sizeof voit->modele, stdin);
                if (clean_fgets(voit->modele, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez la puissance: ");
                fflush(stdout);
                fgets(voit->puissance, sizeof voit->puissance, stdin);
                if (clean_fgets(voit->puissance, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
                printf("\n");
     
                voit->suivant = *p;
            }
            else
            {
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
            *p = voit;
        }
    }

  14. #34
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    Citation Envoyé par poche
    petite dernière question, la fonction créé gère tout même si le fichier texte est vide. Donc moi sa sert à rien que j'ai fais ça:
    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
    void Creer_vide (Voiture **p)
    {
    	Voiture *voit=malloc(sizeof *voit);
    	if(voit!= NULL)
    	{
    		printf("Entrez la marque :\n");
    		scanf("%s",&(voit->marque));
    		printf("Entrez le modele :\n");
    		scanf("%s",&(voit->modele));
    		printf("Entrez la puissance :\n");
    		scanf("%s",&(voit->puissance));
    		voit->suivant=NULL;
    		*p=voit;
    	}        
    }
    juste la fonction créé suffirai? car je vois nul part dans votre code "voit->suivant=NULL;" lorsque le fichier est vide et qu'on veux créer le premier maillon!!

    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
    Creer (Voiture **p)
    {
        if (p != NULL)
        {
            Voiture *voit = malloc(sizeof *voit);
            if (voit!= NULL)
            {	
                printf("Entrez la marque: ");
    			do
    			{
                //fflush(stdout);
                fgets(voit->marque, sizeof voit->marque, stdin); 
     
    			}while (clean_fgets(voit->marque, stdin)!= 0);
     
                printf("Entrez le modèle: ");
                //fflush(stdout);
                fgets(voit->modele, sizeof voit->modele, stdin);
                if (clean_fgets(voit->modele, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez la puissance: ");
                fflush(stdout);
                fgets(voit->puissance, sizeof voit->puissance, stdin);
                if (clean_fgets(voit->puissance, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
                printf("\n");
     
                voit->suivant = *p;
            }
            else
            {
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
            *p = voit;
        }
    }

  15. #35
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Si je me rappelle bien, Creer() est appelée avec &tete. tete a précédemment été initialisée à NULL, donc faire:
    équivaut à:
    Creer_vide() est selon moi inutile.

  16. #36
    Membre confirmé
    Inscrit en
    Décembre 2006
    Messages
    112
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 112
    Par défaut
    ok, merci pour tout.
    Et encore merci pour le temps que vous avez passez pour moi (je suis encore un débutant!!!!).

  17. #37
    Membre émérite Avatar de stephl
    Profil pro
    Développeur informatique
    Inscrit en
    Février 2007
    Messages
    643
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Février 2007
    Messages : 643
    Par défaut
    Citation Envoyé par poche
    ok, merci pour tout.
    Et encore merci pour le temps que vous avez passez pour moi (je suis encore un débutant!!!!).
    Aucun problème. Après tout, le forum est fait pour cela.

  18. #38
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Après réflexion, du point de vue de la portabilité de tes fichiers binaires, tu ne devrais pas avoir de problème d'endianness, ni d'alignement, du moment que tu n'enregistres QUE les champs tableaux de caractères de ta structure Voiture:

    Voici 3 fonctions à ajouter au code précédent qui permettent de sauver dans un fichier binaire:
    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
    static void
    Ecrire_bin (Voiture *p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
     
            fic = fopen("test.bin", "wb");
            if (fic != NULL)
            {
                while (p != NULL)
                {
                    fwrite(p->marque, sizeof p->marque, 1, fic);
                    fwrite(p->modele, sizeof p->modele, 1, fic);
                    fwrite(p->puissance, sizeof p->puissance, 1, fic);
                    p = p->suivant;
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
    static Voiture *
    Analyser_bin (FILE *fic)
    {
        Voiture *p_new = NULL;
     
        if (fic != NULL)
        {
            char *pc;
            static char s_tampon[100];
            static Voiture tmp = {0};
     
            if (fread(s_tampon, sizeof tmp.marque + sizeof tmp.modele +
                    sizeof tmp.puissance, 1, fic) == 1)
            {
                p_new = malloc(sizeof *p_new);
                if (p_new != NULL)
                {
                    *p_new = tmp;
     
                    pc = s_tampon;
                    strncat(p_new->marque, pc, sizeof p_new->marque - 1);
                    pc = pc + sizeof p_new->marque;
                    strncat(p_new->modele, pc, sizeof p_new->modele - 1);
                    pc = pc + sizeof p_new->modele;
                    strncat(p_new->puissance, pc, sizeof p_new->puissance - 1);
                }
                else
                {
                    /* L'allocation de mémoire a échoué */
                    fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                    exit(EXIT_FAILURE);
                }
            }
            else if (feof(fic) != 1)
            {
                fprintf(stderr, "Problème rencontré lors de la lecture!\n");
                exit(EXIT_FAILURE);
            }
        }
        return p_new;
    }
     
    static void
    Lire_bin (Voiture **p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
            Voiture *p_new = NULL;
            Voiture *p_cur = NULL;
     
            fic = fopen("test.bin", "r");
            if (fic != NULL)
            {
                while ((p_new = Analyser_bin(fic)) != NULL)
                {
                    if (*p == NULL)
                    {
                        /* La liste est vide */
                        p_new->suivant = *p;
                        *p = p_new;
                    }
                    else
                    {
                        /* La liste contient des éléments: on recherche le dernier */
                        for (p_cur = *p; p_cur != NULL && p_cur->suivant != NULL;
                                p_cur = p_cur->suivant)
                        {
                            continue;
                        }
                        p_new->suivant = p_cur->suivant;
                        p_cur->suivant = p_new;
                    }
     
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
    Et voici mon code mis à jour. Pour utiliser un format de fichier binaire (test.bin), il faut définir la macro USE_BINARY_FILE à 1. Dans le cas contraire, un fichier texte au format CSV sera généré et utilisé. La lecture se fait avec Lire() et l'écriture avec Ecrire() (ces identificateurs sont redirigés sur les fonctions Lire_csv/Ecrire_csv et Lire_bin/Ecrire_bin par le préprocesseur).
    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
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    397
    398
    399
    400
    401
    402
    403
    404
    405
    406
    407
    408
    409
    410
    411
    412
    413
    414
    415
    416
    417
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <assert.h>
     
    #define USE_BINARY_FILE 1
     
    #define M_DEBUG 0
     
    #ifdef USE_BINARY_FILE
    #    define Lire Lire_bin
    #    define Ecrire Ecrire_bin
    #else
    #    define Lire Lire_csv
    #    define Ecrire Ecrire_csv
    #endif
     
    typedef struct Voiture_ Voiture;
    struct Voiture_
    {
        char marque[20];
        char modele[20];
        char puissance[6];
        Voiture *suivant;
    };
     
    static void Creer (Voiture **p);
    #if USE_BINARY_FILE
    static void Ecrire_bin (Voiture *p);
    static void Lire_bin (Voiture **p);
    #else
    static void Ecrire_csv (Voiture *p);
    static Voiture * Analyser_ligne_csv(FILE *fic);
    static void Lire_csv (Voiture **p);
    #endif
    static void Afficher (Voiture *p);
    static void Detruire (Voiture **p);
    static int clean_fgets(char const *s_buffer, FILE *fp);
     
     
    int main(void)
    {
        int i;
        Voiture *p_liste = NULL;
        Voiture c;
     
        printf("Taille: %u\n", sizeof c);
     
        for (i = 0; i < 5; ++i)
        {
            Creer(&p_liste);
        }
        printf("Affichage de la liste: \n");
        Afficher(p_liste);
        printf("\n");
        Ecrire(p_liste);
        Detruire(&p_liste);
     
        Lire(&p_liste);
        printf("Affichage de la liste après lecture: \n");
        Afficher(p_liste);
        printf("\n");
        Detruire(&p_liste);
        assert(p_liste == NULL);
     
        return EXIT_SUCCESS;
    }
     
     
    /* Définition de la fonction Creer qui est de type Voiture */
    static void
    Creer (Voiture **p)
    {
        if (p != NULL)
        {
            Voiture *voit = malloc(sizeof *voit);
            if (voit!= NULL)
            {
                printf("Entrez la marque: ");
                fflush(stdout);
                fgets(voit->marque, sizeof voit->marque, stdin);
                if (clean_fgets(voit->marque, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez le modèle: ");
                fflush(stdout);
                fgets(voit->modele, sizeof voit->modele, stdin);
                if (clean_fgets(voit->modele, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez la puissance: ");
                fflush(stdout);
                fgets(voit->puissance, sizeof voit->puissance, stdin);
                if (clean_fgets(voit->puissance, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
                printf("\n");
     
                voit->suivant = *p;
            }
            else
            {
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
            *p = voit;
        }
    }
    #if USE_BINARY_FILE
    static void
    Ecrire_bin (Voiture *p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
     
            fic = fopen("test.bin", "wb");
            if (fic != NULL)
            {
                while (p != NULL)
                {
                    fwrite(p->marque, sizeof p->marque, 1, fic);
                    fwrite(p->modele, sizeof p->modele, 1, fic);
                    fwrite(p->puissance, sizeof p->puissance, 1, fic);
                    p = p->suivant;
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
    static Voiture *
    Analyser_bin (FILE *fic)
    {
        Voiture *p_new = NULL;
     
        if (fic != NULL)
        {
            char *pc;
            static char s_tampon[100];
            static Voiture tmp = {0};
     
            if (fread(s_tampon, sizeof tmp.marque + sizeof tmp.modele +
                    sizeof tmp.puissance, 1, fic) == 1)
            {
                p_new = malloc(sizeof *p_new);
                if (p_new != NULL)
                {
                    *p_new = tmp;
     
                    pc = s_tampon;
                    strncat(p_new->marque, pc, sizeof p_new->marque - 1);
                    pc = pc + sizeof p_new->marque;
                    strncat(p_new->modele, pc, sizeof p_new->modele - 1);
                    pc = pc + sizeof p_new->modele;
                    strncat(p_new->puissance, pc, sizeof p_new->puissance - 1);
                }
                else
                {
                    /* L'allocation de mémoire a échoué */
                    fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                    exit(EXIT_FAILURE);
                }
            }
            else if (feof(fic) != 1)
            {
                fprintf(stderr, "Problème rencontré lors de la lecture!\n");
                exit(EXIT_FAILURE);
            }
        }
        return p_new;
    }
     
    static void
    Lire_bin (Voiture **p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
            Voiture *p_new = NULL;
            Voiture *p_cur = NULL;
     
            fic = fopen("test.bin", "r");
            if (fic != NULL)
            {
                while ((p_new = Analyser_bin(fic)) != NULL)
                {
                    if (*p == NULL)
                    {
                        /* La liste est vide */
                        p_new->suivant = *p;
                        *p = p_new;
                    }
                    else
                    {
                        /* La liste contient des éléments: on recherche le dernier */
                        for (p_cur = *p; p_cur != NULL && p_cur->suivant != NULL;
                                p_cur = p_cur->suivant)
                        {
                            continue;
                        }
                        p_new->suivant = p_cur->suivant;
                        p_cur->suivant = p_new;
                    }
     
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
    #else
    static void
    Ecrire_csv (Voiture *p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
     
            fic = fopen("test.txt", "w");
            if (fic != NULL)
            {
                while (p != NULL)
                {
                    fprintf(fic, "%s, %s, %s\n", p->marque, p->modele, p->puissance);
                    p = p->suivant;
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
     
     
    static Voiture *
    Analyser_ligne_csv (FILE *fic)
    {
        char *s_mot;
        /* Tampon servant à la lecture. La taille devrait être suffisante */
        static char s_tampon[100];
        Voiture *p_new = NULL;
     
        /* Si le fichier est ouvert, on essaie de lire une ligne */
        if (fic != NULL && fgets(s_tampon, sizeof s_tampon, fic) != NULL)
        {
            /* On s'assure que la saisie n'a pas été tronquée, et on ignore le
               reste de la ligne si nécessaire */
            if (clean_fgets(s_tampon, fic) != 0)
            {
                fprintf(stderr, "ERREUR: La saisie fichier a été tronquée!\n");
            }
     
            p_new = malloc(sizeof *p_new);
            if (p_new != NULL)
            {
                /* On initialise tous les champs de p_new à 0 */
                static Voiture tmp = {0};
                *p_new = tmp;
     
                /* On copie les éléments de la ligne dans le champs correspondant */
                if ((s_mot = strtok(s_tampon, ", ")) != NULL)
                {
                    strncat(p_new->marque, s_mot, sizeof p_new->marque - 1);
                }
     
                if ((s_mot = strtok(NULL, ", ")) != NULL)
                {
                    strncat(p_new->modele, s_mot, sizeof p_new->modele - 1);
                }
     
                if ((s_mot = strtok(NULL, ", ")) != NULL)
                {
                    strncat(p_new->puissance, s_mot, sizeof p_new->puissance - 1);
                }
     
            }
            else
            {
                /* L'allocation de mémoire a échoué */
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
     
        }
        return p_new;
    }
     
    static void
    Lire_csv (Voiture **p)
    {
        if (p != NULL)
        {
            FILE *fic = NULL;
            Voiture *p_new = NULL;
            Voiture *p_cur = NULL;
     
            fic = fopen("test.txt", "r");
            if (fic != NULL)
            {
                /* Tant qu'il y a des lignes dans le fichier, on lit */
                while ((p_new = Analyser_ligne_csv(fic)) != NULL)
                {
                    if (*p == NULL)
                    {
                        /* La liste est vide */
                        p_new->suivant = *p;
                        *p = p_new;
                    }
                    else
                    {
                        /* La liste contient des éléments: on recherche le dernier */
                        for (p_cur = *p; p_cur != NULL && p_cur->suivant != NULL;
                                p_cur = p_cur->suivant)
                        {
                            continue;
                        }
                        p_new->suivant = p_cur->suivant;
                        p_cur->suivant = p_new;
                    }
     
                }
                fclose(fic), fic = NULL;
            }
            else
            {
                fprintf(stderr, "Impossible d'ouvrir le fichier!\n");
            }
        }
    }
    #endif
     
    static void
    Afficher (Voiture *p)
    {
        while (p != NULL)
        {
            printf("%s %s %s\n", p->marque, p->modele, p->puissance);
            p = p->suivant;
        }
    }
     
    static void
    Detruire (Voiture **p)
    {
        if (p != NULL && *p != NULL)
        {
            Voiture *cur = *p;
            Voiture *next = cur;
     
            while (next != NULL)
            {
                next = next->suivant;
                #if M_DEBUG
                fprintf(stderr, "Destruction: %s %s %s\n", cur->marque,
                        cur->modele, cur->puissance);
                #endif
                free(cur);
                cur = next;
            }
            *p = NULL;
        }
    }
     
     
    /**
     * Teste si la ligne du fichier ou l'entrée utilisateur à partir du flux d'entrée
     * standard n'a pas été tronquée par fgets(). Si la saisie est incomplète, le
     * reste de la ligne (si on travail sur un fichier) est ignoré ou le tampon du
     * flux d'entrée standard (si on travail sur stdin) est purgé, et un code
     * d'erreur est retourné.
     *
     * Si la saisie est correcte, le caractère de nouvelle ligne '\n' placé dans
     * le tampon par fgets() et effacé.
     *
     * @param s_buffer tampon contenant la saisie de fgets()
     * @param fp pointeur sur le fichier considéré, ou sur le flux d'entrée standard
     * @return code d'erreur dont la veleur est 1 en cas de saisie tronquée, et 0
     *         en cas de saisie correcte
     */
    static int clean_fgets(char const *s_buffer, FILE *fp)
    {
        int err = 0; /* error code */
        char *pc = strchr(s_buffer,'\n');
     
        if (pc != NULL) /* input OK */
        {
            *pc = '\0';
        }
        else /* input has been truncated */
        {
            int c;
            while ((c = fgetc(fp)) != '\n' && c != EOF)
            {
                /* We ignore all the remaining characters */
                continue;
            }
            /* we report that an error has been encountered */
            err = 1;
        }
        return err;
    }
    Je n'ai toujours pas eu le temps de commenter de manière exhaustive. Bonne chance et n'hésite pas à poser des questions

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  19. #39
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par stephl
    fflush(stdout) force l'écriture du texte à l'écran. En effet, les sorties peuvent être bufferisées et le texte n'est pas alors écrit nécessairement "tout de suite". J'utilise très rarement fflush(stdout) comme il a été utilisé ici, mais faut croire que c'est peut-être nécessaire sur certaines implémentations.
    Il y a deux événements en C qui entraînent la vidange du tampon de stdin. Soit il est plein, soit la chaîne envoyée sur ce flot se termine par un caractère de fin de ligne. Si on écrit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("Entrez la manque: ");
    Il est TOUJOURS nécessaire de faire suivre cette instruction par fflush(stdout) pour s'assurer un affichage synchronisé. Une alternative est de terminer la chaîne avec le caractère '\n':
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    printf("Entrez la marque:\n");
    Dans ce cas, la vidange du tampon se fait automatiquement.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  20. #40
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par poche

    juste la fonction créé suffirai? car je vois nul part dans le code "voit->suivant=NULL;" lorsque le fichier est vide et qu'on veux créer le premier maillon!!

    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
    Creer (Voiture **p)
    {
        if (p != NULL)
        {
            Voiture *voit = malloc(sizeof *voit);
            if (voit!= NULL)
            {	
                printf("Entrez la marque: ");
    			do
    			{
                //fflush(stdout);
                fgets(voit->marque, sizeof voit->marque, stdin); 
     
    			}while (clean_fgets(voit->marque, stdin)!= 0);
     
                printf("Entrez le modèle: ");
                //fflush(stdout);
                fgets(voit->modele, sizeof voit->modele, stdin);
                if (clean_fgets(voit->modele, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
     
                printf("Entrez la puissance: ");
                fflush(stdout);
                fgets(voit->puissance, sizeof voit->puissance, stdin);
                if (clean_fgets(voit->puissance, stdin) != 0)
                {
                    fprintf(stderr, "AVERTISSEMENT: La saisie a été tronquée!\n");
                }
                printf("\n");
     
                voit->suivant = *p;
            }
            else
            {
                fprintf(stderr, "Allocation impossible! Mémoire insuffisante...");
                exit(EXIT_FAILURE);
            }
            *p = voit;
        }
    }
    Lorsque tu passes une liste vide à ta fonction Creer(), *p prend la valeur NULL. Ainsi:
    est équivalent à
    Il n'est donc pas nécessaire de créer une fonction spécifique pour traîter le cas où la liste est vide.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

Discussions similaires

  1. Petit problème de programmation.
    Par willow.A dans le forum C
    Réponses: 3
    Dernier message: 08/01/2007, 16h36
  2. Problème en programmant un GUI swing
    Par kaelem dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 05/01/2007, 11h59
  3. Problème de programmation orientée objet
    Par dan65 dans le forum WinDev
    Réponses: 8
    Dernier message: 17/09/2006, 01h04
  4. problème finalisation programme
    Par depelek dans le forum Installation, Déploiement et Sécurité
    Réponses: 9
    Dernier message: 02/05/2006, 16h17
  5. Réponses: 1
    Dernier message: 26/09/2005, 19h29

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