[C] Problème de lecture dans un fichier en C : fscanf

Problème de lecture dans un fichier en C : fscanf [C] - C - Programmation

Marsh Posté le 24-11-2008 à 23:09:40    

Bonjour tout le monde,
 
J'ai un problème avec la lecture dans un fichier en C. J'ai un fichier qui contient les lignes suivantes :
 

Code :
  1. e1 1 0 e2 R
  2. e2 1 1 e2 R
  3. e2 0 0 e3 R
  4. e3 1 1 e3 R
  5. e3 0 1 e4 L
  6. e4 1 1 e4 L
  7. e4 0 0 e5 L
  8. e5 1 1 e5 L
  9. e5 0 1 e1 R#


 
J'ai déclaré une structure :

Code :
  1. typedef struct t_transition{     //  Pour la première ligne du fichier on  a :
  2. char* etat_courant;             //  "e1"
  3. char symb_lu;                  //  "1"
  4. char symb_ecrit;              //   "0"
  5. char* nouvel_etat;           //   "e2"
  6. char direction;             //  "R"
  7. }t_transition;


 
Dans mon code je fais un

Code :
  1. fscanf(fichier,"%s %c %c %s %c",transition.etat_courant,&(transition.symb_lu),&(transition.symb_ecrit),transition.nouvel_etat,&(transition.direction));


 
J'ai eu un segmentation fault. En déboggant avec gdb, il m'indique un problème dans le fscanf :

Code :
  1. 0xb7e201b3 in _IO_vfscanf () from /lib/tls/i686/cmov/libc.so.6


 
J'ai essayé d'ajouter progressivement, les valeurs et leurs formats. Tout marche correctement jusqu'au moment où je rajoute le "transition.nouvel_etat" qui crée le segmentation fault. Autrement dit si je fais :

Code :
  1. fscanf(fichier,"%s %c %c",transition.etat_courant,&(transition.symb_lu),&(transition.symb_ecrit));


ca marche nikel. Mais, dès que je rajoute "transition.nouvel_etat", il plante.
 
J'ai essayé de faire un fgets suivi d'un sscanf et j'ai le même problème. J'ai même essayé de lire le "transition.nouvel_etat" sur la ligne suivante en faisant :

Code :
  1. fscanf(fichier,"%s %c %c",transition.etat_courant,&(transition.symb_lu),&(transition.symb_ecrit));
  2. fscanf(fichier,"%s",transition.nouvel_etat);


Et gdb m'indique qu'il plante dès que j'arrive à cette ligne. Ca fait plus de 3h que j'écume les forums et les tutos sur la fonctions fscanf et je n'ai encore rien trouvé (je suis peut-être fatigué, lol).
 
En espérant que vous pourrez m'éclairer.
 
AR


Message édité par AigleRoyal le 24-11-2008 à 23:22:34
Reply

Marsh Posté le 24-11-2008 à 23:09:40   

Reply

Marsh Posté le 25-11-2008 à 02:23:34    

Salut
Comment est-ce que tu déclares et initialises transition?


---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 25-11-2008 à 08:48:57    

ptitchep a écrit :

Salut
Comment est-ce que tu déclares et initialises transition?


 
Bon, en fait je ne l'initialise pas. Je le déclare plutot simplement :

Code :
  1. t_transition transition;


Reply

Marsh Posté le 25-11-2008 à 09:22:09    

et comme tu ne controles pas le retour de fscanf ni rien, comment t'es sur qu'il y a pas de la bouillie dans ta transition ?

Reply

Marsh Posté le 25-11-2008 à 11:16:12    

Taz a écrit :

et comme tu ne controles pas le retour de fscanf ni rien, comment t'es sur qu'il y a pas de la bouillie dans ta transition ?


 
Euuuuuh... Je devrais peut-être l'initialiser ? Je n'ai aucune certitude sur le contenu de ma transition et je ne savais pas qu'il fallait controler le retour de mon fscanf !!!! :D

Reply

Marsh Posté le 25-11-2008 à 11:20:03    

le mieux serait de faire un fgets + sscanf

Reply

Marsh Posté le 25-11-2008 à 11:35:09    

Taz a écrit :

le mieux serait de faire un fgets + sscanf


 
Ca marche pas non plus. Maintenant, plus rien ne marche. Ni le fscanf, ni le fgets + sscanf. J'ai même essayé d'initialiser ma "transition" et j'ai toujours l'erreur de segmentation.
 
AR

Reply

Marsh Posté le 25-11-2008 à 11:38:20    

