Bonjour,
Je souhaite utiliser la fonction str_split proposée ici. Comment connaître la taille du tableau de chaînes créés afin de le parcourir ?
Version imprimable
Bonjour,
Je souhaite utiliser la fonction str_split proposée ici. Comment connaître la taille du tableau de chaînes créés afin de le parcourir ?
Bonjour,
Il faut parcourir le tableau pour en connaitre la taille :
Code:
1
2
3
4
5
6
7
8
9
10 size_t size = 0; char **result = str_split(......); if(result != NULL) { while(result[size] != NULL) { ++size; } printf("la taille du tableau est %d\n", size); } else { printf("la fonction str_split a échoué\n"); }
Merci.
Je souhaiterais passer le tableau précédemment obtenu (appelé fields) en paramètre à une fonction :
void addProfileLine(char fields[], profile profiles[], int profilescount);
Dans cette fonction je veux remplir la structure profile à partir de fields[1], fields[2]...
Cette syntaxe provoque des warnings à la compilation :
L. 120, c.-à-d. lors de l'appel à la fonction :Code:
1
2
3 "add_profiles.c", line 120: warning: argument #1 is incompatible with prototype: prototype: pointer to char : "add_profiles.h", line 10 argument : pointer to pointer to char
addProfileLine(fields, profiles, profilescount);
J'ai également des warnings dans la fonction elle-même :
Lorsque j'essaie de récupérer les valeurs de fields[0], fields[1], etc. pour remplir ma structure.Code:
1
2
3
4
5 "add_profiles.c", line 202: warning: improper pointer/integer combination: arg #1 "add_profiles.c", line 204: warning: improper pointer/integer combination: op "=" "add_profiles.c", line 206: warning: improper pointer/integer combination: op "=" "add_profiles.c", line 208: warning: improper pointer/integer combination: op "=" "add_profiles.c", line 210: warning: improper pointer/integer combination: op "="
Tu peux poster le code qui crée ce problème ?
EDIT : ton compilateur dit :
Cela veut dire que tu passe à la fonction un tableau de chaine à la place d'une chaine seule. (tu donnes un char ** à la place d'un char *)Code:
1
2
3
4 "add_profiles.c", line 120: warning: argument #1 is incompatible with prototype: prototype: pointer to char : "add_profiles.h", line 10 argument : pointer to pointer to char
fields est un tableau de chaîne retourné par str_split.
Quel doit-être le prototype de la fonction addProfile ? Ceci peut-il fonctionner ?
Code:
1
2
3
4
5 void addProfileLine(char **fields, profile profiles[], int profilescount) { char tmp[100]; strcpy(tmp, fields[0]); //... }
OuiCitation:
Ceci peut-il fonctionner ?
Ça dépend de ce que tu veux faire faire à ta fonction...Citation:
Quel doit-être le prototype de la fonction addProfile ?
Désormais j'ai un coredump Bus Error lorsque j'essaie d'accéder au tableau profiles, après l'avoir rempli avec la fonction addProfile...
La fonction est la suivante :
Elle est appelée dans une boucle :Code:
1
2
3
4
5
6
7
8
9
10
11
12 void addProfile(char *fields[], profile profiles[], int profilescount) { profiles = (profile*)realloc (profiles, (profilescount + 1) * sizeof (profile)); if (NULL == profiles) { fprintf (stderr, "Mémoire insuffisante.\n"); free (profiles); exit (EXIT_FAILURE); } /* profile_id */ profiles[profilescount].profile_id = fields[1]; //... }
Code:
1
2 addProfileLine(fields, profiles, profilescount); ++profilescount;
Montre voir comment tu accèdes aux données.
Sinon, il faut voir que la fonction str_split ne fait pas d'allocation mémoire, donc écrire quelque chose commeest risqué : tu gardes l'adresse mémoire où est stocké ta chaine, mais à la modification de la chaine à découper passée à str_split, cette adresse devient invalide...Code:profiles[profilescount].profile_id = fields[1];
2 remarques...
Il est toujours très nettement plus aisé en C de se servir des pointeurs que de tableaux lorsqu'ils sont passés en paramètres...
- Quand tu écris :
ce serait plus clair (pour toi comme pour un relecteur éventuel) de l'écrire comme :Code:void addProfile(char *fields[], profile profiles[], int profilescount)
Car ici on note bien que profiles (qui va être réalloué) est un pointeur qui doit ressortir modifié de la fonction...Code:void addProfile(char **fields, profile **profiles, int profilescount)
Ce que l'écriture profiles[] ne fait pas, étant (relativement) équivalente à *profiles.
- Enfin, on copie une chaîne avec strcpy, sinon on copie juste le pointeur..
Donc dans :
Code:profiles[profilescount].profile_id = fields[1];
tu ne copies que le pointeur et pas la chaîne...
J'ajouterai qu'il faut se souvenir que la valeur d'une variable changée dans une fonction ne verra pas sa valeur changée dans la fonction appelante.
Donc, réalloué profiles avec :
comme prototype est une erreur si tu veux avoir le nouveau pointeur après la réallocation et la fonction.Code:
1
2 void addProfile(char *fields[], profile profiles[], int profilescount)
Le prototype de souviron34 fonctionne si on ajoute les changements dans la fonction.
Jc
Il faut modifier la fonction, en particulier la ré-assignations de profiles :
me donne une erreurCode:profiles = (profile*)realloc (profiles, (profilescount + 1) * sizeof (profile));
Mais je ne sais pas trop quelle est la bonne syntaxe ici.Code:assignment type mismatch
J'ai essayé la syntaxe suivante, sans succès :
Sinon, je copie bien mes chaînes avec strcpy.Code:**profiles = (profile**)realloc (profiles, (profilescount + 1) * sizeof (profile));
Si t'as du mal avec cette solution, fait simplement :
et retourne ton tableau une fois agrandi.Code:profile *addProfile (char **fields, profile *profiles, int profilescount)
Jc
Le code suivant provoque un coredump :
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 void addProfile(char *fields[], profile **profiles, int profilescount) { profiles = (profile**)realloc (profiles, (profilescount + 1) * sizeof (profile)); if (NULL == profiles) { fprintf (stderr, "Mémoire insuffisante.\n"); free (profiles); exit (EXIT_FAILURE); } /* profile_id */ profiles[profilescount]->profile_id = string2int(fields[1]); } char **fields = NULL; size_t size = 0; profile **profiles; int profilescount = 0; while (fgets(line, LINE_SIZE, fp) != NULL) { fields = str_split(line, ";"); if (fields != NULL) { /* Calcul de la taille du tableau */ while(fields[size] != NULL) { ++size; } if ( PROFILE_FLD_NBR != size ) { printf("Nombre de champs incorrect : %d (%d attendu).\n", size, PROFILE_FLD_NBR); return EXIT_FAILURE; } addProfile(fields, profiles, profilescount); ++profilescount; } }
J'aurai plus vu quelque chose comme :
etCode:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 char **fields = NULL; size_t size = 0; profile *profiles = NULL; int profilescount = 0; while (fgets(line, LINE_SIZE, fp) != NULL) { fields = str_split(line, ";"); if (fields != NULL) { /* Calcul de la taille du tableau */ while(fields[size] != NULL) { ++size; } if ( PROFILE_FLD_NBR != size ) { printf("Nombre de champs incorrect : %d (%d attendu).\n", size, PROFILE_FLD_NBR); return EXIT_FAILURE; } addProfile(fields, &profiles, profilescount); ++profilescount; } }
Car dans la première version, tu tentais de ré-allouer une zone mémoire indéfinie.Code:
1
2
3
4
5
6
7
8
9
10 void addProfile(char *fields[], profile **profiles, int profilescount) { *profiles = (profile*)realloc (*profiles, (profilescount + 1) * sizeof (profile)); if (NULL == profiles) { fprintf (stderr, "Mémoire insuffisante.\n"); free (profiles); exit (EXIT_FAILURE); } /* profile_id */ profiles[profilescount]->profile_id = string2int(fields[1]); }
J'ai corrigé comme indiqué mais cela ne fait pas disparaître le coredump qui se produit lors du :
Code:profiles[profilescount]->profile_id = string2int(fields[1]);
C'est apparemment le realloc qui pose problème. En effet avec :
au début, je n'ai pas de coredump.Code:
1
2
3
4
5 profiles = (profile*) malloc(10*sizeof(profile)); if (NULL == profiles) { printf("Erreur d'allocation.\n"); return EXIT_FAILURE; }