Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1330 connectés 

  FORUM HardWare.fr
  Programmation
  C

  [debutant] - Probleme de saisie avec fgets.

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[debutant] - Probleme de saisie avec fgets.

n°1238334
le fou
Forza Massallia
Posté le 03-11-2005 à 23:49:48  profilanswer
 

Bonsoir
 
J'ai un petit programme, pour repondre a un exos, qui permet de saisir une structure (nom, prenom, age, n° secu).
Bon,donc mon probleme vient de la saisie des ces valeurs.
 
La structure est declare en parametres general comme suit :

 
struct identity {
char nom[15];
char prenom[10];
int age;
int secu;
struct identity *next;
}st,tmp;


 
Bon, ensuite dans mon main, j'appele ma fonction saisie qui est :


void saisie (char *anu_secu)  
 
{
 
 FILE *fp;
 char temp[10];
 
 printf("Informations :\n" );
 
 printf("==============\n" );
 
 
 printf ("Nom\t\t : " );
 fgets(st.nom, sizeof(st.nom), stdin);
 fflush (stdout);
 
 
 
     
 
 printf ("Prenom\t\t : " );
 
 fgets(st.prenom, sizeof(st.prenom), stdin);
 
 fflush(stdout);
 
 
 
 printf ("Age\t\t : " );
 
 fgets(temp, sizeof(temp), stdin);
 st.age = strtol(temp, NULL, 10);
 
 fflush(stdout);
 
 
 
 printf ("Numero de secu\t : " );
 
 fgets(temp, sizeof(temp), stdin);
 st.secu = strtol(temp, NULL, 10);
 
 fflush(stdout);
}


 
Alors le probleme vient du fait que, lorsque j'arrive sur cette fonction  au lieu de demander le nom, attendre la saisie, et demander le prenom. J'ai un affichage comme suit :


Informations :
==============
Nom              : Prenom                :


 
En fait il affiche la ligne "prenom", alors que j'ai pas encore rentre le nom.
 
Ps : les librairies utilisés sont :   stdio, stdlib, et ncurses.
Compilateur gcc-4.0.1 (linux)
 
Merci de votre aide


Message édité par le fou le 03-11-2005 à 23:53:55

---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
mood
Publicité
Posté le 03-11-2005 à 23:49:48  profilanswer
 

n°1238354
Taz
bisounours-codeur
Posté le 04-11-2005 à 01:22:16  profilanswer
 

printf("..." );
fflush(stdout);
fgets( .... );
 
 
il ne serait peut être pas mauvais de vérifier que fgets ne renvoit pas NULL (auquel cas fin de fichier / erreur)

n°1238356
le fou
Forza Massallia
Posté le 04-11-2005 à 01:26:25  profilanswer
 

Taz a écrit :

printf("..." );
fflush(stdout);
fgets( .... );
 
 
il ne serait peut être pas mauvais de vérifier que fgets ne renvoit pas NULL (auquel cas fin de fichier / erreur)


 
Non, meme en mettant le fflush entre le printf et le fgets ca ne marche pas.
 
Ce que je ne comprends pas , c'est que si j'utilise un scanf a la place de fgets, je n'ai pas ce probleme la.


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
n°1238358
Taz
bisounours-codeur
Posté le 04-11-2005 à 01:49:31  profilanswer
 

montre ton code corrigé.

n°1238359
le fou
Forza Massallia
Posté le 04-11-2005 à 01:54:30  profilanswer
 

Voila l'ensemble de mon code, si j'avais oublie une ligne, et que ce soit elle qui fasse planter :
 

Code :
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <ncurses.h>
  4. struct identity {
  5. char nom[15];
  6. char prenom[10];
  7. int age;
  8. int secu;
  9. }st,tmp;
  10. void saisie (char *anu_secu)
  11. {
  12. FILE *fp;
  13. char temp[10];
  14. puts("Informations :" );
  15. puts("==============" );
  16. printf ("Nom\t\t : " );
  17. fflush (stdout);
  18. fgets(st.nom, sizeof st.nom, stdin);
  19.  printf ("Prenom\t\t : " );
  20. fflush (stdout);
  21. fgets(st.prenom, sizeof st.prenom, stdin);
  22. printf ("Age\t\t : " );
  23.         fflush(stdout);
  24.         fgets(temp, sizeof(temp), stdin);
  25. st.age = strtol(temp, NULL, 10);
  26. printf ("Numero de secu\t : " );
  27.         fflush(stdout);
  28. fgets(temp, sizeof(temp), stdin);
  29. st.secu = strtol(temp, NULL, 10);
  30. //ECRITURE DU NOM
  31. puts ("ouverture du fichier en cours.." );
  32. fp=fopen (anu_secu,"a+" );
  33. puts("\nEcriture du nom dans le fichier" );
  34. fprintf (fp, "%s",st.nom);
  35. fprintf(fp,"\n" );
  36. //ECRITURE DU PRENOM
  37. puts("\nEcriture du nom dans le fichier" );
  38. fprintf (fp, "%s",st.prenom);
  39. fprintf(fp,"\n" );
  40. // ECRITURE DE L AGE
  41. puts("\nEcriture de l'age dans le fichier" );
  42. fprintf (fp, "%d",st.age);
  43. fprintf(fp,"\n" );
  44.         // ECRITURE DU NUMERO DE SECU
  45. puts("\nEcriture du numero de secu dans le fichier" );
  46. fprintf (fp, "%d",st.secu);
  47. fprintf(fp,"\n" );
  48. puts("\nFermeture du fichier" );
  49. fclose(fp);
  50. }
  51. void visu (char *anu_secu)
  52. {
  53. FILE *fp;
  54. printf("Nom desire\t: " );
  55. scanf("%s",tmp.nom);
  56. getchar();
  57. puts ("ouverture du fichier en cours.." );
  58. fp=fopen (anu_secu,"r+" );
  59. fseek (fp,0,SEEK_SET);
  60. //RECHERCHE
  61. while (strcmp(tmp.nom,st.nom)!=0) {
  62.  fscanf(fp,"%[^\n]\n",st.nom);
  63.  fscanf (fp,"%[^\n]\n",tmp.prenom);
  64.  fscanf (fp,"%d[^\n]\n",&tmp.age);
  65.  fscanf (fp,"%d[^\n]\n",&tmp.secu);
  66. }
  67. //AFFICHAGE
  68. system("clear" );
  69. puts("Informations : " );
  70. puts("===============" );
  71. puts("\n" );
  72. printf("Nom\t\t : %s\n",tmp.nom);
  73. printf("Prenom\t\t : %s\n",tmp.prenom);
  74. printf("Age\t\t : %d\n",tmp.age);
  75. printf("Numero de secu\t : %d\n",tmp.secu);
  76. getchar();
  77. }
  78. int main (void)
  79. {
  80. char *anu_secu="/home/beware/TPC/anu_secu.txt";
  81. char *tmp="/home/beware/TPC/tmp.txt";
  82. int c=0;
  83. char temp[2];
  84. while (c != 3)
  85. {
  86. system("clear" );
  87. printf("\t\t{-------------------MENU-------------------}\n" );
  88. printf("\t\t{                                          }\n" );
  89. printf("\t\t{                                          }\n" );
  90. printf("\t\t{     1 - Saisir une nouvelle fiche        }\n" );
  91. printf("\t\t{     2 - Visualiser les fiches            }\n" );
  92. printf("\t\t{     3 - Quitter                          }\n" );
  93. printf("\t\t{                                          }\n" );
  94. printf("\t\t{------------------------------------------}\n" );
  95. puts("\n\n\n" );
  96. printf("Choix : " );
  97. fflush(stdout);
  98. fgets(temp, sizeof(temp), stdin);
  99. c = strtol(temp, NULL, 10);
  100. system("clear" );
  101. if (c==1)
  102. {
  103.         saisie(anu_secu);
  104. }
  105. else if (c==2)
  106. {
  107.  visu(anu_secu);
  108. }
  109. }
  110. }


Message édité par le fou le 04-11-2005 à 01:58:01

---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
n°1238360
Taz
bisounours-codeur
Posté le 04-11-2005 à 04:33:32  profilanswer
 

1) <ncruses.h> ne te sert à rien. manque <string.h>.
2) // commentaire C++, pas C
3) char *anu_secu = "/home/beware/TPC/anu_secu.txt"; mauvais
   const char *anu_secu = "/home/beware/TPC/anu_secu.txt"; OK
4) t'as le droit de grouper tes prinfs
 
   printf("ligne1\n"
           "ligne2\n"
           ... );
 
 
5) et enfin :
fgets(temp, sizeof(temp), stdin);
 
bravo tu as lu 2 caractère. Un chiffre (espérons le) et un '\0' sont désormais dans temp. Et l'\n' il est passé où ? il est toujours dans le buffer ! Résultat, le prochain fgets il lit une ligne vide (ce qui lui convient très bien). Bon vu ton niveau, on a qu'à dire "agrandit temp" à 80caratères.

n°1238361
Taz
bisounours-codeur
Posté le 04-11-2005 à 04:33:54  profilanswer
 

ah oui : pourquoi des variables globales ...

n°1238363
Elmoricq
Modérateur
Posté le 04-11-2005 à 06:51:51  profilanswer
 

Taz a écrit :

2) // commentaire C++, pas C


 
// est un commentaire C valable en C99 (m'étais fait avoir aussi).

n°1238555
le fou
Forza Massallia
Posté le 04-11-2005 à 11:59:49  profilanswer
 

Taz a écrit :


1) <ncruses.h> ne te sert à rien. manque <string.h>.
2) // commentaire C++, pas C
3) char *anu_secu = "/home/beware/TPC/anu_secu.txt"; mauvais
   const char *anu_secu = "/home/beware/TPC/anu_secu.txt"; OK


Mais quand j'appele ma fonction :
saisie(anu_secu);
Il me dit que le parametre anu_secu n'est pas bon.
 

Taz a écrit :


4) t'as le droit de grouper tes prinfs
 
   printf("ligne1\n"
           "ligne2\n"
           ... );


 
D'accord je savais pas qu'il etait possible de faire ca.
merci
 

Taz a écrit :


5) et enfin :
fgets(temp, sizeof(temp), stdin);
 
bravo tu as lu 2 caractère. Un chiffre (espérons le) et un '\0' sont désormais dans temp. Et l'\n' il est passé où ? il est toujours dans le buffer ! Résultat, le prochain fgets il lit une ligne vide (ce qui lui convient très bien). Bon vu ton niveau, on a qu'à dire "agrandit temp" à 80caratères.


 
Ah oui je comprends mieux pourquoi alors je sautais une saisie. En fait ormis, le cas du temp pas assez grand, je pensais naivement que le fflush vidait le buffer d'entree et donc empechait qu' un \n ne s'y trouve. Mais apparement c'est pas ca.
 
 
PS :  
merci beaucoup pour ton aide.
 
La variable globale n'a rien a faire, il est vrai il faut que je l'integre dans mon main, et que je balance les pointeurs quand j'en ai besoin.
 


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
n°1238576
le fou
Forza Massallia
Posté le 04-11-2005 à 12:27:26  profilanswer
 

Lorsque je fais un fgets pour ma saisie au clavier, je capture donc le \n.
 
Y  a til un moyen, ormis faire une boucle pour le detecter, de ne pas ecrire le \n dans le fichier?


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
mood
Publicité
Posté le 04-11-2005 à 12:27:26  profilanswer
 

n°1238589
Elmoricq
Modérateur
Posté le 04-11-2005 à 12:51:25  profilanswer
 

le fou a écrit :

Lorsque je fais un fgets pour ma saisie au clavier, je capture donc le \n.
 
Y  a til un moyen, ormis faire une boucle pour le detecter, de ne pas ecrire le \n dans le fichier?


 
Oui, en utilisant par exemple strrchr() qui retourne un pointeur sur un caractère recherché dans une chaîne.

n°1238604
le fou
Forza Massallia
Posté le 04-11-2005 à 13:07:25  profilanswer
 

Elmoricq a écrit :

Oui, en utilisant par exemple strrchr() qui retourne un pointeur sur un caractère recherché dans une chaîne.


 
 
Merci beaucoup
ca marche.


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
n°1239136
nlc
Le mieux est l'ennemi du bien
Posté le 04-11-2005 à 21:58:58  profilanswer
 

y'a plus simple :
 
char* chaine = "Coucou\n";
 
