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
| #include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* -tc- Dans la fonction get_infos_8(), tu traites tous les champs de la structure
comme des chaines de caractere. Je modifie ta structure en fonction de
get_infos_8(). Toutefois, c'est peut-etre get_infos_8() qui n'est pas en
accord avec ta conception */
typedef struct
{
char * nomPays;
char * annee;
char * popuTotale;
char * nbH;
char * nbF;
char * tranchAge; // exemple : 35-36
} infos_pays;
//tres utile pour le switch
typedef enum
{
NOM_PAYS,
ANNEE,
TRANCHAGE,
NBTOTAL,
NBH,
NBF
} infos_type;
static char * copie_chaine(const char *chaine)
{
char * copie = NULL;
if (chaine != NULL)
{
size_t taille = strlen (chaine) + 1;
/* -tc- meme si un char fait un byte par definition en C, il est
dangereux de ne pas se premunir contrer un changement du type a
l'avenir: multiplie taille par sizeof *copie */
copie = malloc (taille * sizeof *copie);
if (copie != NULL)
{
/* -tc- memcpy() n'ajoute pas de caractere nul terminal a la fin
de la chaine et tu ne le fais pas manuellement. Pour copier des
chaines, je prefere la fonction strcat() qui ajoute le '\0'
terminal a la fin de la chaine
memcpy (copie, chaine, taille);
*/
*copie = '\0';
strcat(copie, chaine);
}
}
return copie;
}
static void term_chaine(char *chaine)
{
/* -tc- attention: strchr() prend un entier en deuxieme parametre, et non
une chaine de caracteres */
char * p = strchr(chaine, '\n');
if(p != NULL)
{
*p = 0;
}
}
infos_pays * get_infos_8(const char * file)
{
infos_pays * infos = NULL; //structure de retour
FILE * fic = NULL;
char * k = NULL;
/* -tc- attention: buff a le type tableau de 1000 pointeurs sur chars, alors
que tu veux declarer cette variable comme un tableau de 1000 chars.
Au passage, c'est probablement une bonne idee d'initialiser ton tableau */
char buff [1000] = "";
fic = fopen(file, "r");
if (fic != NULL)
{
if ((fgets (buff, sizeof buff, fic)) != NULL)
{
char * p = buff;
int i = 0;
term_chaine(buff);
infos = malloc (sizeof (* infos));
if (infos != NULL)
{
/* -tc- Je deconseille l'utilisation de strtok() qui a le desavantage
d'utiliser un tampon statique pour stocker ta chaine entre
deux appels, ce qui la rend non réentrante et thread-unsafe.
prefere l'utilisation de strtok_r() (POSIX.1) */
while ((k = strtok(p, ",")) != NULL)
{
if (i == 0)
{
p = NULL;
}
switch (i)
{
case NOM_PAYS:
infos->nomPays = copie_chaine(k);
break;
case ANNEE:
/* -tc- Dans la definition initiale de ta structure, le
champ infos->annee et les suivants sont de type int
et non de type pointeur sur char */
infos->annee = copie_chaine(k);
break;
case TRANCHAGE:
infos->tranchAge = copie_chaine(k);
break;
case NBTOTAL:
infos->popuTotale = copie_chaine(k);
break;
case NBH:
infos->nbH = copie_chaine(k);
break;
case NBF:
infos->nbF = copie_chaine(k);
break;
}
i++; //mot suivant
}
}
}
/* -tc- Une fois que fic est ferme, on reaffecte a fic une adresse
invalide testable, a savoir NULL */
fclose(fic), fic = NULL;
}
/* -tc- ATTENTION: si l'ouverture de ton fichier echoue, infos->nonPays
dereference le pointeur infos dont l'adresse est invalide (NULL). Le
comportement est indetermine ici.
printf("Pays : %s -> Check !", infos->nomPays);
*/
return infos;
} |
Partager