[C] Problème fscanf avec string

Problème fscanf avec string [C] - C - Programmation

Marsh Posté le 13-08-2011 à 23:34:55    

Bonjour a tous,
 
voila ça fait deux jours que je galère sur un bout de programme (je viens de commencer a apprendre le C).
J'ai un fichier mot.txt ou il est écrit dedans : salut
Le problème c'est quand je lance mon programme, il crash  :??:  
 

Code :
  1. #include <stdio.h>
  2.     int main() {
  3.         char mot = {0};
  4.         FILE *f = fopen("mot.txt", "r" );
  5.         fscanf(f, "%s", &mot);
  6.         printf ("%s\n", mot);
  7.         fclose(f);
  8.         return 0;
  9.     }


Chose bizarre si je remplace %s par %c j'ai simplement "s" qui s'affiche (le début de "salut" je suppose).
 
Si quelqu'un a une idée de comment résoudre ce problème je suis preneur.
 
Merci beaucoup d'avance.  :jap:

Message cité 1 fois
Message édité par showbas le 13-08-2011 à 23:36:04
Reply

Marsh Posté le 13-08-2011 à 23:34:55   

Reply

Marsh Posté le 14-08-2011 à 00:04:14    

Code :
  1. #include <stdio.h>
  2.     int main() {
  3.         char mot [6] = {0};
  4.         FILE *f = fopen("mot.txt", "r" );
  5.         fscanf(f, "%s", mot);
  6.         printf ("%s\n", mot);
  7.         fclose(f);
  8.         return 0;
  9.     }

Message cité 1 fois
Message édité par Anonymouse le 14-08-2011 à 00:30:28
Reply

Marsh Posté le 14-08-2011 à 00:09:42    

Anonymouse a écrit :

Code :
  1. #include <stdio.h>
  2.     int main() {
  3.         char mot [6] = {0};
  4.         FILE *f = fopen("mot.txt", "r" );
  5.         fscanf(f, "%s", &mot);
  6.         printf ("%s\n", mot);
  7.         fclose(f);
  8.         return 0;
  9.     }



Merci de me répondre. Par contre ça ne marche toujours pas...

Reply

Marsh Posté le 14-08-2011 à 00:31:20    

showbas a écrit :


Merci de me répondre. Par contre ça ne marche toujours pas...


 
On compile avec les warnings et on enlève le & en trop devant mot.

Message cité 1 fois
Message édité par Anonymouse le 14-08-2011 à 00:31:53
Reply

Marsh Posté le 14-08-2011 à 01:30:25    

Anonymouse a écrit :


 
On compile avec les warnings et on enlève le & en trop devant mot.


ben j'ai même pas de warning vu que c'est explorer qui me dit que ça plante :
 
http://img8.imageshack.us/img8/6167/capturekco.png
 
Et pour le & je crois bien qu'il faut le laisser vu qu'on indique l'adresse de mot, son contenu n’intéresse pas fscanf.

Reply

Marsh Posté le 14-08-2011 à 09:53:52    

showbas a écrit :

Bonjour a tous,

 

voila ça fait deux jours que je galère sur un bout de programme (je viens de commencer a apprendre le C).
J'ai un fichier mot.txt ou il est écrit dedans : salut
Le problème c'est quand je lance mon programme, il crash  :??:

 
Code :
  1. #include <stdio.h>
  2.     int main() {
  3.         char mot = {0};
  4.         FILE *f = fopen("mot.txt", "r" );
  5.         fscanf(f, "%s", &mot);
  6.         printf ("%s\n", mot);
  7.         fclose(f);
  8.         return 0;
  9.     }


Chose bizarre si je remplace %s par %c j'ai simplement "s" qui s'affiche (le début de "salut" je suppose).

 

Si quelqu'un a une idée de comment résoudre ce problème je suis preneur.

 

Merci beaucoup d'avance.  :jap:

Il faudrait tester le retour de fopen, c'est le minimum.