chaine[strlen(chaine)-1] = '\0'; // On raccourcit la chaine de 1 caractere pour virer le \n


---------------
char table[] = {112,114,105,110,116,102,40,34,37,99,37,99,37,99,34,44,49,49,48,44,49,48,56,44,57,57,41,59,0}; char* tablePtr = table; while(*tablePtr) printf( "%c",*tablePtr++ );
n°1239137
Taz
bisounours-codeur
Posté le 04-11-2005 à 22:00:03  profilanswer
 

...

n°1239138
nlc
Le mieux est l'ennemi du bien
Posté le 04-11-2005 à 22:06:00  profilanswer
 

Ca pourrait bugguer si la chaine etait vide, mais comme elle vient d'un fgets, on recupe forcement au moins un caractere, le \n
 
Donc tu peux faire :
 
fgets(st.prenom, sizeof st.prenom, stdin);
st.prenom[strlen(st.prenom)-1] = '\0'; // Vire le \n


---------------
char table[] = {112,114,105,110,116,102,40,34,37,99,37,99,37,99,34,44,49,49,48,44,49,48,56,44,57,57,41,59,0}; char* tablePtr = table; while(*tablePtr) printf( "%c",*tablePtr++ );
n°1239148
Elmoricq
Modérateur
Posté le 04-11-2005 à 22:35:51  profilanswer
 

nlc a écrit :

Ca pourrait bugguer si la chaine etait vide, mais comme elle vient d'un fgets, on recupe forcement au moins un caractere, le \n
 
Donc tu peux faire :
 
fgets(st.prenom, sizeof st.prenom, stdin);
st.prenom[strlen(st.prenom)-1] = '\0'; // Vire le \n


 
[:mlc]
 
man fgets :
 

Citation :

The fgets() function shall read bytes from stream into the array pointed to by s, until n-1 bytes are read, or a <newline> is read and transferred to s, or an end-of-file condition is encountered. The string is then terminated with a null byte.


 
Ta chaîne n'est pas obligatoirement terminée par un '\n'.
 
Tiens et puis pour rire, tape directement CTRL+C (ou CTRL+D sous Unix) à la saisie de ta chaîne, comme ça, pour rire. [:itm]


Message édité par Elmoricq le 04-11-2005 à 22:36:55
n°1239176
nlc
Le mieux est l'ennemi du bien
Posté le 04-11-2005 à 23:43:01  profilanswer
 

Si on fait un control C sur un fgets( temp, sizeof(temp), stdin ) ca coupe completement le programme.
 
Ensuite, si le fgets a lu n-1 octets, c'est qu'il arrive en bout de buffer, donc il s'arrete pour se reserver un octet pour mettre le 0 de fin de chaine.
 
Ce que je voulais dire plus haut, c'est qu'il ne faut pas faire un st.prenom[strlen(st.prenom)-1] = '\0' sur une chaine vide, sinon ca ecrit hors de la zone st.prenom.
 
Mais avec un fgets( temp, sizeof(temp), stdin ), y'a peu de chance pour que la chaine temp fasse 0 !
 
Edit : Ah ! Autant pour moi, le Ctrl D renvoit bien 0 (si on a rien tapé avant), donc pour etre blindé faut faire un test.
Ou mieux, utiliser strchr()  :whistle:
 
[:anathema]
 


Message édité par nlc le 05-11-2005 à 00:05:06

---------------
char table[] = {112,114,105,110,116,102,40,34,37,99,37,99,37,99,34,44,49,49,48,44,49,48,56,44,57,57,41,59,0}; char* tablePtr = table; while(*tablePtr) printf( "%c",*tablePtr++ );
n°1239281
Emmanuel D​elahaye
C is a sharp tool
Posté le 05-11-2005 à 12:21:38  profilanswer
 

nlc a écrit :

y'a plus simple :
 
char* chaine = "Coucou\n";
 
chaine[strlen(chaine)-1] = '\0'; // On raccourcit la chaine de 1 caractere pour virer le \n


Non, une chaine n'est pas modifiable.
 


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1239282
Emmanuel D​elahaye
C is a sharp tool
Posté le 05-11-2005 à 12:23:45  profilanswer
 

nlc a écrit :

Ca pourrait bugguer si la chaine etait vide, mais comme elle vient d'un fgets, on recupe forcement au moins un caractere, le \n
 
