[C] soucis, char*, tableau, pointeur :)
Résolu/Fermé
A voir également:
- [C] soucis, char*, tableau, pointeur :)
- Tableau croisé dynamique - Guide
- Tableau ascii - Guide
- Tableau word - Guide
- Trier tableau excel - Guide
- Comment imprimer un tableau excel sur une seule page - Guide
6 réponses
jaky1212
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
4 mars 2013
8
6 déc. 2009 à 11:41
6 déc. 2009 à 11:41
Bonjour,
Je ne sais pas trop si ça va faire ce que tu veux et peut être que tu y a déjà pensé mais :
Si tu crée une variable temporaire dans la fonction, tu lui passerai son adresse est pas l'adresse etiq ?
char* etiq_temp;
etiq_temp=(char*)calloc(strlen(etiq),sizeof(char));
strcpy(etiq_temp,etiq);
while(fgets(ligne,79,fic) != NULL)
{
if (poly_parsing(ligne,etiq,op,ri,rj,rk,nc))
{
etiquettes[cpt] = etiq_temp ;
printf("nia etiquette : %s \n",etiquettes[cpt]) ;
}
cpt ++ ;
}
/*enlève le free si sa bug à la compilation*/
free(etiq_temp);
je sais pas si ça résoudra ton problème ...
Je ne sais pas trop si ça va faire ce que tu veux et peut être que tu y a déjà pensé mais :
Si tu crée une variable temporaire dans la fonction, tu lui passerai son adresse est pas l'adresse etiq ?
char* etiq_temp;
etiq_temp=(char*)calloc(strlen(etiq),sizeof(char));
strcpy(etiq_temp,etiq);
while(fgets(ligne,79,fic) != NULL)
{
if (poly_parsing(ligne,etiq,op,ri,rj,rk,nc))
{
etiquettes[cpt] = etiq_temp ;
printf("nia etiquette : %s \n",etiquettes[cpt]) ;
}
cpt ++ ;
}
/*enlève le free si sa bug à la compilation*/
free(etiq_temp);
je sais pas si ça résoudra ton problème ...
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
6 déc. 2009 à 14:42
6 déc. 2009 à 14:42
Salut,
etiquettes[cpt] = etiq ;
Comme tu le dis si bien, cela ne copie pas le tableau mais l'adresse du pointeur. Donc cela dépend fortement d'etiq.
Ce qu'il faut faire c'est recopier une à une les valeurs, et pour cela tu as la fonction strncpy à ta disposition.
Par contre, il ne faudra pas oublier de réaliser l'allocation dynamique d'etiquettes[cpt].
Cdlt,
etiquettes[cpt] = etiq ;
Comme tu le dis si bien, cela ne copie pas le tableau mais l'adresse du pointeur. Donc cela dépend fortement d'etiq.
Ce qu'il faut faire c'est recopier une à une les valeurs, et pour cela tu as la fonction strncpy à ta disposition.
Par contre, il ne faudra pas oublier de réaliser l'allocation dynamique d'etiquettes[cpt].
Cdlt,
Merci beaucoup à vous deux =)
j'ai donc changé ma fonction et cela donne :
ça marche parfaitement du coup
par contre je me demandais si c'était possible de m'expliquer plus en détail en terme pointeur/valeur ce que signifient ces deux lignes :
Je me le demande parce que j'ai du mal à comprendre comment elles marchent, n'étant pas encore très douée en C. merci d'avance pour votre réponse et merci encore pour celles que vous m'avez déjà apportée.
j'ai donc changé ma fonction et cela donne :
void gestionEtiquettes(char* etiquettes[],char* op,char* ri, char* rj, char* rk, char* nc, int *tailleProg, char* ligne, char* etiq) { int cpt = 0 ; FILE* fic = fopen("essai.asm","r"); while(fgets(ligne,79,fic) != NULL) { if (poly_parsing(ligne,etiq,op,ri,rj,rk,nc)) { etiquettes[cpt] = (char*)calloc(strlen(etiq),sizeof(char)) ; strcpy(etiquettes[cpt],etiq); } cpt ++ ; } *tailleProg = cpt ; fclose(fic) ; }
ça marche parfaitement du coup
par contre je me demandais si c'était possible de m'expliquer plus en détail en terme pointeur/valeur ce que signifient ces deux lignes :
etiquettes[cpt] = (char*)calloc(strlen(etiq),sizeof(char)) ; strcpy(etiquettes[cpt],etiq);
Je me le demande parce que j'ai du mal à comprendre comment elles marchent, n'étant pas encore très douée en C. merci d'avance pour votre réponse et merci encore pour celles que vous m'avez déjà apportée.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
6 déc. 2009 à 16:02
6 déc. 2009 à 16:02
etiquettes[cpt] = (char*)calloc(strlen(etiq),sizeof(char)) ;
Cela signifie que tu alloues une zone dans le heap et que tu rattaches l'adresse à etiquette[cpt].
Cependant pour plus de performance, tu peux utiliser malloc tout simplement :
etiquettes[cpt]=malloc(strlen(etiq)+1);
Le +1 est important pour stocker le \0, tu l'as d'ailleurs oublier dans le calloc, il faut également le mettre.
De plus, tu n'es pas obligé de caster calloc ou malloc en char*.
strcpy(etiquettes[cpt],etiq);
Cela signifie string copy. En gros tu copies tous les caractères de etiq dans etiquettes[cpt] jusqu'au \0 final.
Le problème est que si la chaîne etiq est plus grande qu'etiquettes[cpt], cela causera un bug à ton programme. Tu n'auras pas ce problème ici puisque tu alloues la bonne taille avec ton allocation. Mais je te recommande de ne plus utiliser strcpy, mais strncpy qui donne une taille maximale à recopier.
De plus, n'oublie pas de toujours vérifier la valeur de retour du malloc (si différent de NULL), cela t'évitera bien des surprises.
Et enfin, qui dit allocation (malloc ou calloc, ou realloc) dit désallocation. Et il faudra donc mettre à un moment un free.
Cdlt,
Cela signifie que tu alloues une zone dans le heap et que tu rattaches l'adresse à etiquette[cpt].
Cependant pour plus de performance, tu peux utiliser malloc tout simplement :
etiquettes[cpt]=malloc(strlen(etiq)+1);
Le +1 est important pour stocker le \0, tu l'as d'ailleurs oublier dans le calloc, il faut également le mettre.
De plus, tu n'es pas obligé de caster calloc ou malloc en char*.
strcpy(etiquettes[cpt],etiq);
Cela signifie string copy. En gros tu copies tous les caractères de etiq dans etiquettes[cpt] jusqu'au \0 final.
Le problème est que si la chaîne etiq est plus grande qu'etiquettes[cpt], cela causera un bug à ton programme. Tu n'auras pas ce problème ici puisque tu alloues la bonne taille avec ton allocation. Mais je te recommande de ne plus utiliser strcpy, mais strncpy qui donne une taille maximale à recopier.
De plus, n'oublie pas de toujours vérifier la valeur de retour du malloc (si différent de NULL), cela t'évitera bien des surprises.
Et enfin, qui dit allocation (malloc ou calloc, ou realloc) dit désallocation. Et il faudra donc mettre à un moment un free.
Cdlt,
Isabelle
>
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
6 déc. 2009 à 16:34
6 déc. 2009 à 16:34
merci pour ces nouvelles précisions :
voici la dernière version de mon code :
Si j'ai bien compris, à chaque tour de boucle j'alloue de la mémoire (se trouvant dans la pile ?) à ma case de tableau, puis je copie ma chaine à cet endroit grâce à la fonction strncpy, puis je désalloue cette mémoire.
Je me demande juste quelle mauvaise surprise peut-on avoir si on ne teste pas si le résultat du malloc est NULL (cela voudrait dire qu'on ne pourrait pas lui allouer de mémoire ?)
merci encore pour ces réponses.
voici la dernière version de mon code :
void gestionEtiquettes(char* etiquettes[],char* op,char* ri, char* rj, char* rk, char* nc, int *tailleProg, char* ligne, char* etiq) { int cpt = 0 ; FILE* fic = fopen("essai.asm","r"); while(fgets(ligne,79,fic) != NULL) { if (poly_parsing(ligne,etiq,op,ri,rj,rk,nc)) { etiquettes[cpt] = malloc(strlen(etiq)+1) ; if (etiquettes[cpt] != NULL) { strncpy(etiquettes[cpt],etiq,strlen(etiq)+1); } free(etiquettes[cpt]) ; } cpt ++ ; } *tailleProg = cpt ; fclose(fic) ; }
Si j'ai bien compris, à chaque tour de boucle j'alloue de la mémoire (se trouvant dans la pile ?) à ma case de tableau, puis je copie ma chaine à cet endroit grâce à la fonction strncpy, puis je désalloue cette mémoire.
Je me demande juste quelle mauvaise surprise peut-on avoir si on ne teste pas si le résultat du malloc est NULL (cela voudrait dire qu'on ne pourrait pas lui allouer de mémoire ?)
merci encore pour ces réponses.
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
>
Isabelle
6 déc. 2009 à 17:32
6 déc. 2009 à 17:32
Je te conseille aussi de rajouter après le strncpy un '\0' à la position strlen(etiq)+1 dans etiquettes[cpt].
free(etiquettes[cpt]) ;
Il ne faut pas le mettre ici le free. Surtout pas ^^. Tu le mettras lorsque tu n'auras plus besoin d'accéder à cette case du tableau ou au pire à la fin du programme.
Si j'ai bien compris, à chaque tour de boucle j'alloue de la mémoire (se trouvant dans la pile ?) à ma case de tableau, puis je copie ma chaine à cet endroit grâce à la fonction strncpy, puis je désalloue cette mémoire.
Non la mémoire que tu alloues ne se trouve pas dans la pile mais le tas. Mais le reste, tu as compris. Par contre la désallocation de la mémoire doit se faire lorsque tu n'en as plus besoin (voir réponse ci-dessus).
Je me demande juste quelle mauvaise surprise peut-on avoir si on ne teste pas si le résultat du malloc est NULL
Si tu fais : etiquettes[cpt] = malloc(strlen(etiq)+1) ; et que malloc échoue alors etiquettes[cpt] vaudra NULL. L'allocation ne sera donc pas faite et donc strncpy provoquera l'écriture dans une zone allouée : segmentation fault.
free(etiquettes[cpt]) ;
Il ne faut pas le mettre ici le free. Surtout pas ^^. Tu le mettras lorsque tu n'auras plus besoin d'accéder à cette case du tableau ou au pire à la fin du programme.
Si j'ai bien compris, à chaque tour de boucle j'alloue de la mémoire (se trouvant dans la pile ?) à ma case de tableau, puis je copie ma chaine à cet endroit grâce à la fonction strncpy, puis je désalloue cette mémoire.
Non la mémoire que tu alloues ne se trouve pas dans la pile mais le tas. Mais le reste, tu as compris. Par contre la désallocation de la mémoire doit se faire lorsque tu n'en as plus besoin (voir réponse ci-dessus).
Je me demande juste quelle mauvaise surprise peut-on avoir si on ne teste pas si le résultat du malloc est NULL
Si tu fais : etiquettes[cpt] = malloc(strlen(etiq)+1) ; et que malloc échoue alors etiquettes[cpt] vaudra NULL. L'allocation ne sera donc pas faite et donc strncpy provoquera l'écriture dans une zone allouée : segmentation fault.
jaky1212
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
4 mars 2013
8
6 déc. 2009 à 17:36
6 déc. 2009 à 17:36
malloc c'est un peut comme le fork sous linux, on test toujours pour voir si la fonction n'échoue pas mais bon la fonction échoue 1 fois sur 10000, tu peux t'en passé si tu veux économiser 3 lignes
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
6 déc. 2009 à 17:47
6 déc. 2009 à 17:47
La fonction échoue 1 fois sur 10000
En cas de fonction normale, c'est vrai qu'elle échoue rarement. Mais l'utilisateur peut toujours s'amuser à provoquer un crash de programme, et si la valeur de retour n'a pas été prévu, il pourra exploiter la vulnérabilité.
En C, la règle est simple. Etant donné qu'il s'agit d'un langage bas niveau, il faut tout vérifier soi-même. Et, il faut pas avoir peur d'écrire des lignes en C. ;-))).
En cas de fonction normale, c'est vrai qu'elle échoue rarement. Mais l'utilisateur peut toujours s'amuser à provoquer un crash de programme, et si la valeur de retour n'a pas été prévu, il pourra exploiter la vulnérabilité.
En C, la règle est simple. Etant donné qu'il s'agit d'un langage bas niveau, il faut tout vérifier soi-même. Et, il faut pas avoir peur d'écrire des lignes en C. ;-))).
Isabelle
>
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
6 déc. 2009 à 20:27
6 déc. 2009 à 20:27
merci encore, donc voici une nouvelle modification de mon programme :
j'ai ajouté une autre fonction que j'appelle à la fin de mon programme :
je l'appelle comme ceci :
Je pense avoir mieux compris comment tout ça marchait
juste une dernière chose : je ne vois pas comment rajouter le '/0' (je sais que c'est assez stupide, mais je ne me le représente pas bien)
merci encore pour vos réponses et conseils
void gestionEtiquettes(char* etiquettes[],char* op,char* ri, char* rj, char* rk, char* nc, int *tailleProg, char* ligne, char* etiq) { int cpt = 0 ; FILE* fic = fopen("essai.asm","r"); while(fgets(ligne,79,fic) != NULL) { if (poly_parsing(ligne,etiq,op,ri,rj,rk,nc)) { etiquettes[cpt] = malloc(strlen(etiq)+1) ; if (etiquettes[cpt] != NULL) { strncpy(etiquettes[cpt],etiq,strlen(etiq)+1); } } cpt ++ ; } *tailleProg = cpt ; fclose(fic) ; }
j'ai ajouté une autre fonction que j'appelle à la fin de mon programme :
void desalloue_tableau(char* etiquettes[], int *tailleProg) { for (int i = 0 ; i < *tailleProg ; i++) { free(etiquettes[i]) ; } }
je l'appelle comme ceci :
desalloue_tableau(etiquettes, &tailleProg) ;
Je pense avoir mieux compris comment tout ça marchait
juste une dernière chose : je ne vois pas comment rajouter le '/0' (je sais que c'est assez stupide, mais je ne me le représente pas bien)
merci encore pour vos réponses et conseils
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
>
Isabelle
6 déc. 2009 à 20:35
6 déc. 2009 à 20:35
desalloue_tableau(etiquettes, &tailleProg) ;
Oui, mais pourquoi passer par un pointeur si tu n'as pas besoin de changer la valeur ?
juste une dernière chose : je ne vois pas comment rajouter le '/0'
strncpy(etiquettes[cpt],etiq,strlen(etiq)+1);
Tu rajoutes juste après : etiquettes[cpt][strlen(etiq)]='\0';
Et un dernier truc, tu fais très bien if (etiquettes[cpt]!=NULL), mais faut aussi agir lorsque malloc retourne NULL, par exemple un simple exit(EXIT_FAILURE) avec juste un avant un message d'erreur.
Sinon tout le reste est bien. Bravo ;-)))
Oui, mais pourquoi passer par un pointeur si tu n'as pas besoin de changer la valeur ?
juste une dernière chose : je ne vois pas comment rajouter le '/0'
strncpy(etiquettes[cpt],etiq,strlen(etiq)+1);
Tu rajoutes juste après : etiquettes[cpt][strlen(etiq)]='\0';
Et un dernier truc, tu fais très bien if (etiquettes[cpt]!=NULL), mais faut aussi agir lorsque malloc retourne NULL, par exemple un simple exit(EXIT_FAILURE) avec juste un avant un message d'erreur.
Sinon tout le reste est bien. Bravo ;-)))
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
jaky1212
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
4 mars 2013
8
6 déc. 2009 à 17:49
6 déc. 2009 à 17:49
entièrement d'accord
jaky1212
Messages postés
126
Date d'inscription
mardi 25 août 2009
Statut
Membre
Dernière intervention
4 mars 2013
8
6 déc. 2009 à 20:30
6 déc. 2009 à 20:30
le fonction strcat peut t'aider à faire sa:
char* ma_chaine="toto"
strcat(ma_chaine,"titi");
et la ma_chaine = tototiti
fais pareil avec '\0'
a++
char* ma_chaine="toto"
strcat(ma_chaine,"titi");
et la ma_chaine = tototiti
fais pareil avec '\0'
a++
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
6 déc. 2009 à 20:37
6 déc. 2009 à 20:37
fais pareil avec '\0'
Non pas besoin de rajouter explicitement le '\0' avec strcat. Il s'ajoute automatiquement dans tous les cas.
Par contre, il vaut mieux utiliser strncat que strcat. Même raison que pour strncpy.
Cdlt
Non pas besoin de rajouter explicitement le '\0' avec strcat. Il s'ajoute automatiquement dans tous les cas.
Par contre, il vaut mieux utiliser strncat que strcat. Même raison que pour strncpy.
Cdlt
Isabelle
>
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
6 déc. 2009 à 21:15
6 déc. 2009 à 21:15
J'ai fais les dernières modifications que tu m'as suggérée.
Merci encore et bonne continuation
problème totalement résolu =)
Merci encore et bonne continuation
problème totalement résolu =)