Code :
  1. #include <stdio.h>
  2.     int main(void) {
  3.         char mot[1024] = {0};
  4.         FILE *f = fopen("mot.txt", "r" );
  5.        if (f == NULL)
  6.        {
  7.            puts("Pb ouverture fichier" );
  8.        }
  9.        else
  10.       {
  11.            fscanf(f, "%s", &mot);
  12.            printf ("%s\n", mot);
  13.            fclose(f);
  14.       }
  15.       return 0;
  16.     }


Cela ne règle pas tous les problèmes (en particulier la longueur du mot que tu vas lire, c'est  pourquoi j'ai mis 1024) mais c'est déjà mieux.
D'autre part, tu veux lire un mot, donc une suite de caractères, tu vas donc donner à fscanf une adresse où ranger les caractères. En C un tableau est en fait une adresse mémoire et le compilo s'arrange pour que tu puisses ranger tous les caractères qui sont prévus pour ce tableau, dans mon cas 1024. mot étant un tableau il n'y a pas besoin de mettre le &.
Dons ton premier code, tu as écris char mot donc tu dis que mot est un caractère, il faut donc alors effectivement mettre un & devant mot pour le fscanf qui prendra cette adresse, mais ici, mot n'est pas un tableau, alors fscanf va écrire consciensieusement les caractères lus (tu lui as dis de lire une suite de caractères : fscanf avec %s) donc il va écraser la mémoire est tu auras un crash.

 
Citation :

Chose bizarre si je remplace %s par %c j'ai simplement "s" qui s'affiche (le début de "salut" je suppose).

