google + sizeof
http://www.lri.fr/~aze/page_c/aide_c/sizeof.html
;-)
Version imprimable
google + sizeof
http://www.lri.fr/~aze/page_c/aide_c/sizeof.html
;-)
Tu as posté pendant mon EDIT, voila donc l'EDIT en question que je retire du post précédent pour que tu puisses voir que j'ai répondu ^^
Tu va peut etre m'en vouloir, mais pourtant je te jure que j'ai regardé !
J'ai reglé a peu près tout les problemes, seulement, j'ai un souci au niveau du fprintf ( encore une fois, c'est un souci de compréhension ) :
Lorseque tu fais : "fprintf(nouveauFichier, "%i%s %s %s %s", num, col1, chColonne, col3, col4);", le nouveauFichier est le nom du fichier dans lequel doivent s'enregistrer les modifications, ou bien est-ce une variable qui stocke les modifications ?
Je pose cette question parceque sur les sites ou j'ai chercher un peu le fonctionnement, tout indique qu'il s'agit d'une variable, ce qui expliquerais pourquoi le compilateur veut que je le déclare. Seulement l'ennui, c'est que si je le déclare, j'ai l'erreur suivante :
'fprintf' : impossible de convertir le paramètre 1 de 'int' en 'FILE *'
Je dois bien avouer que je ne comprend pas du tout ce message d'erreur, pourquoi parle-t-il de paramettre 1 de int ? Pire encore, pourquoi faire intervenir FILE* ? Cela voudrait donc dire que l'on veut ecrire sur le fichier et que donc, nouveauFichier est bien le nom du nouveau fichier, et non d'une variable ?
Voila ce qui me turlupine, j'espere ne pas t'avoir trop énervé ^^
Bon,
Un petit coup de pouce...
Voici deux versions exemple que j'ai eu le temps de coder cet AM qui permettent de faire l'exigence (1) déjà citée plus haut, à savoir regarder si il y a modif dans la colonne 2 et ajouter en fonction un compteur au début sur 5 digits.
La version que je vais appeler alpha remplit l'exigence (1) mais ne respecte pas l'espacement initial entre les colonnes.
La version que je vais appeler beta remplit l'exigence (1) et respecte l'espacement initial entre les colonnes.
Je te laisse le soin de modulariser le tout, d'utiliser argv et argc pour ne pas avoir de nom de fichier en dur, etc...
A propos de l'utilisation d'un fichier .ini : c'est plus difficile à mettre en oeuvre, beaucoup de contrôles, à la fois en lecture, et aussi à l'insertion...
alpha :
Code:
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 #include <stdio.h> #include <stdlib.h> #include <string.h> #define M_CLINE 255 #define M_CCOL1 30 #define M_CCOL2 15 #define M_CCOL3 15 #define M_CCOL4 30 #define STR_(x) #x #define STR(x) STR_(x) int main(void) { FILE * fp_in = NULL; FILE * fp_out = NULL; char * pLine = NULL; char line[M_CLINE+1 ] = ""; char col1[M_CCOL1+1] = ""; char col2[M_CCOL2+1] = ""; char prevcol2[M_CCOL2+1] = ""; char col3[M_CCOL3+1] = ""; char col4[M_CCOL4+1] = ""; int cpt = 0, rc = 0; /* OUVERTURE FICHIERS */ fp_in = fopen("X04.txt", "r"); if (!fp_in) { fprintf(stderr, "Cannot open X04.txt for reading.\n"); exit(EXIT_FAILURE); } fp_out = fopen("X04.txt.out", "w"); if (!fp_out) { fprintf(stderr, "Cannot open X04.txt.out for writing.\n"); exit(EXIT_FAILURE); } /* BOUCLE DE LECTURE ECRITURE */ /* lecture 1ere ligne */ pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); ++cpt; while (pLine) { /* Récupération des colonnes 1 à 4 */ if ( sscanf( line, "%" STR(M_CCOL1) "s %" STR(M_CCOL2) "s %" STR(M_CCOL3) "s %" STR(M_CCOL4) "s", col1, col2, col3, col4) != 4 ) { break; rc = -1; } /* RAU (Remise A Un) de cpt */ if ( strcmp(col2, prevcol2) ) { cpt = 1; } /* Ecriture du compteur et des colonnes*/ if ( fprintf(fp_out,"%05d%s %s %s %s\n", cpt, col1, col2, col3, col4) < 0 ) { break; rc = -1; } /* lecture n-ième ligne */ pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); ++cpt; /* cpt, une fois formaté, c'est sur 5 digits, donc de 1 à 99999 */ if (cpt == 100000) { break; rc = -1; } /* sauvegarde colonne 2 précédente */ strcpy(prevcol2, col2); } /* FERMETURE FICHIERS */ /* On enlève le fichier généré si il y a eu un souci */ if (rc < 0 || ferror(fp_in) || !feof(fp_in) || ferror(fp_out) ) { fclose(fp_in); fclose(fp_out); fprintf(stderr, "An error occured while processing, trying to remove X04.txt.out\n"); rc = remove("X04.txt.out"); if (!rc) { fprintf(stderr, "Cannot remove X04.txt.out\n"); } } else { fclose(fp_in); fclose(fp_out); } return 0; }
beta :
A+Code:
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 #include <stdio.h> #include <stdlib.h> #include <string.h> #define M_CLINE 255 #define M_CCOL2 15 #define STR_(x) #x #define STR(x) STR_(x) int main(void) { FILE * fp_in = NULL; FILE * fp_out = NULL; char * pLine = NULL; char line[M_CLINE+1 ] = ""; char col2[M_CCOL2+1] = ""; char prevcol2[M_CCOL2+1] = ""; int cpt = 0, rc = 0; /* OUVERTURE FICHIERS */ fp_in = fopen("X04.txt", "r"); if (!fp_in) { fprintf(stderr, "Cannot open X04.txt for reading.\n"); exit(EXIT_FAILURE); } fp_out = fopen("X04.txt.out", "w"); if (!fp_out) { fprintf(stderr, "Cannot open X04.txt.out for writing.\n"); exit(EXIT_FAILURE); } /* BOUCLE DE LECTURE ECRITURE */ /* lecture 1ere ligne */ pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); ++cpt; while (pLine) { /* Récupération de la colonne 2 */ if ( sscanf( line, "%*s %" STR(M_CCOL2) "s %*s %*s",col2) != 1 ) { break; rc = -1; } /* RAU (Remise A Un) de cpt */ if ( strcmp(col2, prevcol2) ) { cpt = 1; } /* écriture compteur formaté sur 5 digits */ if ( fprintf(fp_out,"%05d", cpt) < 0 ) { break; rc = -1; } /* écriture de la ligne non modifiée après le compteur */ /* attention au '\n' qui traine dans fgets() */ if ( strchr(line, '\n') ) { if ( fprintf(fp_out,"%s", line) < 0 ) { break; rc = -1; } } else { if ( fprintf(fp_out,"%s\n", line) < 0 ) { break; rc = -1; } } /* lecture n-ième ligne */ pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); ++cpt; /* cpt, une fois formaté, c'est sur 5 digits, donc de 1 à 99999 */ if (cpt == 100000) { break; rc = -1; } /* sauvegarde colonne 2 précédente */ strcpy(prevcol2, col2); } /* FERMETURE FICHIERS */ /* On enlève le fichier généré si il y a eu un souci */ if (rc < 0 || ferror(fp_in) || !feof(fp_in) || ferror(fp_out) ) { fclose(fp_in); fclose(fp_out); fprintf(stderr, "An error occured while processing, trying to remove X04.txt.out\n"); rc = remove("X04.txt.out"); if (!rc) { fprintf(stderr, "Cannot remove X04.txt.out\n"); } } else { fclose(fp_in); fclose(fp_out); } return 0; }
ouaaaaa, c'est un sacré programme que tu as fait la ! ^^
Pourrais tu s'il te plais m'expliquer a quoi correspondent tes variables ? Parceque la, j'ai un mal fou a suivre ce que tu as fait, je comprend pas toujours tout lol ^^
Juste les variables alors, car le code est documenté. Je pense que ton/tes problèmes de compréhension vont venir de sscanf() et des 2 macros bizarres STR() et STR_() : la FAQ est là pour ça.Citation:
Envoyé par SnaKou
A+Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 /* Pointeur pour récupérer le retour de fgets() */ char * pLine = NULL; /* Tableau contenant la ligne lue par fgets() */ char line[M_CLINE+1 ] = ""; /* Tableau pour stocker la colonne 1 sous forme de chaine de caractères */ char col1[M_CCOL1+1] = ""; /* Tableau pour stocker la colonne 2 sous forme de chaine de caractères */ char col2[M_CCOL2+1] = ""; /* Tableau pour stocker la colonne 2 lue au coup précédent */ char prevcol2[M_CCOL2+1] = ""; /* Tableau pour stocker la colonne 3 sous forme de chaine de caractères */ char col3[M_CCOL3+1] = ""; /* Tableau pour stocker la colonne 4 sous forme de chaine de caractères */ char col4[M_CCOL4+1] = ""; /* Le compteur */ int cpt = 0; /* Une variable entière dont je me sers pour le traitement des erreurs */ int rc = 0;
Merci pour cette réponse, c'est tout de suite beaucoup plus clair pour moi !
Je comprend a présent la totalité du programme, sauf une chose, comme tu l'avais fait remarqué : les STR() et STR_(), en cherchant une bonne demi-heure sur google et dans la FAQ, j'ai vu qu'il s'agissait de macros, ayant pour but de remplacer un élément par un autre, ainsi tu remplace STR_(x) et STR(x) par #x, seulement, ce qui n'est pas expliqué dans les sites que j'ai visité, c'est l'urilisation du #x, qu'est-ce que cela représent finallement ? Parceque du coups, apres quand je vois que tu marques STR(M_CCOL2), j'en déduis que le programme lira #x(M_CCOL2), mais je ne comprend pas le role de ce #x, pourrais tu m'éclairer la dessus s'il te plais ?
# est l'opérateur de [english]stringification[/english] des macros, c'est-à-dire que STR(blabla) donnera "blabla" (guillemets compris).
Il existe aussi ##, l'opérateur de concaténation qui peut entre autres permettre de créer un identificateur en plusieurs morceaux (sous Windows, on peut voir dans winnt.h la macro DECLARE_HANDLE(x) qui déclare pour tout nom une structure factice et un type pointeur:
Code:
1
2
3
4
5
6
7
8 //C'est pas exactement ça, mais c'est un truc du genre: #define DECLARE_HANDLE(x) typedef struct x ## __ * x; //Utilisation: DECLARE_HANDLE(HWND) //donne: //typedef struct HWND__ * HWND; //(noter que le type est "HWND__" avec les undescores collés au nom).
Merci pour tes explications Médinoc ! Ca m'aide a y voir plus clair ^^
Cependant, ce que je ne comprend toujours pas, c'est quel a été l'intéret de faire ce macros dans le programme de Foobar1329 ? On t ils vraiments des roles indispensables ?
il a fait ça pour essayer de rajouter une certaine "flexibilité" de ton programme en passant par des "#define" pour définir la taille des colonnes de ton fichiers.
Donc ton logiciel fonctionnera avec d'autre type de fichier (structure un peu différente) moyennant un changement de ces #define et une recompilation.
Enfin je pense que c'est pour ça qu'il a fait ça.
Par contre, je ne connais pas trop le préprocesseur : La double définition permet de garantir que STR(M_CCOL2) donnera bien "15" et non "M_CCOL2", c'est ça ?
Est-ce que STR_(M_CCOL2) est garanti donner "M_CCOL2" ?
Je vien d'essayer de rajouter au programme le fait que le fichier Z04 doit lui aussi etre modifié, de la meme manière que le X04, pour ca, j'ai voulu tout simplement rajouter ces deux lignes dans la partie OUVERTURE FICHIER :
Code:
1
2
3
4
5 fp_in = fopen("Z04.txt", "r"); if (!fp_in) { fprintf(stderr, "Impossible d'ouvrir le fichier Z04.txt pour lecture.\n"); exit(EXIT_FAILURE); }
Seulement, l'ennui, c'est qu'en faisant ça, seul le fichier Z04 est modifié, et non le X04 :(Code:
1
2
3
4
5 fp_out = fopen("Z04.out.txt", "w"); if (!fp_out) { fprintf(stderr, "Impossible d'ouvrir le fichier Z04.txt pour lecture.\n"); exit(EXIT_FAILURE); }
Comment dois-je m'y prendre pour que le programme fasse les modifications sur les 2 fichiers, et non seulement sur le X04 ?
déclarer un fp_in2 et fp_out2, et faire les écritures sur les deux ?
Au fait : corrige les messages d'erreur : Il y a un léger problème dedans.
J'ai pensé a faire un fp_in2 et un fp_out2 ( c'est d'ailleur la premiere chose a laquelle j'ai pensé ensuite ), voila ce que j'ai fait :
Code:
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 #include <stdio.h> #include <stdlib.h> #include <string.h> /*A modifier si le programme doit etre adapté a un autre projet*/ #define M_CLINE 255 #define M_CCOL2 15 /*Nombre de caractères jusqu'a la 2eme colonne*/ #define STR_(x) #x #define STR(x) STR_(x) int main(void) { FILE * fp_in = NULL; FILE * fp_out = NULL; FILE * fp_in2 = NULL; FILE * fp_out2 = NULL; /* Pointeur pour récupérer le retour de fgets() */ char * pLine = NULL; char * pLine2 = NULL; /* Tableau contenant la ligne lue par fgets() */ char line[M_CLINE+1 ] = ""; /* Tableau pour stocker la colonne 2 sous forme de chaine de caractères */ char col2[M_CCOL2+1] = ""; /* Tableau pour stocker la colonne 2 lue au coup précédent */ char prevcol2[M_CCOL2+1] = ""; /* Le compteur */ int cpt = 0; /* Une variable entière dont je me sers pour le traitement des erreurs */ int rc = 0; /* OUVERTURE FICHIERS */ fp_in = fopen("X04.txt", "r"); if (!fp_in) { fprintf(stderr, "Impossible d'ouvrir le fichier X04.txt pour lecture.\n"); exit(EXIT_FAILURE); } fp_in2 = fopen("Z04.txt", "r"); if (!fp_in2) { fprintf(stderr, "Impossible d'ouvrir le fichier Z04.txt pour lecture.\n"); exit(EXIT_FAILURE); } fp_out = fopen("X04.out.txt", "w"); if (!fp_out) { fprintf(stderr, "Impossible d'ouvrir le fichier X04.txt pour lecture.\n"); exit(EXIT_FAILURE); } fp_out2 = fopen("Z04.out.txt", "w"); if (!fp_out2) { fprintf(stderr, "Impossible d'ouvrir le fichier Z04.txt pour lecture.\n"); exit(EXIT_FAILURE); } /* BOUCLE DE LECTURE ECRITURE */ /* Lecture 1ere ligne */ pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); pLine2 = fgets(line, sizeof(line)/sizeof(*line), fp_in2); ++cpt; while (pLine) { /* Récupération de la colonne 2 */ if ( sscanf( line, "%*s %" STR(M_CCOL2) "s %*s %*s",col2) != 1 ) { break; rc = -1; } /* Remise a un de cpt */ if ( strcmp(col2, prevcol2) ) { cpt = 1; } /* Ecriture compteur formaté sur 5 digits */ if ( fprintf(fp_out,"%05d", cpt) < 0 ) { break; rc = -1; } /* Ecriture de la ligne non modifiée après le compteur */ if ( strchr(line, '\n') ) { if ( fprintf(fp_out,"%s", line) < 0 ) { break; rc = -1; } } else { if ( fprintf(fp_out,"%s\n", line) < 0 ) { break; rc = -1; } } while (pLine2) { /* Récupération de la colonne 2 */ if ( sscanf( line, "%*s %" STR(M_CCOL2) "s %*s %*s",col2) != 1 ) { break; rc = -1; } /* Remise a un de cpt */ if ( strcmp(col2, prevcol2) ) { cpt = 1; } /* Ecriture compteur formaté sur 5 digits */ if ( fprintf(fp_out2,"%05d", cpt) < 0 ) { break; rc = -1; } /* Ecriture de la ligne non modifiée après le compteur */ if ( strchr(line, '\n') ) { if ( fprintf(fp_out2,"%s", line) < 0 ) { break; rc = -1; } } else { if ( fprintf(fp_out2,"%s\n", line) < 0 ) { break; rc = -1; } } /* Lecture n-ième ligne */ pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); ++cpt; pLine2 = fgets(line, sizeof(line)/sizeof(*line), fp_in2); ++cpt; /* cpt est sur 5 digits, donc de 1 à 99999 */ if (cpt == 100000) { break; rc = -1; } /* sauvegarde colonne 2 précédente */ strcpy(prevcol2, col2); } /* FERMETURE FICHIERS */ /* On enlève le fichier généré si il y a eu un souci */ if (rc < 0 || ferror(fp_in) || !feof(fp_in) || ferror(fp_out) ) { fclose(fp_in); fclose(fp_out); fprintf(stderr, "Une erreur est survenue durant le déroulement de l'application, effacement du X04.out.txt\n"); rc = remove("X04.txt.out"); if (!rc) { fprintf(stderr, "Impossible de supprimer X04.out.txt\n"); } } else { fclose(fp_in); fclose(fp_out); } if (rc < 0 || ferror(fp_in2) || !feof(fp_in2) || ferror(fp_out2) ) { fclose(fp_in2); fclose(fp_out2); fprintf(stderr, "Une erreur est survenue durant le déroulement de l'application, effacement du X04.out.txt\n"); rc = remove("Z04.txt.out"); if (!rc) { fprintf(stderr, "Impossible de supprimer Z04.out.txt\n"); } } else { fclose(fp_in2); fclose(fp_out2); } return 0; }
L'ennui, c'est qu'a la fin, lors de la compilation, j'ai une grosse erreure :
"fatal error C1075: fin de fichier rencontrée avant que l'élément accolade '{' gauche de 'c:\Documents and Settings\gmoly\Mes documents\Visual Studio Projects\Compteur\Compteur\main.cpp(13)' soit équilibré"
a première vu, tu n'as pas bien fermé ton premiere while(pLine)
tu ouvre l'accolade, mais tu ne la ferme pas.
Si je me trompe pas, elle devrai se fermer après tous tes "if" et donc juste avant ton deuxième while.
edit :
oula non je crois que c'est pire que ça, tu t'es vraiment emmelé les pinceaux dans ton code.
En effet, j'ai bien l'impression que le probleme vien du while mais le souci, c'est que j'arrive pas a le fermer correctement !
En le fermant juste avant le 2eme while, ou on le fermant juste avant le /*FERMETURE FICHIERS*/, le résultat est le meme, c'est a dire que ca compile, mais la fenetre dos reste ouverte, et quand je la ferme et que je vais voir les fichiers créés, il y a bien le X04.out et Z.04.out, seulement le X04 fait 49016 ko et quand on tente de l'ouvrir, plantage de l'explorer, quand au Z04, il est carément vide :(
EDIT : J'ai bien l'impression moi aussi de m'etre totalement planté xD
Je comprend pas pourquoi ca bug comme ca, j'ai pourtant pas l'impression d'avoir fait de grosse bourde, j'étais obligé de faire comme je l'ai fait :/
bon, là j'ai un peu plus de temps. ;-)
Alors dejà ton problème a commencer par l'ajout de tes deux nouveaux fichiers.
Peut tu préciser ici qu'est ce que tu compte faire de ces fichiers ?
Tu veux appliquer le même traitement sur ce fichier ?
X04 -> X04.out
Z04 -> Z04.out
Tu veux faire ça en même temps ?
A mon avis tu te complique la tache pour pas grand chose. Pourquoi ne pas le faire un par un ?
Tu met ton code dans un fonction qui prend par exemple deux paramètres (le nom du fichier a étudier et le nom du fichier qui va être écrit).
Et dans ton main tu appelles deux fois cette fonctions pour traiter des deux fichiers ?
Et tout ça bien sûr si les deux traitement sont indépendant, sinon précise ton soucis.
bon courage
Oui c'est vrai ^^
Donc, pour toi, ce qu'il faudrai, c'est que je fasse deux foix ce codes ? Un pour le X04 et un pour le Z04 ? Ca me semble assez difficile a faire :/
Hello,
He ben, il s'en est passé des choses depuis hier :)Citation:
Envoyé par SnaKou
Tu te punis tout suel avec tes copier-coller sans tout bien saisir :mrgreen: , voilà les erreurs :
- Tu oublies une accolade après le 1er while.
- Pourquoi fais-tu ceci ?
Tu lis la première ligne de fp_in en mettant son contenu dans le tableau line...Et tu écrases cette première ligne avec la première ligne de fp_in2 !! :aie:Code:
1
2
3
4
5
6 [...] pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); pLine2 = fgets(line, sizeof(line)/sizeof(*line), fp_in2); ++cpt; while (pLine) { [...]
Le 1er fgets() fait partie intégrante de la boucle de lecture si je puis dire. Donc le fgets sur fp_in2 n'a rien à faire là !! Il doit être fait pour la lecture de fp_in2, avant le 2ème while !!
- Entre les boucles de lecture/écriture, tu n'as pas remis cpt à zéro !
- Tu n'as pas compris ce que faisait break : cette instruction fait sortir de la boucle, ici dans le cas d'une erreur. Or, tu mets les 2 boucles à la suite, et sans te préocupper d'un possible échec de la 1ère boucle qui agit les fichiers fp_in et fp_out, tu passes dierctement à la seconde boucle (qui ne doit gérer que fp_in2 et fp_out2).
Ca doit se présenter ainsi :
A+Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 /* BOUCLE 1*/ pLine = fgets(line, sizeof(line)/sizeof(*line), fp_in); ++cpt; while (pLine) { /* */ } /* traitement erreurs en cas de sortie de boucle 1 ci-dessus ICI */ /* BOUCLE 2*/ cpt = 0; pLine2 = fgets(line, sizeof(line)/sizeof(*line), fp_in2); ++cpt; while (pLine2) { /* */ } /* traitement erreurs en cas de sortie de boucle 2 ci-dessus ICI */
Citation:
Envoyé par SnaKou
non tu ne fais pas deux fois le code.
Tu fais ce qu'on appelle une fonction que tu appelles 2 fois. Là si tu ne sais pas ce que c'est une fonction, je t'invite à revoir tes cours d'algo.