Donc tu peux faire :
 
fgets(st.prenom, sizeof st.prenom, stdin);
st.prenom[strlen(st.prenom)-1] = '\0'; // Vire le \n


Non.
 
La seule méthode reconnue pour éliminer le '\n' est le search'n kill.


char *p = strchr(s, '\n');
 
if (p != NULL)
{
   *p = 0;
}


---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
n°1240923
le fou
Forza Massallia
Posté le 07-11-2005 à 23:14:41  profilanswer
 

bonsoir
est il possible de tester si le nombre de caractere rentre lors d'un fgets est compatible avec la capacité du tableau?


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
n°1240930
Elmoricq
Modérateur
Posté le 07-11-2005 à 23:21:26  profilanswer
 

fgets() ne va pas plus loin que la taille maximum - 1 (pour le caractère '\0' terminal) que tu lui passes en paramètre (et il s'arrête avant s'il rencontre un saut de ligne, ou une fin de fichier).  
 
C'est à toi de passer le bonne taille max.

Message cité 1 fois
Message édité par Elmoricq le 07-11-2005 à 23:22:04
n°1240933
le fou
Forza Massallia
Posté le 07-11-2005 à 23:25:30  profilanswer
 

Elmoricq a écrit :

fgets() ne va pas plus loin que la taille maximum - 1 (pour le caractère '\0' terminal) que tu lui passes en paramètre (et il s'arrête avant s'il rencontre un saut de ligne, ou une fin de fichier).  
 
C'est à toi de passer le bonne taille max.


 
Oui mais dans le cas, d'une saisie au clavier, par exemple
L utilisateur ne sait pas forcement le nombre max de caractere qui lui est permis de rentrer.
Doit on alors, prevoir plus de place pour le stockage, ou peut ton tester la longueur de la chaine rentre, (par exemple en verifiant, si aucun /n n'apparait dans la chaine stocké?)


---------------
Celui qui sauve une vie, sauve l'humanité (Le Talmud) - Personne n'a plus grand amour que celui de donner sa vie pour ses amis (Jean XV, 13)
n°1240994
Emmanuel D​elahaye
C is a sharp tool
Posté le 08-11-2005 à 08:08:44  profilanswer
 

le fou a écrit :

Oui mais dans le cas, d'une saisie au clavier, par exemple
L utilisateur ne sait pas forcement le nombre max de caractere qui lui est permis de rentrer.
Doit on alors, prevoir plus de place pour le stockage, ou peut ton tester la longueur de la chaine rentre, (par exemple en verifiant, si aucun /n n'apparait dans la chaine stocké?)


Si il est bien utilisé, fgets() ne permettra pas le débordement. Si une tentative de débordement a eu lieu, le '\n' n'est pas présent dans la chaine. Les caractères nons lus seront encore à disposition dans stdin. Il suffit de rappeler fgets() pour lire la suite. On peut aussi les ignorer en bouclant sur stdin avec fgetc(), par exemple, jusquà detection de '\n' ou de EOF.
 
http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fichiers
 
A l'aide d'une combinaison astucieuse de realloc(), de fgets() (ou de fgetc()) et d'une boucle, on peut saisir une ligne de longueur arbitraire.
 
Bref, il y a plusieurs possibilités. Il est conseillé de les recenser et d'écrire les fonctions correspondantes une bonne fois pour toutes.
 
http://mapage.noos.fr/emdel/clib.htm
Module IO


Message édité par Emmanuel Delahaye le 08-11-2005 à 08:12:10

---------------
Des infos sur la programmation et le langage C: http://www.bien-programmer.fr Pas de Wi-Fi à la maison : http://www.cpl-france.org/
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  [debutant] - Probleme de saisie avec fgets.

 

Sujets relatifs
[php] probleme avec ecriture de fichierprobleme avec un code
problème de session en phpProblème traduction avec ressource hacker
[debutant] [swing] bulle d'aide à la eclipse[ACCESS] probleme cumul sur requete
Problème de vitesse d'envoi de données par socketprobleme pour débuter java
Problème de forumaire d'inscriptionPetit problème de FTP
Plus de sujets relatifs à : [debutant] - Probleme de saisie avec fgets.


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR