Programme en C
Résolu/Fermé
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
-
28 nov. 2009 à 13:55
jamsss Messages postés 36 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 19 septembre 2011 - 12 déc. 2009 à 11:50
jamsss Messages postés 36 Date d'inscription dimanche 6 septembre 2009 Statut Membre Dernière intervention 19 septembre 2011 - 12 déc. 2009 à 11:50
A voir également:
- Programme en C
- Programme demarrage windows 10 - Guide
- Désinstaller programme windows 10 - Guide
- Mettre en veille un programme - Guide
- Cette action ne peut pas être réalisée car le fichier est ouvert dans un autre programme - Guide
- Forcer la fermeture d'un programme - Guide
11 réponses
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
29 nov. 2009 à 18:08
29 nov. 2009 à 18:08
Problème d'allocation de double pointeur... quel gland je fais ;-p
Giorgiolino
Messages postés
253
Date d'inscription
vendredi 15 mai 2009
Statut
Contributeur
Dernière intervention
2 mars 2015
52
30 nov. 2009 à 09:41
30 nov. 2009 à 09:41
Bonjour,
pour faire encore moins gland, un petit "résolu" peut être utile aussi.
Cordialement.
pour faire encore moins gland, un petit "résolu" peut être utile aussi.
Cordialement.
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
1 déc. 2009 à 18:05
1 déc. 2009 à 18:05
Sauf que je n'ai pas mis résolu parce que le problème ne l'est pas... J'ai mis ceci
for(findico=0;!feof(fichierdico);findico++)
{
dico[findico]=malloc(LONGMOT*sizeof(char*));
fscanf(fichierdico,"%s",dico[findico]);
}
pour allouer mon pointeur de tableau de char mais gdb me dit ça :
(gdb) run texte.txt
Starting program: /home/christophe/Test_C/D8.2 texte.txt
Program received signal SIGSEGV, Segmentation fault.
0x000000000040095e in main (argc=2, argv=0x7fff3a234db8) at D8.2.c:51
51 dico[findico]=malloc(LONGMOT*sizeof(char*));
Missing debug package(s), you should install: glibc-debug-2.9-0.20081113.5mnb2.x86_64
(gdb) bt full
#0 0x000000000040095e in main (argc=2, argv=0x7fff3a234db8) at D8.2.c:51
fichiertexte = (FILE *) 0x7c80c0
fichierdico = (FILE *) 0x7c8300
i = 0
findico = 0
reponse = ""
dico = (char **) 0x4007c0
mot_texte = 0x7c8010 ""
(gdb)
Merci d'avance
for(findico=0;!feof(fichierdico);findico++)
{
dico[findico]=malloc(LONGMOT*sizeof(char*));
fscanf(fichierdico,"%s",dico[findico]);
}
pour allouer mon pointeur de tableau de char mais gdb me dit ça :
(gdb) run texte.txt
Starting program: /home/christophe/Test_C/D8.2 texte.txt
Program received signal SIGSEGV, Segmentation fault.
0x000000000040095e in main (argc=2, argv=0x7fff3a234db8) at D8.2.c:51
51 dico[findico]=malloc(LONGMOT*sizeof(char*));
Missing debug package(s), you should install: glibc-debug-2.9-0.20081113.5mnb2.x86_64
(gdb) bt full
#0 0x000000000040095e in main (argc=2, argv=0x7fff3a234db8) at D8.2.c:51
fichiertexte = (FILE *) 0x7c80c0
fichierdico = (FILE *) 0x7c8300
i = 0
findico = 0
reponse = ""
dico = (char **) 0x4007c0
mot_texte = 0x7c8010 ""
(gdb)
Merci d'avance
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
1 déc. 2009 à 19:18
1 déc. 2009 à 19:18
Salut,
J'ai pas tout lu, mais je vois des erreurs.
Notamment, l'erreur d'allocation sur le double pointeur.
Tu alloues le double pointeur dico. Ce qui t'assure que dico pointera bien vers une zone du heap. Mais, l'allocation de dico[i] n'est pas fait. Il faut donc réaliser l'allocation sur dico[i] avec une simple boucle for.
De plus, char reponse[1] ne sert à rien. Autant mettre : char reponse et utiliser getchar(); pour récupérer un caractère. Soit si tu veux impérativement passer par scanf %s et un tableau de char, tu devras utiliser char reponse[2]; le second caractère étant le '\0'. Mais tu devras bien penser à vider le buffer clavier après pour éliminer le '\n'. Par ailleurs attention au cas où l'utilisateur entre une chaîne bien plus grande qu'un simple caractère. Cela te provoquerait bien des surprises dans ton programme.
De plus, en C, tu dois toujours vérifier que l'allocation s'est bien déroulée en testant la valeur de retour, de même pour les fopen etc.
Cdlt
J'ai pas tout lu, mais je vois des erreurs.
Notamment, l'erreur d'allocation sur le double pointeur.
Tu alloues le double pointeur dico. Ce qui t'assure que dico pointera bien vers une zone du heap. Mais, l'allocation de dico[i] n'est pas fait. Il faut donc réaliser l'allocation sur dico[i] avec une simple boucle for.
De plus, char reponse[1] ne sert à rien. Autant mettre : char reponse et utiliser getchar(); pour récupérer un caractère. Soit si tu veux impérativement passer par scanf %s et un tableau de char, tu devras utiliser char reponse[2]; le second caractère étant le '\0'. Mais tu devras bien penser à vider le buffer clavier après pour éliminer le '\n'. Par ailleurs attention au cas où l'utilisateur entre une chaîne bien plus grande qu'un simple caractère. Cela te provoquerait bien des surprises dans ton programme.
De plus, en C, tu dois toujours vérifier que l'allocation s'est bien déroulée en testant la valeur de retour, de même pour les fopen etc.
Cdlt
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
2 déc. 2009 à 17:35
2 déc. 2009 à 17:35
Salut,
pour l'allocation du double pointeur c'est ce que j'ai dit plus haut j'ai remplacé le:
dico=malloc(MAXMOTS*LONGMOT*sizeof(char **));
par
for(findico=0;!feof(fichierdico);findico++)
{
dico[findico]=malloc(LONGMOT*sizeof(char*));
fscanf(fichierdico,"%s",dico[findico]);
}
mais j'ai toujours cette erreur de segmentation
Pour le réponse[1] ça fonctionne très bien (testé sur un autre programme), on ne peut pas rentrer d'autres valeurs que 'o' ou 'n' grace à :
while((reponse[0]!='o') && (reponse[0]!='n'))
{
printf("Réponse invalide, recommencez\n");
scanf("%s",reponse);
purger();
}
;)
pour l'allocation du double pointeur c'est ce que j'ai dit plus haut j'ai remplacé le:
dico=malloc(MAXMOTS*LONGMOT*sizeof(char **));
par
for(findico=0;!feof(fichierdico);findico++)
{
dico[findico]=malloc(LONGMOT*sizeof(char*));
fscanf(fichierdico,"%s",dico[findico]);
}
mais j'ai toujours cette erreur de segmentation
Pour le réponse[1] ça fonctionne très bien (testé sur un autre programme), on ne peut pas rentrer d'autres valeurs que 'o' ou 'n' grace à :
while((reponse[0]!='o') && (reponse[0]!='n'))
{
printf("Réponse invalide, recommencez\n");
scanf("%s",reponse);
purger();
}
;)
fiddy
Messages postés
11069
Date d'inscription
samedi 5 mai 2007
Statut
Contributeur
Dernière intervention
23 avril 2022
1 844
2 déc. 2009 à 22:06
2 déc. 2009 à 22:06
dico=malloc(MAXMOTS*LONGMOT*sizeof(char **));
Il faut faire sizeof(char*);
dico[findico]=malloc(LONGMOT*sizeof(char*));
il faut mettre sizeof(char).
Pour le réponse[1] ça fonctionne très bien (testé sur un autre programme), on ne peut pas rentrer d'autres valeurs que 'o' ou 'n' grace à :
Il est possible que ça marche. Mais il n'empêche que c'est faux. Tu utilises %s dans ton scanf, il va donc mettre un \0 à la fin. Et donc il y aura un débordement d'un byte. Il suffit qu'il y ait une variable juste à côté dans la pile et tu changeras un byte au passage, ce qui est très gênant.
Il faut faire sizeof(char*);
dico[findico]=malloc(LONGMOT*sizeof(char*));
il faut mettre sizeof(char).
Pour le réponse[1] ça fonctionne très bien (testé sur un autre programme), on ne peut pas rentrer d'autres valeurs que 'o' ou 'n' grace à :
Il est possible que ça marche. Mais il n'empêche que c'est faux. Tu utilises %s dans ton scanf, il va donc mettre un \0 à la fin. Et donc il y aura un débordement d'un byte. Il suffit qu'il y ait une variable juste à côté dans la pile et tu changeras un byte au passage, ce qui est très gênant.
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
2 déc. 2009 à 18:41
2 déc. 2009 à 18:41
Je remet le code à jour avec les corrections citées précédement:
Et toujours cette erreur de segmentation détectée par gdb à cette ligne:
dico[findico]=malloc(LONGMOT*sizeof(char*));
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> short dichotomie(char **dico,char *mot_texte,int nbmots); void ajout(char **dico, char *mot_texte, int findico); char *sup_ponc(char *mot_texte); char *sup_maj(char *mot_texte); int compare_mots(const void *a, const void *b); void purger(); #define MAXMOTS 100 #define LONGMOT 20 int main(int argc,char *argv[]) { /*Déclarations des fichiers*/ FILE *fichiertexte; FILE *fichierdico; /*Déclarations des variables*/ int i,findico; char reponse[1]; /*Déclarations des pointeurs*/ char **dico; char *mot_texte; /*Allocation du pointeur *mot_texte*/ mot_texte=malloc(LONGMOT*sizeof(char*)); if (mot_texte==NULL) { fprintf(stderr,"Allocation impossible \n"); exit(EXIT_FAILURE); } /*Vérification du nombre d'arguments corrects à l'appel*/ if (argc!=2) { printf("Erreur dans le nombre d'arguments\n"); exit(EXIT_FAILURE); } /*Ouverture des fichiers en lecture*/ fichiertexte=fopen(argv[1],"r"); if (fichiertexte==NULL) { printf("Impossible d'ouvrir %s.\n", argv[1]); exit(EXIT_FAILURE); } fichierdico=fopen("dico.dat","r"); /*Lecture du fichier dico et stockage en mémoire dans le tabeau dico*/ for(findico=0;!feof(fichierdico);findico++) { dico[findico]=malloc(LONGMOT*sizeof(char*)); fscanf(fichierdico,"%s",dico[findico]); if (dico[findico]==NULL) { fprintf(stderr,"Allocation impossible \n"); exit(EXIT_FAILURE); } } /*Fermeture du fichier dico.dat*/ fclose(fichierdico); /*Tri du tableau dico*/ qsort((char**)dico,MAXMOTS,LONGMOT,compare_mots); /*Lecture et traitement du fichier texte*/ while(!feof(fichiertexte)) { fscanf(fichiertexte,"%s",mot_texte); mot_texte=sup_ponc(mot_texte); mot_texte=sup_maj(mot_texte); if (dichotomie(dico,mot_texte,findico-1)==0) { printf("Le mot '%s' n'est pas dans le dictionnaire, voulez vous le rajouter (o/n) ?\n", mot_texte); scanf("%s",reponse); while((reponse[0]!='o') && (reponse[0]!='n')) { printf("Réponse invalide, recommencez\n"); scanf("%s",reponse); purger(); } if(reponse[0]=='o') ajout(dico,mot_texte,findico); } } /*Fermeture du fichier texte*/ fclose(fichiertexte); /*Ouverture du fichier dico, écriture des éléments du tableau et fermeture*/ fichierdico=fopen("dico.dat","w"); for(i=0;i<=findico;i++) fprintf(fichierdico,"%s",dico[i]); fclose(fichierdico); /*Libération des pointeurs en mémoire*/ free(mot_texte); free(dico); return 0; } char *sup_ponc(char *mot) { int lettre, lettresuiv; for(lettre=0,lettresuiv=0;mot[lettresuiv];lettresuiv++) { mot[lettre]=mot[lettresuiv]; /* Si le caractère est une ponctuation, on l'ignore*/ if (ispunct(mot[lettresuiv])!=1) lettre++; } /*Pour terminer la chaîne:*/ mot[lettre]='\0'; return mot; } char *sup_maj(char *mot) { int lettre; for (lettre=0;mot[lettre];lettre++) { if (isupper(mot[lettre])) mot[lettre]=tolower(mot[lettre]); } return mot; } short dichotomie(char **dico,char *mot,int nbmots) { int i,j,k,x; i=0; j=nbmots; /*Allocation du pointeur **dico*/ for(x=0;x<=(nbmots+1);x++) { dico[x]=malloc(LONGMOT*sizeof(char)); if (dico[x]==NULL) { fprintf(stderr,"Allocation impossible \n"); exit(EXIT_FAILURE); } } while ((j-i)>1) { k=i+((j-i)/2); if (((j-i)%2)==0) k++; if (strcmp(mot,dico[k-1])==0) return 1; if (strcmp(mot,dico[k-1])<0) j=(k-1); else i=(k-1); } if ((strcmp(dico[i],mot)==0) || (strcmp(dico[j],mot)==0)) return 1; else return 0; } void ajout(char **dico,char *mot_texte,int findico) { /*Si le le nombre de mots est supérieur à MAXMOTS, on affiche une erreur sinon on ajoute le mot a la fin du tableau*/ if(findico!=MAXMOTS) { dico[findico+1]=mot_texte; findico++; } else { printf("Vous avez dépassé le nombre de mots maximal du dictionnaire"); exit(EXIT_FAILURE); } /*On retri le tableau*/ qsort((char**)dico, MAXMOTS,LONGMOT,compare_mots); } int compare_mots(const void *chaine1, const void *chaine2) { return strcmp(chaine1,chaine2); } void purger(void) { int c; while ((c=getchar()) != '\n' && c != EOF) {} }
Et toujours cette erreur de segmentation détectée par gdb à cette ligne:
dico[findico]=malloc(LONGMOT*sizeof(char*));
heyquem
Messages postés
759
Date d'inscription
mercredi 17 juin 2009
Statut
Membre
Dernière intervention
29 décembre 2013
131
2 déc. 2009 à 23:01
2 déc. 2009 à 23:01
Cas typique d'un beau travail dans le principe qui est gaché dans sa concrétisation par l'obligation de se coltiner des préoccupations de niveau hardware dont le niveau de détail m'effraie:
Tout sujet portant sur une langue me semble pourtant relever d'un langage de plus haut niveau, pour pouvoir se concentrer sur les vraies questions intéressantes. Pourquoi avoir choisi de faire ce code en langage C ?? Je vois mal que la vitesse d'exécution soit un impératif.
Félicitations quand même , jamsss
Tu utilises %s dans ton scanf, il va donc mettre un \0 à la fin. Et donc il y aura un débordement d'un byte. Il suffit qu'il y ait une variable juste à côté dans la pile et tu changeras un byte au passage, ce qui est très gênant.
Tout sujet portant sur une langue me semble pourtant relever d'un langage de plus haut niveau, pour pouvoir se concentrer sur les vraies questions intéressantes. Pourquoi avoir choisi de faire ce code en langage C ?? Je vois mal que la vitesse d'exécution soit un impératif.
Félicitations quand même , jamsss
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
2 déc. 2009 à 23:08
2 déc. 2009 à 23:08
Bonjour,
pour répondre à ta question heyquem la raison pour laquelle j'ai écrit ce code en C est que c'est un devoir dans le cadre de de ma formation tout simplement je n'ai pas le choix du langage
;)
pour répondre à ta question heyquem la raison pour laquelle j'ai écrit ce code en C est que c'est un devoir dans le cadre de de ma formation tout simplement je n'ai pas le choix du langage
;)
heyquem
Messages postés
759
Date d'inscription
mercredi 17 juin 2009
Statut
Membre
Dernière intervention
29 décembre 2013
131
2 déc. 2009 à 23:22
2 déc. 2009 à 23:22
Merci pour la réponse.
Un tel programme me semble demander un certain niveau de connaissance, et donc demandé par un prof qui doit quand même être bien expérimenté en informatique. J'espère donc que ce devoir n'est imposé en C que pour fournir un sujet sur lequel s'exercer en C. Il faut bien faire des programmes sur quelque chose. Le but étant le C, pas la correction orthographique.
Un tel programme me semble demander un certain niveau de connaissance, et donc demandé par un prof qui doit quand même être bien expérimenté en informatique. J'espère donc que ce devoir n'est imposé en C que pour fournir un sujet sur lequel s'exercer en C. Il faut bien faire des programmes sur quelque chose. Le but étant le C, pas la correction orthographique.
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
11 déc. 2009 à 18:56
11 déc. 2009 à 18:56
Bonjour,
Suite à vos remarques j'ai pu régler (je pense) les erreurs de segmentation par contre maintenant j'ai un autre soucis c'est que mon tableau dico[] ne contient pas vraiment les mots du texte mais après un test avec un printf il contient plutôt des choses de ce style : 0+��j ou P+��j ... Inutile de vous dire que pour la comparaison avec les mots du texte c'est pas génial... Voici le code:
Merci de votre aide
Suite à vos remarques j'ai pu régler (je pense) les erreurs de segmentation par contre maintenant j'ai un autre soucis c'est que mon tableau dico[] ne contient pas vraiment les mots du texte mais après un test avec un printf il contient plutôt des choses de ce style : 0+��j ou P+��j ... Inutile de vous dire que pour la comparaison avec les mots du texte c'est pas génial... Voici le code:
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> short dichotomie(char **dico,char *mot_texte,short nbmots); void ajout(char **dico, char *mot_texte, int findico); char *sup_ponc(char *mot_texte); char *sup_maj(char *mot_texte); int compare_mots(const void *a, const void *b); void purger(); #define MAXMOTS 100 #define LONGMOT 20 int main(int argc,char *argv[]) { /*Déclarations des fichiers*/ FILE *fichiertexte; FILE *fichierdico; /*Déclarations des variables*/ int i,findico; char reponse; /*Déclarations des pointeurs*/ char **dico; char *mot_texte; /*Allocation des pointeurs */ mot_texte=malloc(MAXMOTS*sizeof(char *)); dico=malloc(MAXMOTS*LONGMOT*sizeof(char *)); if (mot_texte==NULL) { fprintf(stderr,"Allocation impossible \n"); exit(EXIT_FAILURE); } /*Vérification du nombre d'arguments corrects à l'appel*/ if (argc!=2) { printf("Erreur dans le nombre d'arguments\n"); exit(EXIT_FAILURE); } /*Ouverture des fichiers en lecture*/ fichiertexte=fopen(argv[1],"r"); if (fichiertexte==NULL) { printf("Impossible d'ouvrir %s.\n", argv[1]); exit(EXIT_FAILURE); } fichierdico=fopen("dico.dat","r"); /*Lecture du fichier dico et stockage en mémoire dans le tabeau dico*/ for(findico=0;!feof(fichierdico);findico++) { dico[findico]=malloc(LONGMOT*sizeof(char)); if (dico[findico]==NULL) { fprintf(stderr,"Allocation impossible \n"); exit(EXIT_FAILURE); } else fscanf(fichierdico,"%s",dico[findico]); printf("%s\n",dico[findico]); } /*Fermeture du fichier dico.dat*/ fclose(fichierdico); /*Tri du tableau dico*/ qsort((char**)dico,MAXMOTS,LONGMOT,compare_mots); /*Lecture et traitement du fichier texte*/ while(!feof(fichiertexte)) { fscanf(fichiertexte,"%s",mot_texte); mot_texte=sup_ponc(mot_texte); mot_texte=sup_maj(mot_texte); if (dichotomie(dico,mot_texte,findico-1)!=1) { printf("Le mot '%s' n'est pas dans le dictionnaire, voulez vous le rajouter (o/n) ?\n", mot_texte); reponse=getchar(); purger(); while((reponse!='o') && (reponse!='n')) { printf("Réponse invalide, recommencez\n"); reponse=getchar(); purger(); } if(reponse=='o') ajout(dico,mot_texte,findico); } } /*Fermeture du fichier texte*/ fclose(fichiertexte); /*Ouverture du fichier dico, écriture des éléments du tableau et fermeture*/ fichierdico=fopen("dico.dat","w"); for(i=0;i<=findico;i++) fprintf(fichierdico,"%s",dico[i]); fclose(fichierdico); /*Libération des pointeurs en mémoire*/ free(mot_texte); for (i=0;i<findico;i++) free(dico[i]); return 0; } char *sup_ponc(char *mot) { int lettre, lettresuiv; for(lettre=0;mot[lettresuiv];lettre++) { lettresuiv=lettre+1; /* Si le caractère est une ponctuation, on l'ignore*/ if (ispunct(mot[lettre])!=0) strcpy(&mot[lettre],&mot[lettresuiv]); } /*Pour terminer la chaîne:*/ mot[lettre]='\0'; return mot; } char *sup_maj(char *mot) { int lettre; for (lettre=0;mot[lettre];lettre++) { if (isupper(mot[lettre])) mot[lettre]=tolower(mot[lettre]); } return mot; } short dichotomie(char **dico,char *mot,short nbmots) { int i,j,k,x; j=nbmots; i=0; /*Allocation du pointeur **dico*/ for(x=0;x<=nbmots;x++) { dico[x]=malloc(LONGMOT*sizeof(char)); if (dico[x]==NULL) { fprintf(stderr,"Allocation impossible \n"); exit(EXIT_FAILURE); } } while ((j-i)>1) { k=i+((j-i)/2); if (((j-i)%2)==0) k++; if (strcmp(mot,dico[k-1])==0) return 1; if (strcmp(mot,dico[k-1])<0) j=(k-1); else i=(k-1); } printf("%s\n",dico[i]); printf("%s\n",mot); if ((strcmp(dico[i],mot)==0) || (strcmp(dico[j],mot)==0)) return 1; else return 0; } void ajout(char **dico,char *mot_texte,int findico) { /*Si le le nombre de mots est supérieur à MAXMOTS, on affiche une erreur sinon on ajoute le mot a la fin du tableau*/ if(findico!=MAXMOTS) { dico[findico+1]=mot_texte; findico++; } else { printf("Vous avez dépassé le nombre de mots maximal du dictionnaire"); exit(EXIT_FAILURE); } /*On retri le tableau*/ qsort((char**)dico, MAXMOTS,LONGMOT,compare_mots); } int compare_mots(const void *chaine1, const void *chaine2) { return strcmp(chaine1,chaine2); } void purger(void) { int c; while ((c=getchar()) != '\n' && c != EOF) {} }
Merci de votre aide
jamsss
Messages postés
36
Date d'inscription
dimanche 6 septembre 2009
Statut
Membre
Dernière intervention
19 septembre 2011
12 déc. 2009 à 11:50
12 déc. 2009 à 11:50
Le remplissage du tableau dico semble bon, le problème viendrai plutôt du qsort, quelqu'un à une idée ?