probleme avec scanf

probleme avec scanf - C - Programmation

Marsh Posté le 19-04-2004 à 21:12:20    

Bonjour,
 
Petit probleme avec scanf donc.
En gros, le but du jeu est de saisir une chaine qui peut contenir des espaces. Si on met pas d'espace, tout se passe bien. Si on met des espaces, les scanf suivant sont "sautés".
 
En gros le code (j'abrege hein.. c'est pas la syntaxe exacte) resemble a :
 
printf "entrez chaine1"
scanf (chaine1)
printf "entrez chaine2"
scanf (chaine2)
printf "entrez chaine3"  
scanf (chaine3)
etc.
 
Si pour chaine1, je repond par exemple "bidule chose"
alors chaine1 vaudra bidule, et chaine2 vaudra chose,
le prog saute directement sur le dernier scanf.
Moi je voudrai qu'il considere les espaces comme des caracteres normaux quoi...
 
Voila, j'espere que c'etait clair comme explication :D Si vous avez une solution...

Reply

Marsh Posté le 19-04-2004 à 21:12:20   

Reply

Marsh Posté le 19-04-2004 à 21:17:29    

printf("message sans \\n" );
fflush(stdout);
fgets(buffer, sizeof buffer, stdin);

Reply

Marsh Posté le 19-04-2004 à 21:17:37    

salut,
scanf coupe a chaque espace ou entrée.
La suite est dans la chaine parce que ca marche avec un buffer qui se vide de ce qui a été passé dans ta variable, donc il reste "chose".
Pour faire simple, fais avec gets().
Si tu veux utiliser scanf, rajoute fflush(stdin); avant chacun d'eux pour éviter les pb de ce type avec le buffer.


Message édité par Le Mage le 19-04-2004 à 21:19:01
Reply

Marsh Posté le 19-04-2004 à 21:18:45    

Le Mage a écrit :

salut,
scanf coupe a chaque espace ou entrée.
La suite est dans la chaine parce que ca marche avec un buffer qui se vide de ce qui a été passé dans ta variable, donc il reste "chose".


buffer overflow -> erreur de segmentation

Le Mage a écrit :


Pour faire simple, fais avec gets().


buffer overflow -> erreur de segmentation

Le Mage a écrit :


Si tu veux utiliser scanf, rajoute fflush(stdin); avant chacun d'eux pour éviter les pb de ce type avec le buffer.

aucun effet. t'as besoin de retourner à l'école toi


Message édité par Taz le 19-04-2004 à 21:19:03
Reply

Marsh Posté le 19-04-2004 à 21:20:05    

Merci a vous deux, avec ca elle devrait y arriver....  
(moi le C j'avoue que ca fait un moment que j'en avait pas fait :D )

Reply

Marsh Posté le 19-04-2004 à 21:21:45    

merci à moi, si tu suis les conseils du mage, ça ne marchera jamais

Reply

Marsh Posté le 19-04-2004 à 21:24:01    

Taz : j'ai bien ton approche mais :
- Tu peux m'expliquer pourquoi on pourait pas mettre de \n a la fin du printf ? (désole j'ai l'impression de poser des questions bete la....)
- Y a pas moyen de faire ca avec un gets plutot qu'un fgets ? Enfin disons y a pas moyen de faire ca avec une syntaxe plus facile a comprendre ? Parce que c'est pour un programme de debutant en C, ils ont pas encore appris les stream, ni les malloc etc, bref, ils utilise que des tableaux pour leur chaine de caractere, je sens que si elle fait un truc aussi bien, avec un sizeof au milieu de la commande, ca va pas le faire...

Reply

Marsh Posté le 19-04-2004 à 21:29:10    

1) si tu ne force pas le rafraichissement de ton écran avec ton prompt, tu risque de voir d'abord le prompt, ensuite le message t'invitant à saisir une donnée. si le printf avec ton scanf se termine par un '\n', à cause du mode de bufferisation, tu n'a pas besoin de rafraichir manuellement, ça se fera tout seul
2) avec gets, si tu as un char[5] et que tu en saisi 10, ça va faire boom. avec fgets, tu spécifies le maximum de caractères à prendre, comme ça tu ne risques pas de dépassement de capacité.
 
vrai programme
 

Code :
  1. #include <stdio.h>
  2. int main()
  3. {
  4.   char buffer[40];
  5.   printf("prompt :" );
  6.   fflush(stdout);
  7.   fgets(buffer, sizeof buffer, stdin);
  8.   puts(buffer);
  9.   return 0;
  10. }

note que sizeof buffer == 40, c'est juste un raccourci pour éviter les erreurs de typo et autre puisqu'apèrs tout, on ne veut pas lire 40caractères, mais plutot autant de caractère que peut contenir le buffer

Reply

Marsh Posté le 19-04-2004 à 21:30:26    

char * fgets (char * s, int size, FILE * stream);
 
 
fgets renvoie NULL s'il y a une erreur
avec s le buffer d'entrée
size la taille du buffer d'entrée
stream le flux à lire

Reply

Marsh Posté le 19-04-2004 à 21:37:23    

Vi j'avais bien compris le principe, je voulais juste savoir si on pouvait pas faire tout aussi secure avec des commandes plus "simples". Mais bon, si pour eviter les buffer overflow y a pas le choix et qu'on est forcé de preciser la taille, ok, je vais lui conseiller ca.
Un immense merci.

Reply

Marsh Posté le 19-04-2004 à 21:37:23   

Reply

Marsh Posté le 19-04-2004 à 21:42:54    

Au lieu de casser tout le monde comme je viens de le voir sur d'autres post Taz, tu aurais pu remarquer le "pour faire simple" avant la suggestion du gets() vu qu'alana a l'air de débuter et faire juste qq tests.
Cela dit, le fflush(stdin); vide le buffer de SAISIE, tous les profs le conseille en C.

Reply

Marsh Posté le 19-04-2004 à 21:43:04    

ben en C, tu peux pas passer un tableau tel quel en paramètre, donc tu doit passer le tableau automatiquement converti en pointeur + sa taille. ça fait 2 paramètres déjà. après le flux, ici, stdin, le flux d'entrée standard ... rien de bien méchant. c'est sur que gets(char *buffer) aurait du être gets(char *buffer, size_t size) <-> fgets(buffer, size, stdin) mais c'est comme ça :/

Reply

Marsh Posté le 19-04-2004 à 21:48:41    

Le Mage ==> il est dit dans le k&r ansi que un fflush sur un input stream a un effet indefinis alors tu peux dir a t prof d'arreter de dir des connerie

Reply

Marsh Posté le 19-04-2004 à 21:49:18    

skelter a écrit :

Le Mage ==> il est dit dans le k&r ansi que un fflush sur un input stream a un effet indefinis alors tu peux dir a t prof d'arreter de dir des connerie


 
Je me suis fait grilled d'une force :D à la citation près.

Reply

Marsh Posté le 19-04-2004 à 21:51:26    

oui faut etre plus rapide :d

Reply

Marsh Posté le 19-04-2004 à 21:57:07    

je maintiens que pour les trucs basiques ca marche.
Apres, pour des manips + compliquées, je suis d'accord que ca a des ratés comme strcpy et la plupart des fonctions sur les chaines qui ont des effets de bords.

Reply

Marsh Posté le 19-04-2004 à 21:59:56    

Le Mage a écrit :

je maintiens que pour les trucs basiques ca marche.
Apres, pour des manips + compliquées, je suis d'accord que ca a des ratés comme strcpy et la plupart des fonctions sur les chaines qui ont des effets de bords.

1) non
2) non et c'est dangereux.
 
je crois que tous les compilateurs qui se valent emettent un warning si on utilise gets :o

Reply

Marsh Posté le 19-04-2004 à 22:04:51    

Je répète que G donné çà "pour faire simple", je l'utilise jamais et j'utilise tt le tps fgets.

Reply

Marsh Posté le 19-04-2004 à 22:05:58    

Le Mage a écrit :

Je répète que G donné çà "pour faire simple", je l'utilise jamais et j'utilise tt le tps fgets.

y a pas de "pour faire simple"
1) il ne faut jamais utiliser gets
2) fflush(stdin) n'a aucun effet comme déjà expliqué

Reply

Marsh Posté le 19-04-2004 à 22:09:38    

Enfin, je reconnais bien là le cliché du programmeur acharné et toujours agréable qd il explique (cf autres posts sur le même thème).
J'insiste pas.

Reply

Marsh Posté le 19-04-2004 à 22:11:42    

- gets est __la__ fonction à banir du C
- fflush(stdin) est un des plus gros mythe qui soit
 
 
et toi tu débarques et tu refiles ça à un débutant... t'attends pas à de bonnes réactions

Reply

Marsh Posté le 19-04-2004 à 22:20:28    

j'ai chercher sur internet et des fflush(stdin) on en voit partout (tuto, cours, exemple, ...)
 
inquietant non?

Reply

Marsh Posté le 19-04-2004 à 22:32:29    

Taz a écrit :

- fflush(stdin) est un des plus gros mythe qui soit

dieu^k&r est mort. les gens ne croient plus en rien, on est plus beaucoup à penser que pour apprendre le C il faut lire le k&r

Reply

Marsh Posté le 19-04-2004 à 22:43:01    

oui, ca j'imagine, en fait qd on regarde bien rare sont les tutos qui respecte le standard ansi, ne serait-ce que pour les commentaires  "//" omniresent
 
j'ai trouver un lien qui pointe sur des codes en vieux c (k&r pre ansi) marrant a voir
 
si ca interresse qq1
 
http://cm.bell-labs.com/cm/cs/who/dmr/primevalC.html


Message édité par skelter le 19-04-2004 à 22:44:19
Reply

Marsh Posté le 19-04-2004 à 23:57:23    

Whaou.. je vois que ca declanche un debat passioné...
bon merci encore Taz, car j'aprouve ton coté heu... on va dire extremiste ;)
Par contre le bout de code que tu m'a filé ne marche pas.
j'avoue que ca m'a un peu enervé, mais en fait je viens de comprendre pourquoi. Il semblerait que la fonction fflush ne fonctione pas sous linux. (j'avais pas precisé que c'etait sous linux mais bon.. je pensai pas une seconde que pour un truc aussi basique ca pouvait avoir de l'importance).
Donc voila sous linux c'est plus le bordel apparament.
Donc si t'a une autre reponse, plus unixiene on va dire, hesite pas :)

Reply

Marsh Posté le 20-04-2004 à 00:00:35    

y a quoi qui marche pas ? le bout de code que je t'ai filé fonctionne parfaitement. tu te rends compte de ce que tu sors : tu fais du C depuis 1h et tu remets un cause une fonction de la bibliothèqye qui a plus de 20ans "hey elle bug cette fonction, c'est de la merde" ?
faut être un peu sérieux. le petit bout de code que je t'ai donné fonctionne parfaitement. maintenant si ton programmes fonctionne mal, c'est que tu as d'autres endroits qui ne doivent pas être très sains

Reply

Marsh Posté le 20-04-2004 à 00:28:39    

Hé Du calme :( Je te dis juste ce que je constate, et ce que pretend le prof de ma femme (je t'ai dit c'est pas moi qui fait le programme). Et donc ce monsieur pretend que fflush fonctionne pas sous linux, il se goure peut etre completement, j'en sais fichtrement rien moi. Si tu m'affirme que ca fonctionne tout aussi bien sous linux et que tu as pu le verifier, je te crois. Maitenant mon probleme c'est que le premier fgets recupere un \n qui vient de je sais pas ou. Pour la suite par contre ca marche parfaitement.
 
Donc bein voila. Si tu m'affirme que ca fonctionne tout pareil sous linux, je vais continuer a me pencher sur le code pour essayer de comprendre d'ou pourait bien venir ce fichu \n. Sinon elle va suivre les recomandations de son prof (ultra lourdingues) qui consistent a reecrire la fonction fsgets a coup de getchar en gros. (vraiment pas top donc)

Reply

Marsh Posté le 20-04-2004 à 00:31:00    

ben quand tu saisis "dawa" au clavier, tu valides et hop y a un '\n' qui est balancé. donc oui tu le récupères évidemment. c'est écris dans la documentation.
 
tu veux l'enlever ? ben tu mets un '\0' à la place et voilà

Reply

Marsh Posté le 20-04-2004 à 00:35:38    

faut vraiment tout faire ici
 

Code :
  1. #include <stdio.h>
  2. #include <string.h>
  3.  
  4. char *my_gets(char *buffer, size_t size)
  5. {
  6.   char *eol = NULL;
  7.   if(!fgets(buffer, size, stdin))
  8.     return NULL;
  9.   eol = strrchr(buffer, '\n');
  10.   if(eol)
  11.     *eol = '\0';
  12.   return buffer;
  13. }
  14. int main()
  15. {
  16.   char buffer[40];
  17.    
  18.   printf("prompt : " );
  19.   fflush(stdout);
  20.   my_gets(buffer, sizeof buffer);
  21.   printf("\"%s\"", buffer);
  22.   return 0;
  23. }


Message édité par Taz le 20-04-2004 à 00:37:37
Reply

Marsh Posté le 20-04-2004 à 00:39:13    

juste pour l'histoire : je m'applique a toujours donné du code du plus pur standard c'est à dire qui fonctionne parfaitement de manière identique partout où il y a un compilateur qui respecte la norme. le prof de ta femme est un amateur, un mauvais pédagogue, un ignorant.

Reply

Marsh Posté le 20-04-2004 à 00:41:22    

Bein c'etait ce qu'elle etait en train d'ecrire. Merci donc de lui confirmer que c'est bien comme ca qu'il faut faire. J'avoue que je comprend un peu son etonement, tout ce code la pour faire un simple scanf qui fonctionne, t'avouera qu'on a déja fait plus ergonomique...

Reply

Marsh Posté le 20-04-2004 à 00:45:45    

rien à voir.
scanf -> pas (ou mauvaise) gestion des dépassement de capacité
-> impossible de lire une ligne, scanf lit jusqu'au premier blanc, c'est à dire un seul mot.
 
le fflush est une autre chose qui est compréhensible, les terminaux étant bufferisés en mode ligne
 
tu veux pas du '\n' qui est naturellement dans stdin puisque tu le tappes ? il te suffit de l'enlever.
 
ça reste du C. bien arrangé dans une jolie fonction, ça redevient sure, efficace et simple à utiliser.

Reply

Marsh Posté le 20-04-2004 à 00:47:06    

Citation :


le prof de ta femme est un amateur, un mauvais pédagogue, un ignorant.


 
Meme si je trouve completement anormal qu'il ai apparement pas parlé du probleme des buffer overflow, et encore plus anormal qu'il commence par filer des commandes dangereuses, je me met a sa place. Serieusmeent si je devai faire un cours en C, et si la premiere chose que je disai a mes eleves c'est que pour faire l'equivalent d'un input "nom :";A$ il faut plus de 20 lignes de code, je pense pas que mon cours ai beaucoup de succes et je pense que les elevs auraient vite laissé tombé.
 
Bref, c'est pas parce qu'UN prof enseigne pas un C ultra pur qu'il faut te mettre dans tes etats :D J'ai été impressioné par le nombre de bons profs qu'elle a, et par leur niveau global (ainsi que par leur large support de tout ce qui est open source).
 
Quand tu explique un truc a quelqu'un il faut deux choses, la connaissance technique, et un peu de pedagogie...
 
EDIT : j'ai édité car tout compte fait, je pense pas qu'il soit si mauvais que ca ce prof.


Message édité par Alana le 20-04-2004 à 09:33:42
Reply

Marsh Posté le 20-04-2004 à 00:48:14    

Gasp, t'a été plus rapide que moi. Je pensai a strcpy et j'ai edité mon post, mais trop tard :D

Reply

Marsh Posté le 20-04-2004 à 00:50:32    

euh je vois pas de quoi tu parles pour strcpy ? elle est dans quelle fac ta femme ? quelle formation ?
 
ce n'est pas une question d'être à jour. le C a toujours était comme ça. le créateur du C t'aurais à peu près suggéré la même chose que moi.

Reply

Marsh Posté le 20-04-2004 à 00:51:56    

Je parle de strcpy parce que c'est, il me semble, l'une des fonction a surtout pas utiliser pour faire du code secure, et tu semblait, comme moi, apporter une grande importance a cet aspect des choses.


Message édité par Alana le 20-04-2004 à 00:58:06
Reply

Marsh Posté le 20-04-2004 à 00:56:13    

strcpy peut en effet poser problème, on lui préfère strncpy/strlcpy mais c'est c'est là un moindre mal. le problème avec strcpy, c'est que si dans strcpy(dest, src) src a un problème, à savoir n'a pas de '\0' terminal, là ça fait boom. si src est correctement formé et que dest est suffisemment large pour accueillir une copie des caractères de src, tout ira bien.
 
en fait strcpy n'est pas dangereuse en elle même, ça vient des ses paramètres. mais gets, elle, va lire tant et plus de telle sorte que tu feras un dépassement de capacité quelque soit la taille de ton buffer de lecture.

Reply

Marsh Posté le 20-04-2004 à 00:57:41    

Je le note. Bon allez, dodo. Merci.

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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