- Probleme de saisie avec fgets. [debutant] - C - Programmation
Marsh Posté le 04-11-2005 à 01:22:16
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)
Marsh Posté le 04-11-2005 à 01:26:25
Taz a écrit : printf("..." ); |
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.
Marsh Posté le 04-11-2005 à 01:54:30
Voila l'ensemble de mon code, si j'avais oublie une ligne, et que ce soit elle qui fasse planter :
Code :
|
Marsh Posté le 04-11-2005 à 04:33:32
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.
Marsh Posté le 04-11-2005 à 06:51:51
Taz a écrit : 2) // commentaire C++, pas C |
// est un commentaire C valable en C99 (m'étais fait avoir aussi).
Marsh Posté le 04-11-2005 à 11:59:49
Taz a écrit : |
Mais quand j'appele ma fonction :
saisie(anu_secu);
Il me dit que le parametre anu_secu n'est pas bon.
Taz a écrit : |
D'accord je savais pas qu'il etait possible de faire ca.
merci
Taz a écrit : |
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.
Marsh Posté le 04-11-2005 à 12:27:26
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?
Marsh Posté le 04-11-2005 à 12:51:25
le fou a écrit : Lorsque je fais un fgets pour ma saisie au clavier, je capture donc le \n. |
Oui, en utilisant par exemple strrchr() qui retourne un pointeur sur un caractère recherché dans une chaîne.
Marsh Posté le 04-11-2005 à 13:07:25
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.
Marsh Posté le 04-11-2005 à 21:58:58
y'a plus simple :
char* chaine = "Coucou\n";
chaine[strlen(chaine)-1] = '\0'; // On raccourcit la chaine de 1 caractere pour virer le \n
Marsh Posté le 04-11-2005 à 22:06:00
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
Marsh Posté le 04-11-2005 à 22:35:51
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 |
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.
Marsh Posté le 04-11-2005 à 23:43:01
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()
Marsh Posté le 05-11-2005 à 12:21:38
nlc a écrit : y'a plus simple : |
Non, une chaine n'est pas modifiable.
Marsh Posté le 05-11-2005 à 12:23:45
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 |
Non.
La seule méthode reconnue pour éliminer le '\n' est le search'n kill.
|
Marsh Posté le 07-11-2005 à 23:14:41
bonsoir
est il possible de tester si le nombre de caractere rentre lors d'un fgets est compatible avec la capacité du tableau?
Marsh Posté le 07-11-2005 à 23:21:26
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.
Marsh Posté le 07-11-2005 à 23:25:30
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). |
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é?)
Marsh Posté le 08-11-2005 à 08:08:44
le fou a écrit : Oui mais dans le cas, d'une saisie au clavier, par exemple |
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
Marsh Posté le 03-11-2005 à 23:49:48
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)