OVH Cloud OVH Cloud

printf et scanf

102 réponses
Avatar
Pascal
Bonjour,

J'ai des pb bizarres : dans une fonction j'ai besoin que l'utilisateur
me donne plusieurs infos, je fais donc des printf("question") et des scanf.

Sur les 3 premieres questions, ca marche bien, sur les 2 dernières, le
programme les affiche, mais le scanf ne semble pas marcher. Pourtant le
scanf recup sur les 5 fois un char *. C'est un bug? D'ailleurs si je ne
mets pas de \n sur le printf, parfois c'est encore pire...
voici un ex :
char *nom;
printf("nom\n");
scanf("%s", nom);
etc .. prenom, adress, tel, mail...

Parfois le scanf est comme sauté. Dans une autre fonction, je fais la
meme chose : une question, une reponse. Il m'affiche bien la question,
mais le scanf comme s'il était inactif, le programme ne me laisse pas
répondre, et passe à l'instruction suivante...

10 réponses

1 2 3 4 5
Avatar
Jean-Marc
"Pascal" a écrit dans le message de
news:4187e772$0$19675$
Anthony Fleury wrote:

OUILLE ! Et où est ce que la place nécessaire pour stocker le nom a été


en fait j'ai réecris rapidement mon code, mais je me sers bien d'un char
nom [TAILLE]; (je fais même un memset)

Donc préferer fgets() :

fgets(nom, NOMBRE_DE_CARACTERE_MAX, stdin);

vérifier le retour de fgets() et enlever le n que fgets laisse et tout
ira


bien...


Ba c'est super pratique ça...

Pourquoi ? et bien parce que scanf a laissé le caractère 'n' qui est
tapé


derrière le nombre pour valider la première saisie, et quand il regarde
l'entrée standard il va retrouver ce caractère et le prendre pour la
saisie


d'après. Conclusion il va « ignorer » (du point de vue de l'utilisateur)
la


saisie d'après :-)



J'ai enfin l'explication de ce "bug". Je trouve ça aberrant que la
fonction scanf soit si mal foutu. Faudrait changer le man, et foutre
"grosse fonction qui fait n'imp".


Hello,

scanf, fscanf et sscanf sont pratiques pour lire des données
formattées, par exemple pour lire des données dans un fichier
dont on connait avec certitude la structure (parce qu'on l'a
écrit soi même par exemple). Dans les autre cas, c'est
effectivement une fonction pleine de pièges et dont l'emploi
n'est pas évident.

--
Jean-marc
"There are only 10 kind of people
those who understand binary and those who don't."


Avatar
Emmanuel Delahaye
Jean-Marc wrote on 02/11/04 :
scanf, fscanf et sscanf sont pratiques pour lire des données
formattées, par exemple pour lire des données dans un fichier
dont on connait avec certitude la structure (parce qu'on l'a
écrit soi même par exemple).


Et encore... Il vaut parfois mieux passer par fgets(), puis sscanf().
De toutes façons, il faut tester le code retour de *scanf() (nombre de
conversions réussies).

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

Avatar
Anthony Fleury
Hamiral wrote:


fgets() reads in at most one less than size characters
Mais c'est pas possible ça, la deuxième fois que je poste un ânerie plus

grosse que moi sur ce groupe. Pourant j'avais lu la manpage juste
avant de poster, pour être sûr. Mais j'ai dû lire un peu vite, j'ai
sauté le "one less" ...
Mea culpa, je posterai plus avant de lire 7 fois la manpage
correspondante.


Y'a pas de mal, je suis loin d'être le dernier à en dire (merci au passage à
ceux qui me corrigent et donc me font progresser).
De plus, il y a tellement de fonctions « bizarres » dans la manipulation de
chaines (cf les discussions sur strncpy et strncat) que pour une fois
qu'une fonction se comporte normalement ca peut surprendre...

Anthony
--
Alan Turing thought about criteria to settle the question of whether
machines can think, a question of which we now know that it is about as
relevant as the question of whether submarines can swim.
-- Dijkstra


Avatar
Pascal
J'ai essayé fgets, ça ne marche pas non plus. Il me saute le fgets :

printf("Entrer votre nom : ");//param est une struct qui contient les
champs nom, prenom etc...
fgets(param.nom, TAILLE_NOM, stdin);
printf("Entrer votre prenom : ");
fgets(param.prenom, TAILLE_NOM, stdin);
printf("Entrer votre adresse : ");
fgets(param.adresse, TAILLE_ADRESSE, stdin);
printf("Entrer votre tel : ");
fgets(param.tel, TAILLE_TEL, stdin);
printf("Entrer votre mail : ");
fgets(param.mail, TAILLE_MAIL, stdin);

et sur mon ecran j'ai ça :
**************************************
Agenda Répartie
**************************************
Choisissez le numéro :
1 - Lister les agendas disponibles
2 - Créer un agenda
3 - Insérer un contact
4 - Rechercher un contact
5 - Supprimer un contact

0 - Quitter le programme

Rep : 3
Entrer votre nom : Entrer votre prenom :