Peux-tu poster la partie significative de ton code correspondant à ton problème ?
Ça nous aiderait à situer le souci.

Reply

Marsh Posté le 25-11-2008 à 11:46:01    

tes char* ils sont pas alloués. utilise des tableaux ou bien fais des malloc

Reply

Marsh Posté le 25-11-2008 à 11:47:30    

Ah oui, tout bêtement.

Reply

Marsh Posté le 25-11-2008 à 11:47:30   

Reply

Marsh Posté le 25-11-2008 à 11:48:29    

AigleRoyal a écrit :

 

Bon, en fait je ne l'initialise pas. Je le déclare plutot simplement :

Code :
  1. t_transition transition;



 

Si tu n'initialises pas tes char* ils pointent sur n'importe quoi, d'où l'erreur de segmentation je pense.

 

edit: grillé

Message cité 1 fois
Message édité par ptitchep le 25-11-2008 à 11:49:15

---------------
deluser --remove-home ptitchep
Reply

Marsh Posté le 25-11-2008 à 13:14:48    

ptitchep a écrit :


 
Si tu n'initialises pas tes char* ils pointent sur n'importe quoi, d'où l'erreur de segmentation je pense.
 
edit: grillé


 
Je ne voulais pas en arriver à poster tout le code, surtout que quand je fais un copier/coller, il n'est pas bien indenté sur le forum. Le voila :
 

Code :
  1. typedef char t_symboles;
  2. typedef struct t_transition{   
  3.    char* etat_courant;           
  4.    t_symboles symb_lu;                 
  5.    t_symboles symb_ecrit;             
  6.    char* nouvel_etat;         
  7.    char direction;           
  8. }t_transition;
  9. /////////////////////////////////// FONCTION RECHERCHER_TRANSITIONS //////////////////////////////
  10. /*   
  11. * Recherche les transitions dans le fichier 'MACHINE'
  12. * Préconditions : Le fichier existe
  13. * Postconditions :  
  14. */
  15. ////////////////////////////////////////////////////////////////////////////////////////////////
  16. void rechercher_transitions(FILE* fichier){
  17.     int i=0;
  18.     int j=0;   
  19.     t_symboles* chaine_avec_espaces = NULL;
  20.     t_transition transition;
  21.     /* Initialisatin de la structure transition */
  22.     transition.etat_courant=NULL;
  23.     transition.symb_lu='-';
  24.     transition.symb_ecrit='-';
  25.     transition.nouvel_etat=NULL;
  26.     transition.direction='-';
  27.  
  28.    /* Parcours du fichier ligne par ligne. */
  29.    while (!feof(fichier)){
  30. /*fscanf(fichier,"%s %c %c %s %c",transition.etat_courant,&(transition.symb_lu),&(transition.symb_ecrit),transition.nouvel_etat,&(transition.direction));*/
  31.   chaine_avec_espaces = rechercher_ligne_dans_fichier(fichier);
  32.   sscanf(chaine_avec_espaces,"%s %c %c",transition.etat_courant,&(transition.symb_lu),&(transition.symb_ecrit));
  33.            printf("etat courant :%s\t",transition.etat_courant);
  34.            printf("symbole lu :%c\t",transition.symb_lu);
  35.            printf("symbole ecrit : %c\t",transition.symb_ecrit);
  36.            printf("nouvel etat : %s\t",transition.nouvel_etat);
  37.            printf("direction : %c\n",transition.direction);
  38.     }// Fin du while
  39. }// Fin de la fonction rechercher_transitions


 
J'ai initialisé ma structure "transition" et rien n'y fait. Je continue d'avoir l'erreur de segmentation.


Message édité par AigleRoyal le 25-11-2008 à 13:47:59
Reply

Marsh Posté le 25-11-2008 à 13:16:12    

Non mais tes pointeurs char* sont placés à NULL. Donc quand tu fais ton assignation, ça essaie de mettre des données dans NULL. Et donc, ça segfault.

Reply

Marsh Posté le 25-11-2008 à 13:19:44    

Elmoricq a écrit :

Non mais tes pointeurs char* sont placés à NULL. Donc quand tu fais ton assignation, ça essaie de mettre des données dans NULL. Et donc, ça segfault.


 
C'est pour les initialiser que j'ai fait ça. Sinon, je n'initialisais pas avant et j'avais le même résultat :)  
 
AR


Message édité par AigleRoyal le 25-11-2008 à 13:23:25
Reply

Marsh Posté le 25-11-2008 à 13:24:06    

Oui, tu initialises à NULL. Donc au moins, ça plante à chaque fois de façon fiable, plutôt que de ne planter qu'aléatoirement. :o
 
Bref :  

Taz a écrit :

tes char* ils sont pas alloués. utilise des tableaux ou bien fais des malloc


Reply

Marsh Posté le 25-11-2008 à 13:32:06    

Elmoricq a écrit :

Oui, tu initialises à NULL. Donc au moins, ça plante à chaque fois de façon fiable, plutôt que de ne planter qu'aléatoirement. :o
 
Bref : tes char* ils sont pas alloués. utilise des tableaux ou bien fais des malloc


 
J'y ai pensé mais le problème c'est que je ne connais pas à l'avance la taille que feront les chaines de caractères. Je voudrais pouvoir traiter les deux fichiers suivants de la même manière :
 

Code :
  1. e1 1 0 e2 R
  2. e2 1 1 e2 R
  3. e2 0 0 e3 R
  4. e3 1 1 e3 R
  5. e3 0 1 e4 L
  6. e4 1 1 e4 L
  7. e4 0 0 e5 L
  8. e5 1 1 e5 L
  9. e5 0 1 e1 R#


 

Code :
  1. etat1 1 0 etat2 R
  2. etat2 1 1 etat2 R
  3. etat2 0 0 stateInEnglish3 R
  4. stateInEnglish3 1 1 stateInEnglish3 R
  5. stateInEnglish3 0 1 q4 L
  6. q4 1 1 q4 L
  7. q4 0 0 e5 L
  8. e5 1 1 e5 L
  9. e5 0 1 etat1 R#


 
0ù etat1, etat2, stateInEnglish3, q4 et e5 sont les états.
 
Tu vois ce que je veux dire ? On ne peut pas prévoir à l'avance quelle taille auront le nom des états dans le fichier qui est lu.
 
Si vous avez des idées...
 
AR

Message cité 1 fois
Message édité par AigleRoyal le 25-11-2008 à 13:35:14
Reply

Marsh Posté le 25-11-2008 à 13:33:57    

AigleRoyal a écrit :


Tu vois ce que je veux dire ? On ne peut pas prévoir à l'avance quelle taille auront le nom des états dans le fichier qui est lu.

 

Eh oui, c'est le problème récurrent de la lecture de données en C.

 

Les deux solutions les plus courantes :

  • lecture dans un buffer que tu sais suffisamment grand pour contenir les données à lire
  • lecture dans un buffer, détection pour savoir si la chaîne est complète, et si ce n'est pas le cas, agrandissement du buffer et poursuite de la lecture. Rince & Repeat.


Dans ton cas, la première solution est peut-être suffisante.

Message cité 1 fois
Message édité par Elmoricq le 25-11-2008 à 13:34:09
Reply

Marsh Posté le 25-11-2008 à 13:37:28    

Elmoricq a écrit :


 
Eh oui, c'est le problème récurrent de la lecture de données en C.
 
Les deux solutions les plus courantes :

  • lecture dans un buffer que tu sais suffisamment grand pour contenir les données à lire
  • lecture dans un buffer, détection pour savoir si la chaîne est complète, et si ce n'est pas le cas, agrandissement du buffer et poursuite de la lecture. Rince & Repeat.


Dans ton cas, la première solution est peut-être suffisante.


 
Dans ce cas, je fais un tableau suffisamment grand ou un malloc de taille fixe ?
 
AR

Reply

Marsh Posté le 25-11-2008 à 13:39:22    

Un malloc() de taille fixe n'a aucun intérêt : l'allocation mémoire dynamique sert surtout lorsque la taille à allouer ne peut être déterminée qu'à l'exécution du code.

 

Donc un tableau de taille fixe me semble très bien.

Message cité 1 fois
Message édité par Elmoricq le 25-11-2008 à 13:39:37
Reply

Marsh Posté le 25-11-2008 à 13:42:14    

Elmoricq a écrit :

Un malloc() de taille fixe n'a aucun intérêt : l'allocation mémoire dynamique sert surtout lorsque la taille à allouer ne peut être déterminée qu'à l'exécution du code.
 
Donc un tableau de taille fixe me semble très bien.


 
Ok, je fais ça et je te mets au parfum.
 
Merci, pour ton aide et ton temps :jap:  
 
AR

Reply

Marsh Posté le 25-11-2008 à 20:27:33    

C'est bon, problème résolu tout marche nikel :)
 
Merci à vous tous,
 
AR

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed