L'approche en deux passes me semblait plus simple à mettre en oeuvre dans un premier temps (dans la mesure où c'est possible).Envoyé par Médinoc
Thierry
L'approche en deux passes me semblait plus simple à mettre en oeuvre dans un premier temps (dans la mesure où c'est possible).Envoyé par Médinoc
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++
+
Oui jusqu'à là ça va.. je pense, à la lecture j'ai compris. Merci !!Envoyé par mujigka
Mais comment faire pour passer :
en paramètre dans une fonction ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 char (*p_date)[50]=NULL;
Nous allons donc mettre tout cela en fonctions avec:
- une fonction de création du tableau (constructeur)
- une fonction de destruction du tableau (destructeur: en principe un free suffit, mais bon!)
- une fonction permettant d'afficher le contenu du tableau
Fonction d'affichage du tableau:
La principale difficulté de cette fonction réside au niveau du propotype. Comment déclarer une fonction qui retourne un pointeur sur 50 caractères. C'est je l'avoue un peu complexe:
une fonction qui retourne un caractère s'écrit:
Maintenant, une fonction qui retourne un pointeur sur un caractère s'écrit:
Code : Sélectionner tout - Visualiser dans une fenêtre à part char fonction(void);
Jusque là, c'est facile. Maintenant, une fonction qui retourne un pointeur sur un tableau de caractère s'écrit:
Code : Sélectionner tout - Visualiser dans une fenêtre à part char *fonction(void);
Nous voulons un fonction qui retroune un pointeur sur un tableau de caractères, et qui prend en paramètre le nombre d'éléments que doit contenir le tableau, c'est à dire le nombre de chaines de caractères contenues dans ton fichier. On a donc:
Code : Sélectionner tout - Visualiser dans une fenêtre à part char ( *fonction() )[50];
Le plus difficile est fait. Nous avons plus qu'à encapsuler le code responsable de l'allocation mémoire et de l'initialisation dans la fonction. Il vient:
Code : Sélectionner tout - Visualiser dans une fenêtre à part char ( *fonction(int nombre_chaines) )[50];
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 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXLEN 50 /* Longueur maximale de tes chaines de caractères */ /** * Crée un tableau de n_chaines chaines de MAXLEN caractères */ char (*tableau_creer(int n_chaines))[MAXLEN] { char (*p_tableau)[MAXLEN] = NULL; if (n_chaines > 0) { p_tableau = malloc(n_chaines * sizeof *p_tableau); if (p_tableau != NULL) { /* Toutes les cases du tableau sont initialisées à 0 */ memset(p_tableau, 0, n_chaines * sizeof *p_tableau); } } return p_tableau; }
Fonction permettant d'afficher le contenu du tableau:
La valeur du pointeur n'étant pas modifiée au sein de cette fonction, on
peut se contenter du prototype suivant:
Ce qui nous donne en vrai:
Code : Sélectionner tout - Visualiser dans une fenêtre à part void fonction(char (*tableau)[50], int nombre_chaines);
Je ne pense pas qu'il y ait de problème particulier avec cette fonction, mais n'hésite pas à poser des questions si c'est le cas.
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 /** * Affiche un tableau de n_chaines chaines de MAXLEN caractères */ void tableau_afficher(char (*p_tab)[MAXLEN], int n_chaines) { if (p_tab != NULL && n_chaines > 0) { int i; for (i = 0; i < n_chaines; ++i) { if (p_tab[i][0] == '\0') { puts("(chaine vide)"); } else { puts(p_tab[i]); } } } }
Fonction de destruction du tableau:
Pour terminer, regardons la fonction de destruction. En principe, un appel à free() nous suffit pour libérer la mémoire allouée pour le tableau. Voici le comportement de notre fonction de destruction. Nous voulons que cette fonction libère l'espace alloué au tableau, ET qu'elle ré-initialise la valeur du pointeur passé en argument à NULL. Comme le passage d'un argument à fonction se fait par copie en C, nous devons utiliser un niveau d'indirection suuplémentaire. Exemple:
Cette fonction n'est pas capable de modifier la valeur de nombre à cause du passage par copie.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 void fonction(int a) { a = 10; } /* ... */ int nombre = 0; fonction(nombre); printf("%d\n", nombre); /* Ici, nombre vaut 0 */
En utilisant un niveau d'indirection supplémentaire, on parvient à modifier la valeur de nombre à l'intérieur de la fonction. Et bien, c'est la même chose avec notre pointeur sur chaine de caractère:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 void fonction(int *a) { *a = 10; } /* ... */ int nombre = 0; fonction(nombre); printf("%d\n", nombre); /* Ici, nombre vaut 10 */
Voici donc notre fonction destructeur:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 void fonction(char (**pp_tab)[50]) { *pp_tab = NULL; } /* ... */ char un_tableau[50] = "Bienvenue sur developpez!"; char (*notre_pointeur)[50] = &un_tableau; fonction(¬re_pointeur); printf("%p\n", (void *) notre_pointeur); /* Ici, notre_pointeur vaut NULL */
Voilà, nous donc vu toutes les manières de passer notre pointeur sur MAXLEN (vaut 50 dans ton cas) caractères en argument d'une fonction, et pour récupérer sa valeur en retour d'une fonction (voir tableau_creer()). Voici un récapitulatif du code complet:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 /** * détruit un tableau de chaines de MAXLEN caractères */ void tableau_detruire(char (**pp_tab)[MAXLEN]) { if (pp_tab != NULL && *pp_tab != NULL) { char (*p_tableau)[MAXLEN] = *pp_tab; free(p_tableau); /* Il faut un niveau d'indirection supplémentaire pour ré-initialiser le pointeur pointé par pp_tab à NULL */ *pp_tab = NULL; } }
Si tu ne comprends pas, n'hésite pas à poser des questions. Maintenant, il te reste à déterminer combien de chaines sont contenues dans ton fichier, puis à réaliser des saisies sécurisées (c'est relativement facile, comme tu es sûr qu'aucune chaine ne sera plus longue que 50 caractères). A toi de jouer... poste ton 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 #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXLEN 50 /** * Crée un tableau de n_chaines chaines de MAXLEN caractères */ char (*tableau_creer(int n_chaines))[MAXLEN] { char (*p_tableau)[MAXLEN] = NULL; if (n_chaines > 0) { p_tableau = malloc(n_chaines * sizeof *p_tableau); if (p_tableau != NULL) { /* Toutes les cases du tableau sont initialisées à 0 */ memset(p_tableau, 0, n_chaines * sizeof *p_tableau); } } return p_tableau; } /** * détruit un tableau de chaines de MAXLEN caractères */ void tableau_detruire(char (**pp_tab)[MAXLEN]) { if (pp_tab != NULL && *pp_tab != NULL) { char (*p_tableau)[MAXLEN] = *pp_tab; free(p_tableau); /* Il faut un niveau d'indirection supplémentaire pour ré-initialiser le pointeur pointé par pp_tab à NULL */ *pp_tab = NULL; } } /** * Affiche un tableau de n_chaines chaines de MAXLEN caractères */ void tableau_afficher(char (*p_tab)[MAXLEN], int n_chaines) { if (p_tab != NULL && n_chaines > 0) { int i; for (i = 0; i < n_chaines; ++i) { if (p_tab[i][0] == '\0') { puts("(chaine vide)"); } else { puts(p_tab[i]); } } } } int main(void) { int err = EXIT_SUCCESS; int n_chaines = 3; char (*p_mon_tableau)[MAXLEN] = NULL; /* On crée le tableau */ p_mon_tableau = tableau_creer(n_chaines); if (p_mon_tableau != NULL) /* Si pas d'erreur d'allocation mémoire */ { /* On affiche le tableau */ tableau_afficher(p_mon_tableau, n_chaines); /* Et lorsqu'on a plus besoin du tableau, on libère la mémoire */ tableau_detruire(&p_mon_tableau); } else { fprintf(stderr, "Erreur d'allocation!\n"); err = EXIT_FAILURE; } return err; }
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++
+
Merci, à la première lecture je n'ai pas encore tout cerné mais ce n'est pas du chinois ! C'est déjà ça! Il faudra aussi que je digère la fonction suivie par [50] ... étonnant ! Je n'aurais pas pu le trouver toute seule.
Je vais relire tout demain, et je vais également essayer d'intégrer tout cela à mon code. C'est en faisant qu'on apprend non ?
J'ai déjà écrit la partie du code qui définit le nombre de chaîne, et ça a l'air de fonctionner.
Je posterai également mon code plus tard.
Encore merci !
J'admets que c'est une notation barbare. Il est possible de faire autrement. A lire que lorsque tu auras compris le reste de mon exemple, sous peine de t'embrouiller avec 15 méthodes différentes.Envoyé par acryline
Tu peux te simplifier la vie par exemple en retournant simplement une adresse générique au lieu d'un pointeur sur tableau de caractères (ATTENTION: cette méthode présente des dangers):
Là, il n'y aucune modification au niveau de l'utilisation de la fonction, si ce n'est qu'il faut faire TRES attention à affecter la valeur retournée à un pointeur du bon type (personnellement, je déconseille cette façon de faire).
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 /** * Crée un tableau de n_chaines chaines de MAXLEN caractères */ void *tableau_creer(int n_chaines) { char (*p_tableau)[MAXLEN] = NULL; if (n_chaines > 0) { p_tableau = malloc(n_chaines * sizeof *p_tableau); if (p_tableau != NULL) { /* Toutes les cases du tableau sont initialisées à 0 */ memset(p_tableau, 0, n_chaines * sizeof *p_tableau); } } return (void *) p_tableau; }
Tu peux également faire comme avec la fonction tableau_detruire(), et retourner le tableau alloué, via les paramètre de la fonction. Cela te permet d'utiliser la valeur de retour de la fonction pour retourner des codes d'erreur bienvenus. Voici un exemple remanié de la fonction tableau_creer():
Bonne lecture
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 /* Constantes utilisées pour les codes d'erreurs retournés par la fonction */ typedef enum Tableau_err_ { TABLEAU_OK, TABLEAU_ERR_TAILLE, TABLEAU_ERR_NULL_ARG, TABLEAU_ERR_MEMOIRE, TABLEAU_ERR_INCONNU } Tableau_err_e; /** * Crée un tableau de n_chaines chaines de MAXLEN caractères */ Tableau_err_e tableau_creer(char (**pp_tab)[MAXLEN], int n_chaines) { Tableau_err_e err = TABLEAU_OK; if (pp_tab != NULL) { if (n_chaines > 0) { char (*p_tableau)[MAXLEN] = *pp_tab; p_tableau = malloc(n_chaines * sizeof *p_tableau); if (p_tableau != NULL) { /* Toutes les cases du tableau sont initialisées à 0 */ memset(p_tableau, 0, n_chaines * sizeof *p_tableau); } else { err = TABLEAU_ERR_MEMOIRE; } *pp_tab = p_tableau; } else { err = TABLEAU_ERR_TAILLE; } } else { err = TABLEAU_ERR_NULL_ARG; } return err; }
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++
+
Voilà enfin j'y suis arrivée avec ton aide ! Encore merci.
Voici une partie de mon code (mais j'ai bcp pompé ton code --> Je l'ai intégré ) Autrement tout n'est pas encore terminé, comme les message d'erreur par exemple. Je compte aussi retourner un code d'erreur pour chaque fonction. A noter que je travaille avec la bibliothèque GTK+:
Fonction pour afficher les chaînes
Trouver le nombre de chaînes dans le fichier
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 void afficherDate (GADGET *p_gadget) { gchar (*p_mon_tableau)[MAXLEN] = NULL; glong enreg =0,i=0; //Charger le nombre d'entrées pour la question nombreEnregistrement (p_gadget,&enreg); // On crée le tableau p_mon_tableau = tableau_creer(enreg); // Afficher toutes les dates dans la fenêtre bilan chargerAfficherDates (&p_mon_tableau, enreg); // Et lorsqu'on a plus besoin du tableau, on libère la mémoire tableau_detruire(&p_mon_tableau); }
La fonction de mujigka pour créer le tableau
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 void nombreEnregistrement(GADGET *p_gadget,glong *enreg) { FILE* fichier = NULL; glong i=0 ; gchar enregistrement[TAILLE_TEXTE]={0}; //lire jusqu'à la question -1(4 lignes à chaque fois) fichier = fopen("question.qt", "r+"); if (fichier != NULL) { for(i=0;i<p_gadget->question-1;i++) { fgets(enregistrement,TAILLE_TEXTE,fichier); fgets(enregistrement,TAILLE_TEXTE,fichier); fgets(enregistrement,TAILLE_TEXTE,fichier); fgets(enregistrement,TAILLE_TEXTE,fichier); } fgets(enregistrement,TAILLE_TEXTE,fichier); fgets(enregistrement,TAILLE_TEXTE,fichier); //convertir la chaîne enregistrement en nombre *enreg = strtol(enregistrement,NULL,10); fclose(fichier); } else { //message pour dire qu'il n'y a pas de fichier } }
Fonction de mujigka pour détruire le tableau
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 gchar (*tableau_creer(int n_chaines))[MAXLEN] { char (*p_tableau)[MAXLEN] = NULL; if (n_chaines > 0) { p_tableau = malloc(n_chaines * sizeof *p_tableau); if (p_tableau != NULL) { // Toutes les cases du tableau sont initialisées à 0 memset(p_tableau, 0, n_chaines * sizeof *p_tableau); } } return p_tableau; }
Affichage des chaîne de caractères, pour l'instant seulement dans la console.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 void tableau_detruire(gchar (**pp_tab)[MAXLEN]) { if (pp_tab != NULL && *pp_tab != NULL) { gchar (*p_tableau)[MAXLEN] = *pp_tab; free(p_tableau); // Il faut un niveau d'indirection supplémentaire pour // ré-initialiser le pointeur pointé par pp_tab à NULL *pp_tab = NULL; } }
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 void chargerAfficherDates (gchar (**pp_tab)[MAXLEN], glong enreg) { FILE* fichier = NULL; glong i=0; if (pp_tab != NULL && pp_tab!=NULL && enreg !=0) { gchar (*p_tableau)[MAXLEN] = *pp_tab; fichier = fopen("reponses.txt", "r+"); if (fichier != NULL) { for(i=0;i<enreg;i++) { fgets(p_tableau[i],MAXLEN,fichier); printf("%s",p_tableau[i]); } fclose(fichier); } else { printf("erreur"); } } else { //message d'erreur } }
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager