Il n'y a qu'une seule fonction main() dans un programme, que je sache.... Eh bien, apprend que cette fonction-là doit retourner un int. Généralement zéro.
Ben non, ça ne veut pas dire ça. La valeur de feof() est indéfinie tant que les fonctions de lecture n'ont pas retourné une erreur.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Pourquoi me demandes-tu de quel main je parle puisqu'il n'y en a qu'un seul ?
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
En C, il doit toujours y avoir une fonction main. Cette fonction doit toujours renvoyer un entier (souvent 0). Le code minimum est doncLe void signifie ici que tu n'utilises pas d'argument pour la fonction main. Ton "void main ()" n'a pas de sens.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 int main(void) { return 0; }
http://emmanuel-delahaye.developpez....s.htm#typemain
et pour le problème du feof() :
http://emmanuel-delahaye.developpez....es.htm#fichier
Voici ton programme un peu (beaucoup) remanié:
Pose des questions si tu ne comprends pas.
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 #include <stdio.h> #include <stdlib.h> #if 0 /* -tc- inclusion inutile */ # include<conio.h> #endif #include <string.h> #include <ctype.h> typedef struct { char nom[20]; char prenom[20]; int code; } etudiant; /* -tc- je recommande de declarer les fonctions hors de main() ET sous forme de prototypes (une liste vide d'arguments est spécifiee par void) */ void saisie(void); void suppression(void); /* -tc- j'ai renomme la fonction edition qui ne faisait que de l'affichage */ void affichage(void); void tri(void); /* -tc- quelques fcts pour securiser les saisies*/ int fget_c(FILE *fp); int fget_s(char *buffer, size_t bufsize, FILE *fp); int fget_int(int *value, FILE *fp); /* -tc- recupere les donnees enregistrees par etudient_enreg() */ int etudiant_get(etudiant *self, FILE *fp); /* -tc- enregistre la description d'un etudiant au format texte dans un fichier */ void etudiant_enreg(etudiant *self, FILE *fp); /* -tc- main() retourne un entier de type int, TOUJOURS! */ int main(void) { int choix; int err = 0; /* affichage de menu */ do { printf("____________________________\n" "gestion des etudiants\n" "____________________________\n" " 1-saisie\n" " 2-suppression\n" " 3-affichage\n" " 4-tri\n" " 5-fin\n"); do { printf("choix: "); fflush(stdout); /* -tc- Saisie pas tres heureuse: laisse un caracterec de fin de ligne dans le tampon de stdin. Je prefere convertir en entier. choix = getchar(); */ err = fget_int(&choix, stdin); } while (err == 1 || ( choix < 1) || (choix > 5)); switch (choix) { case 1: saisie(); break; case 2: suppression(); break; case 3: affichage(); break; case 4: tri(); break; case 5: printf("au revoir!\n"); break; } } while (choix != 5); /* -tc- Les 3 valeurs portables que peut retourner main() sont 0, EXIT_SUCCESS et EXIT_FAILURE */ return 0; } void saisie(void) { etudiant e; char reponse; FILE *f = NULL; f = fopen("etudiant.txt", "a"); if (f != NULL) { do { printf("Entrer le nom de votre etudiant: "); /* -tc- on force l'affichage de l'invite */ fflush(stdout); /* -tc- pour saisir une chaine proprement */ fget_s(e.nom, sizeof e.nom, stdin); printf("Entrer le prenom de votre etudiant: "); fflush(stdout); fget_s(e.prenom, sizeof e.prenom, stdin); printf("Entrer le code de votre etudiant: "); fflush(stdout); fget_int(&e.code, stdin); etudiant_enreg(&e, f); do { printf("Voulez vous continuez?[o/n] "); fflush(stdout); /* -tc- il reste au moins un caractere de fin de ligne sur le flux d'entree standard. Il faut faire le menage... reponse = getchar(); */ reponse = fget_c(stdin); } while ((toupper(reponse) != 'N') && ( toupper(reponse) != 'O')); } while (toupper(reponse) != 'N'); fclose(f), f = NULL; } } void suppression(void) { FILE *infile = NULL; FILE *outfile = NULL; etudiant e_suppr = {"", "", 0}; etudiant e = {"", "", 0}; /* -tc- on n'a pas le choix du nom de fichier dans la fonction saisie(). Pourquoi le donner dans suppression() ? */ infile = fopen("etudiant.txt", "r"); if (infile == NULL) { fprintf(stderr, "\aERREUR: Impossible d'ouvrir " "le fichier etudiant.txt"); } else { outfile = fopen("etudiant-tmp.txt", "w"); if (!outfile) { printf("\aERREUR: Impossible d'ouvrir " "le fichier etudiant-tmp.txt"); } else { /* -tc- On identifie l'etudiant a supprimer avec nom et prenom */ printf("Nom de l'etudiant a supprimer: "); fflush(stdout); fget_s(e_suppr.nom, sizeof e_suppr.nom, stdin); printf("Prenom de l'etudiant a supprimmer: "); fflush(stdout); fget_s(e_suppr.prenom, sizeof e_suppr.prenom, stdin); while (etudiant_get(&e, infile) != EOF) { /* -tc- on ne conserve que les etudiants dont le nom ET le prenom different de ceux entres par l'utilisateur */ if (strcmp(e.nom, e_suppr.nom) != 0 || strcmp(e.prenom, e_suppr.prenom) != 0) { etudiant_enreg(&e, outfile); } } /* Fermeture des fichiers */ remove("etudiant.txt"); rename("etudiant-tmp.txt","etudiant.txt"); fclose(outfile); } fclose(infile); } } void affichage(void) { int i; etudiant e= {"", "", 0}; FILE *f = NULL; f = fopen("etudiant.txt","r"); if (f != NULL) { i = 1; while (etudiant_get(&e, f) != EOF) { printf("La personne numero %d est:\n", i); printf(" Le nom est %s:\n", e.nom); printf(" Le prenom est %s:\n", e.prenom); printf(" Le code est %d:\n", e.code); i++; } printf("Le fichier contient %d element%s\n", i - 1, (i > 2) ? "s": ""); } fclose(f); } void tri(void) { printf("hi\n"); } /* -tc- elimine le caractere de fin de ligne saisi par fgets() et fait le * menage sur le flux entrant en cas de saisie tronquee. */ int fclean(char *buffer, FILE *fp) { int err = 0; if (buffer != NULL && fp != NULL) { char *pc = strchr(buffer, '\n'); if (pc != NULL) { *pc = 0; } else { int c; while ((c = fgetc(fp)) != '\n' && c != EOF) { } err = 1; } } return err; } /* -tc- permet de saisir proprement un caractere sur le flux entrant fp */ int fget_c(FILE *fp) { int ret = 0; if (fp != NULL) { ret = fgetc(fp); if (ret != '\n' && ret != EOF) { int c; while ((c = fgetc(fp)) != '\n' && c != EOF) { } } } return ret; } /* -tc- permet de saisir proprement une chaine sur le flux d'entree standard */ int fget_s(char *buffer, size_t bufsize, FILE *fp) { int err = 0; if (buffer != NULL && bufsize > 1 && fp != NULL) { if (fgets(buffer, bufsize, fp) != NULL) { err = fclean(buffer, fp); } else { if (feof(fp) == 1) { /* -tc- EOF */ err = EOF; } } } else { /* -tc- erreur: buffer et fp ne doivent pas etre NULL */ err = 2; } return err; } /* -tc- permet la saisie securisee d'un entier sur le flux d'entree standard */ int fget_int(int *value, FILE *fp) { int err = 0; if (value != NULL && fp != NULL) { char buffer[15] = ""; char *pend = NULL; if (fget_s(buffer, sizeof buffer, fp) != 1) { /* -tc- conversion de la chaine en entier */ *value = strtol(buffer, &pend, 0); if (*pend != 0) { /* -tc- erreur de format */ err = 1; } } } else { /* -tc- erreur: value et fp ne doivent pas etre NULL */ err = 2; } return err; } /* -tc- permet la saisie d'une entree a partir du fichier contenant la liste des etudiants */ int etudiant_get(etudiant *self, FILE *fp) { int err = 0; if (self != NULL && fp != NULL) { char buffer[60] = ""; if ((err = fget_s(buffer, sizeof buffer, fp)) == 0) { int rv = sscanf(buffer, "%19[^,],%19[^,],%d", self->nom, self->prenom, &self->code); if (rv != 3) { err = 1; } } } return err; } /* -tc- permet d'ajouter une entree dans le fichier contenant la liste des etudiants */ void etudiant_enreg(etudiant *self, FILE *fp) { if (self != NULL && fp != NULL) { fprintf(fp, "%s,%s,%d\n", self->nom, self->prenom, self->code); } }
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++
+
bonsoir tout le monde,
bon je vous poste ici seulement ma nouvelle suppression qui m'a permis de revenir au menu principal,mais la ya un autre probleme ,aucune suppression n'a pu etre faite:,je sais pas pourquoi parce que le tout Me parait logiquement bien fait!
la methode est aussi expliqué dans le site que Monsieur Emmanuel m'a donné
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 void suppression() { FILE*p;\\le pointeur sur le nouveau fichier FILE*f;\\le pointeur sur l'ancien fichier char name[20]; etudiant e; \controle de l'ouverture des 2 fichiers do { f=fopen("etudiant.txt","w"); if(f==NULL) printf("impossible d'ouvrir le fichier"); } while(f==NULL); do { p=fopen("eleve.txt","w"); if(f==NULL) printf("impossible d'ouvrir le fichier"); } while(p==NULL); printf("quel etudiant voulez vous supprimez?"); scanf("%s",name); while(!feof(f)) { fread(&e,sizeof(e),1,f); if(strcmp(e.nom,name)!=0) fwrite(&e,sizeof(e),1,p); } fclose(f); fclose(p); rename("eleve.txt","etudiant.txt"); }
http://emmanuel-delahaye.developpez....es.htm#fichier
(fread est la,le if aussi ,le fwrite....)
sinon pour le feof ,j'arrive toujours pas à saisir en quoi elle n'est pas bien utilisé dans mon code?
j'ai lu le http://emmanuel-delahaye.developpez....es.htm#fichier mais j'aarive toujours pas à detecter la faute!
Ahem... Dans mon article, il n'est certainement pas dit d'utiliser feof() comme ça :
Euh, c'est quoi çà ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 while(!feof(f)) { fread(&e,sizeof(e),1,f); if(strcmp(e.nom,name)!=0) fwrite(&e,sizeof(e),1,p); }
je rappelle qu'en C, les commentaires, c'est /* ... */
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 FILE*p;\\le pointeur sur le nouveau fichier
Quand à
Ca n'a aucun sens. Pourquoi ces boucles ? Pourquoi ouvrir les 2 fichiers en mode "w" (et donc les détruire) ?
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 do { f=fopen("etudiant.txt","w"); if(f==NULL) printf("impossible d'ouvrir le fichier"); } while(f==NULL); do { p=fopen("eleve.txt","w"); if(f==NULL) printf("impossible d'ouvrir le fichier"); } while(p==NULL);
Reprenons pas à pas .
1 - On commence par ouvrir les 2 fichiers correctement :
- on donne un nom correct et clair aux pointeurs
- on ouvre l'ancien fichier le lecture et le nouveau en écriture.
- on utilise le mode binaire ("rb", "wb"), car il s'agit visiblement d'un fichier binaire composé d'une séquence structures de type 'etudiant'.
ensuite, on vérifie que tout s'est bien passé, et on en profite pour placer le code pour fermer correctement les fichiers. (le traitement se fera entre les deux, évidemment) :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 FILE *fp_old = fopen ("etudiant.txt", "rb"); FILE *fp_new = fopen ("eleve.txt", "wb");
On ajoute une saisie correcte du nom de l'étudiant :
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 void suppression (void) { FILE *fp_old = fopen ("etudiant.txt", "rb"); if (fp_old != NULL) { FILE *fp_new = fopen ("eleve.txt", "wb"); if (fp_new != NULL) { /* traitement a venir */ fclose (fp_new), fp_new = NULL; } else { printf ("impossible d'ouvrir le nouveau fichier"); } fclose (fp_old), fp_old = NULL; } else { printf ("impossible d'ouvrir l'ancien fichier"); } }
enfin, il faut boucler correctement et faire le filtre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 void suppression (void) { <...> if (fp_new != NULL) { char nom[20]; printf ("quel etudiant voulez vous supprimer ? "); fgets (nom, sizeof nom, stdin); fclean (nom, stdin); /* traitement a venir */ <...>
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 { etudiant e; while (fread (&e, sizeof e, 1, fp_old) == 1) { if (strcmp (e.nom, name) != 0) { fwrite (&e, sizeof e, 1, fp_new); } else { printf ("etudiant '%s' supprime\n", name); } } }
c'est seulement une erreur de frappe!j'ouvre l'un en ecriture l'autre en lecture bien sur!Ca n'a aucun sens. Pourquoi ces boucles ? Pourquoi ouvrir les 2 fichiers en mode "w" (et donc les détruire) ?
pour les boucles c'est une sorte d'essai pour ouvrir le fichier.
s'explique par:tant que je suis pas encore arrivée a la fin de mon fichier
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 while(!feof(f)) { fread(&e,sizeof(e),1,f); if(strcmp(e.nom,name)!=0) fwrite(&e,sizeof(e),1,p); }
je lis mon enregistrement(par fread()),si je trouve que mon nom a supprimer concide avec le nom de mon enregitrement je le transfert pas au nouveau fichier.
ici vous avez utilisez une autre methode:tant que je suis en train de lire mon enregistrement je fais....
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 while (fread (&e, sizeof e, 1, fp_old) == 1) { if (strcmp (e.nom, name) != 0) { fwrite (&e, sizeof e, 1, fp_new); } else { printf ("etudiant '%s' supprime\n", name); } }
donc les 2 boucles auront le meme effet au niveau de l'execution de mon programme ... c'est bien ça non?
Décidément, malgré toutes les explications données, tu n'arrives pas à comprendre le fonctionnement de feof(). Je ne sais plus quoi faire. Il est dit que feof() n'a de sens qu'après que la détection de la fin de lecture ait eu lieu. La séquence
- feof()
- fread()
est donc une absurdité étant donné que c'est fread() qui détecte la fin de lecture. La valeur retournée par feof() avant la fin de lecture n'est pas définie.
D'autre part, feof() est rarement utile, puisqu'il ne sert qu'à identifier la cause de la fin de lecture, qui peut être 'Fin de fichier atteinte' (feof() retourne alors 1) ou 'erreur de lecture' (ferror() retourne 1).
Je n'ai pas utilisé une 'autre' méthode. J'ai utilisé une méthode correcte qui s'appuie sur le fait que semble ne pas comprendre : c'est la fonction de lecture qui indique la fin de lecture et rien d'autre. Ton code est faux. Que se passe-t-il si il y a une erreur de lecture ? Boucle infinie.ici vous avez utilisez une autre methode:tant que je suis en train de lire mon enregistrement je fais....
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 while (fread (&e, sizeof e, 1, fp_old) == 1) { if (strcmp (e.nom, name) != 0) { fwrite (&e, sizeof e, 1, fp_new); } else { printf ("etudiant '%s' supprime\n", name); } }
donc les 2 boucles auront le meme effet au niveau de l'execution de mon programme ... c'est bien ça non?
Bon, c'est clair maintenant ? Comment tu te formes au langage C ?
oui oui c'est trés clair maintenant! je vous remercie infiniment Monsieur Emmanuel d'avoir accordé tout ce temps pour mes problemesBon, c'est clair maintenant ? Comment tu te formes au langage C ?
sinon comment je me forme?:en fait le cours de prof n'est pas toujours complet ,pas toujours d'explication...(on s'est meme pas arretés sur la façon dont le feof fonctionne... et beaucoup d'autre chose)
je me suis apres tombé sur le cours que vous venez de me deconseillez..(merci!!)
et ça me sera trés utile si vous me conseillez un bon cours...![]()
vous avez tout fait Monsieur...le probleme reside dans mes capacités trés ,disant trop faible(mais que j'essaie d'ameliorer ....enfin esperons!)Je ne sais plus quoi faire.
Partager