Et la je peux rentrer le reste des infos normalement(prenom, mail,
tel...), mais pour le nom, je n'ai rien rentré. Il est tout de suite
passé au prenom.
Avatar
Jean-Marc
"Emmanuel Delahaye" a écrit dans le message de
news:
Jean-Marc wrote on 02/11/04 :
scanf, fscanf et sscanf sont pratiques pour lire des données
formattées, par exemple pour lire des données dans un fichier
dont on connait avec certitude la structure (parce qu'on l'a
écrit soi même par exemple).


Et encore... Il vaut parfois mieux passer par fgets(), puis sscanf().
De toutes façons, il faut tester le code retour de *scanf() (nombre de
conversions réussies).



Très juste. Dans la pratique, le couple fgets/sscanf + test
de conversion est le plus (simple|sur|efficace) pour lire et
convertir des entrées formatées.

--
Jean-marc
"There are only 10 kind of people
those who understand binary and those who don't."


Avatar
Emmanuel Delahaye
Pascal wrote on 02/11/04 :
J'ai essayé fgets, ça ne marche pas non plus. Il me saute le fgets :

printf("Entrer votre nom : ");//param est une struct qui contient les
champs nom, prenom etc...
fgets(param.nom, TAILLE_NOM, stdin);
printf("Entrer votre prenom : ");
fgets(param.prenom, TAILLE_NOM, stdin);
printf("Entrer votre adresse : ");
fgets(param.adresse, TAILLE_ADRESSE, stdin);
printf("Entrer votre tel : ");
fgets(param.tel, TAILLE_TEL, stdin);
printf("Entrer votre mail : ");
fgets(param.mail, TAILLE_MAIL, stdin);


C'est possible si un des champs est trop petit. Prevoir de la place
pour le 'n' et le 0.

Mais pour bien faire, il faut saisir la ligne dans une chaine
suffisament grande, supprimer le 'n', puis recopier la chaine dans le
champ, qui doit être suffisament grand pour le 0 final.

J'ai pas donné çà, déjà :

http://mapage.noos.fr/emdel/notes.htm#saisie

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

Avatar
Pascal
Je viens de tester le fgets, et j'ai les même soucis.

Par exemple, dans mon code, j'ai ça :
void creerAgenda(CLIENT *clnt)
{
agenda agd;
int *result;

printf("Creation d'un agendan");
printf("Entrer le nom de l'agenda : n");
fgets(agd.nom_agenda, TAILLE_NOM_AGENDA, stdin);
...

et dans mon switch :

switch (rep)
{
case 1 :
listAgenda(clnt);
break;
case 2 :
creerAgenda(clnt);
break;
case 3 :
malloc_info(&param);
printf("Entrer votre nom : ");
fgets(param.nom, TAILLE_NOM, stdin);
printf("Entrer votre prenom : ");
fgets(param.prenom, TAILLE_NOM, stdin);
printf("Entrer votre adresse : ");
fgets(param.adresse, TAILLE_ADRESSE, stdin);
printf("Entrer votre tel : ");
fgets(param.tel, TAILLE_TEL, stdin);
printf("Entrer votre mail : ");
fgets(param.mail, TAILLE_MAIL, stdin);


Ba quand je tape 2, il va bien dans la fonction, sur l'ecran, ça
m'affiche à la vitesse de l'eclair la phrase, mais je peux pas rentrer
ma réponse.
Si je tape 3, j'ai ça sur mon écran :
Choisissez le numéro :
1 - Lister les agendas disponibles
2 - Créer un agenda
3 - Insérer un contact
4 - Rechercher un contact
5 - Supprimer un contact

0 - Quitter le programme

Rep : 3
Entrer votre nom : Entrer votre prenom :

En gros, la première réponse, "nom" a été sauté, et il est directement
passé au prenom. Ensuite (adresse,tel, mail) ça se passe normalement. Où
est l'erreur??
Avatar
Pascal
C'est possible si un des champs est trop petit. Prevoir de la place pour
le 'n' et le 0.

Mais pour bien faire, il faut saisir la ligne dans une chaine
suffisament grande, supprimer le 'n', puis recopier la chaine dans le
champ, qui doit être suffisament grand pour le 0 final.

J'ai pas donné çà, déjà :

http://mapage.noos.fr/emdel/notes.htm#saisie



Oups j'ai reposté, car j'ai pas vu mon post... m'enfin tant pis, le
deuxième post est plus clair. Et fais aussi part d'un autre pb.

Les constantes sont définis comme ci :
#define TAILLE_NOM 255
#define TAILLE_ADRESSE 255
#define TAILLE_MAIL 255
#define TAILLE_UID 25
#define TAILLE_PWD 3
#define TAILLE_TEL 10
#define TAILLE_NOM_AGENDA 1024

Donc il y a largement assez de place!

Avatar
Emmanuel Delahaye
Emmanuel Delahaye wrote on 02/11/04 :
http://mapage.noos.fr/emdel/notes.htm#saisie


et ça:

http://mapage.noos.fr/emdel/notes.htm#fichiers

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

Avatar
Emmanuel Delahaye
Pascal wrote on 02/11/04 :
Je viens de tester le fgets, et j'ai les même soucis.

Par exemple, dans mon code, j'ai ça :


Poste un code compilable et simplifié qui montre le problème, parce là,
on ne peut pas savoir d'où vient l'erreur.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"

1 2 3 4 5