Pas du tout bizarre mais tout à fait normal, tu as par contre de la chance !
Si tu mets fscanf avec %c, tu indiques que tu veux lire un caractères, tu indiques l'adresse où le ranger avec &mot, fscanf fait ce qu'on lui dit de faire tout va bien.
Où tu as de la chance c'est le printf("%s \n", mot) si c'est ce que tu as écris (je penche plutôt pour printf("%s \n", &mot) car tu dis que tu veux écrire une chaine de caractère débutant à l'adresse de mot, or en C une chaine doit se terminer par \0 donc comme l'écriture se passe bien, à l'adresse de mot + 1 il y avait un \0 : une chance sur 256 !
Par contre, si tu as écrit printf("%c \n", mot) alors c'est tout ce qu'il y a de normal, tu dis que tu veux écrire la valeur du caractère mot sous forme de caractère et non de nombre.

Message cité 1 fois
Message édité par Trap D le 14-08-2011 à 10:06:57
Reply

Marsh Posté le 14-08-2011 à 11:12:42    

Trap D a écrit :

Il faudrait tester le retour de fopen, c'est le minimum.

Code :
  1. #include <stdio.h>
  2.     int main(void) {
  3.         char mot[1024] = {0};
  4.         FILE *f = fopen("mot.txt", "r" );
  5.        if (f == NULL)
  6.        {
  7.            puts("Pb ouverture fichier" );
  8.        }
  9.        else
  10.       {
  11.            fscanf(f, "%s", &mot);
  12.            printf ("%s\n", mot);
  13.            fclose(f);
  14.       }
  15.       return 0;
  16.     }


Cela ne règle pas tous les problèmes (en particulier la longueur du mot que tu vas lire, c'est  pourquoi j'ai mis 1024) mais c'est déjà mieux.
D'autre part, tu veux lire un mot, donc une suite de caractères, tu vas donc donner à fscanf une adresse où ranger les caractères. En C un tableau est en fait une adresse mémoire et le compilo s'arrange pour que tu puisses ranger tous les caractères qui sont prévus pour ce tableau, dans mon cas 1024. mot étant un tableau il n'y a pas besoin de mettre le &.
Dons ton premier code, tu as écris char mot donc tu dis que mot est un caractère, il faut donc alors effectivement mettre un & devant mot pour le fscanf qui prendra cette adresse, mais ici, mot n'est pas un tableau, alors fscanf va écrire consciensieusement les caractères lus (tu lui as dis de lire une suite de caractères : fscanf avec %s) donc il va écraser la mémoire est tu auras un crash.  
 

Citation :

Chose bizarre si je remplace %s par %c j'ai simplement "s" qui s'affiche (le début de "salut" je suppose).

Pas du tout bizarre mais tout à fait normal, tu as par contre de la chance !
Si tu mets fscanf avec %c, tu indiques que tu veux lire un caractères, tu indiques l'adresse où le ranger avec &mot, fscanf fait ce qu'on lui dit de faire tout va bien.  
Où tu as de la chance c'est le printf("%s \n", mot) si c'est ce que tu as écris (je penche plutôt pour printf("%s \n", &mot) car tu dis que tu veux écrire une chaine de caractère débutant à l'adresse de mot, or en C une chaine doit se terminer par \0 donc comme l'écriture se passe bien, à l'adresse de mot + 1 il y avait un \0 : une chance sur 256 !
Par contre, si tu as écrit printf("%c \n", mot) alors c'est tout ce qu'il y a de normal, tu dis que tu veux écrire la valeur du caractère mot sous forme de caractère et non de nombre.


Merci beaucoup pour toutes ces précisions effectivement ça marche très bien avec ton code le fait d'avoir indiqué 1024 a mot a réglé le problème.  
Je comprend également mieux le fonctionnement de fprintf.
Merci beaucoup.  :)

Reply

Marsh Posté le 14-08-2011 à 11:34:22    

Désolé je reviens avec un autre problème... je réalise un pendu en C le problème est que la si j'applique la méthode Trap D m'a expliquée ça ne fonctionne pas (j'ai encore un crash).
Voila le code, ne vous préoccupez pas trop de toutes les variables c'est surtout les opérations sur les fichier qui sont importantes. Le fichier qui m’intéresse est fichier2. Avant de faire le fscanf je fais déjà d'autres opérations sur fichier2 ça explique peut-être pourquoi il crash. Peut-être faut-il se repositionner au début du fichier ?? J'avoue être un peu perdu.

Code :
  1. int testlettre(char *copylettre, int *copyok)
  2. {
  3.     int reussite=0;
  4.     int i=0;   
  5.     char motsauv[1024] = {0};
  6.     int caractereActuel = 0;
  7.     int caractereSauv = 0;
  8.     FILE* fichier = NULL;
  9.     FILE* fichier2 = NULL;
  10.     fichier = fopen("test.txt", "r" );
  11.     fichier2 = fopen("sauv.txt", "r" );
  12.     if (fichier != NULL && fichier2 != NULL)
  13.     {
  14.         caractereActuel = fgetc(fichier);
  15.         caractereSauv = fgetc(fichier2);
  16.         while (caractereActuel != EOF)
  17.         {
  18.             if (caractereActuel == *copylettre && caractereSauv != *copylettre)
  19.             {
  20.                 fprintf(fichier2,copylettre);
  21.                 reussite++;
  22.             }
  23.             else
  24.             {
  25.                 fprintf(fichier2,"_" );
  26.             }
  27.             caractereActuel = fgetc(fichier);
  28.             caractereSauv = fgetc(fichier2);
  29.             i++;
  30.         }
  31.         printf("debug1" );
  32.         fscanf(fichier2, "%s", &motsauv);
  33.         printf ("%s\n", motsauv);
  34.         printf("debug2" );
  35.         if (i==reussite)
  36.         {
  37.             *copyok=1;
  38.         }
  39.         fclose(fichier);
  40.         fclose(fichier2);
  41.     }

Reply

Marsh Posté le 14-08-2011 à 11:54:30    

Citation :

fprintf(fichier2,copylettre);

 :heink: WTF!

 

De toute façon, il y a pas que ça de pas bon dans ce code:
int testlettre(char *copylettre, int *copyok)
1) tu utilises jamais le fait que copylettre est un pointeur, puisque tu déplaces jamais ce pointeur ni ne modifies la valeur pointée. Alors autant faire un passage de la lettre par valeur: int testlettre(char copylettre, int *copyok), c'est pas plus couteux que de la passer par pointeur, et plus sur.
2) apparemment, ta fonctions ne retourne rien, et tu as un pointeur sur un flag que tu positionnes si tout a été OK.
La encore, ce n'est pas un bon style. Fais retourner à ta fonction un indicateur si tout a été OK:
int testlettre(char copylettre)
{
    int copyok = 0;
    ...............
    return copyok;
}

 

A+,

Message cité 1 fois
Message édité par gilou le 14-08-2011 à 11:54:45

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-08-2011 à 12:11:34    

gilou a écrit :

Citation :

fprintf(fichier2,copylettre);

 :heink: WTF!
 
De toute façon, il y a pas que ça de pas bon dans ce code:
int testlettre(char *copylettre, int *copyok)
1) tu utilises jamais le fait que copylettre est un pointeur, puisque tu déplaces jamais ce pointeur ni ne modifies la valeur pointée. Alors autant faire un passage de la lettre par valeur: int testlettre(char copylettre, int *copyok), c'est pas plus couteux que de la passer par pointeur, et plus sur.
2) apparemment, ta fonctions ne retourne rien, et tu as un pointeur sur un flag que tu positionnes si tout a été OK.
La encore, ce n'est pas un bon style. Fais retourner à ta fonction un indicateur si tout a été OK:
int testlettre(char copylettre)  
{
    int copyok = 0;
    ...............
    return copyok;
}
 
A+,


 
Merci c'est corrigé et étrangement maintenant ça ne crash plus cependant ça ne m'affiche rien comme si le fscanf m'affichait du vide pourtant mon fichier 2 est bien remplit par un mot.

Reply

Marsh Posté le 14-08-2011 à 12:11:34   

Reply

Marsh Posté le 14-08-2011 à 12:16:08    

Ben déjà, c'est sur qu'en faisant fichier2 = fopen("sauv.txt", "r" ); il va être très facile d'écrire dans fichier2  [:prozac]  
Ensuite, si vous êtes positionné en fin de fichier, c'est sur qu'il y a rien a lire, et que fscanf ne va donc rien trouver à lire.
A+,

Message cité 1 fois
Message édité par gilou le 14-08-2011 à 12:18:48

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-08-2011 à 12:17:47    

gilou a écrit :

Ben déjà, c'est sur qu'en faisant fichier2 = fopen("sauv.txt", "r" ); il va être très facile d'écrire dans fichier2  [:prozac]  
A+,


 :pt1cable: oui effectivement petite erreur de ma part ^^ du coup ça se remet a crasher  :sweat:

Reply

Marsh Posté le 14-08-2011 à 12:20:50    

cf mon édit...
regarder votre position dans le fichier avant écriture et lecture.
l'utilisation de ftell et fpos peut être un plus :whistle:  
Bon, je vais bouffer...
A+,

Message cité 1 fois
Message édité par gilou le 14-08-2011 à 12:31:17

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-08-2011 à 13:14:10    

gilou a écrit :

cf mon édit...
regarder votre position dans le fichier avant écriture et lecture.
l'utilisation de ftell et fpos peut être un plus :whistle:  
Bon, je vais bouffer...
A+,


Super merci bien. j'ai utilisé rewind(fichier2) maintenant ça ne crashe plus par contre encore un probleme (eh oui !) il ne m'affiche que la premiere lettre du mot genre j'ai "salut" dans fichier il ne m'affiche que "s"  :??:  
Pourtant j'ai bien %s.

Code :
  1. rewind(fichier2);
  2. fscanf(fichier2, "%s", &motsauv);
  3. printf ("%s\n", motsauv);

Reply

Marsh Posté le 14-08-2011 à 13:58:46    

Faut dire que dans ton code, il y a des caractereSauv = fgetc(fichier2); qui me semblent suspicieux.
 
Si tu expliquais clairement ce que testlettre est censé faire ça aiderait grandement à comprendre le code.
1) En entrée, fichier contient quoi, fichier2 contient quoi
2) copylettre c'est quoi
3) la fonction fait quoi avec tout ça
4) en sortie fichier contient quoi, fichier2 contient quoi, copylettre vaut quoi et la fonction testlettre  retourne quoi?
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-08-2011 à 14:14:56    

gilou a écrit :

Faut dire que dans ton code, il y a des caractereSauv = fgetc(fichier2); qui me semblent suspicieux.
 
Si tu expliquais clairement ce que testlettre est censé faire ça aiderait grandement à comprendre le code.
1) En entrée, fichier contient quoi, fichier2 contient quoi
2) copylettre c'est quoi
3) la fonction fait quoi avec tout ça
4) en sortie fichier contient quoi, fichier2 contient quoi, copylettre vaut quoi et la fonction testlettre  retourne quoi?
 
A+,


En fait ça serait un peu long et inutile de t'expliquer je pense que le plus important est que a la sortie du while fichier 2 contient un mot entier (du style "salut" ) et le problème est que le fscanf ne prend que la première lettre. J'ai bien vérifié ne t’inquiète pas a la sortie du while le fichier sauv.txt (fichier2 pointe dessus) contient bien un mot entier.
Merci

Reply

Marsh Posté le 14-08-2011 à 14:35:56    

Citation :

En fait ça serait un peu long et inutile de t'expliquer

Dans ces conditions, il est long et inutile que je réfléchisse.
Les programmes non documentés méritent pas d'être améliorés.
Ce sera donc mon dernier commentaire:
Vu que tu as déclaré
char motsauv[1024];
faire
fscanf(fichier2, "%s", motsauv);
devrait améliorer les choses.
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 14-08-2011 à 14:48:23    

gilou a écrit :

Citation :

En fait ça serait un peu long et inutile de t'expliquer

Dans ces conditions, il est long et inutile que je réfléchisse.
Les programmes non documentés méritent pas d'être améliorés.
Ce sera donc mon dernier commentaire:
Vu que tu as déclaré
char motsauv[1024];
faire
fscanf(fichier2, "%s", motsauv);
devrait améliorer les choses.
A+,


Ok je disais pas ça méchamment après si tu le prends comme ça tant pis... c'est simplement que mon programme est un peu compliqué vu que je commence le C c'est pas super compréhensible.
Merci quand même, même si le fait d'enlever le & n'a rien changé.

Reply

Marsh Posté le 14-08-2011 à 15:12:45    

Chez moi, ça marche, quand je lis dans un fichier ou un mot a été inscrit, hein...

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(int argc, char *argv[])
  4. {
  5.     FILE *f = NULL;
  6.     char *fname = "test.txt";
  7.     char *errtab[3] = {"", "Error opening file %s!\n", "Error scanning file %s!\n"};
  8.     int   errcode = 0;
  9.     if (!(f = fopen(fname, "r" ))) { fprintf(stderr, errtab[errcode = 1], fname); }
  10.     else {
  11.         char buffer[1024] = {0};
  12.         if (fscanf(f, "%1023s", buffer) == EOF) { fprintf(stderr, errtab[errcode = 2], fname); }
  13.         else { fprintf(stdout, "%s\n", buffer); }
  14.         fclose(f);
  15.     }
  16.     return (errcode?EXIT_FAILURE:EXIT_SUCCESS);
  17. }

Donc si ça marche pas chez vous, c'est que le code que vous montrez n'est pas exactement celui que l'on teste ici.
Incidemment, file2 est bien ouvert en écriture et lecture (r+), j’espère...
A+,


Message édité par gilou le 14-08-2011 à 16:05:55

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Sujets relatifs:

Leave a Replay

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