probleme avec fgets

probleme avec fgets - C - Programmation

Marsh Posté le 27-12-2006 à 18:59:03    

Bonjour  :hello:  
j'ai un ptit probleme avec le fontion fgets()
En effet, quand j'utilise cette methode pour faire rentrer une chaine de caracteres dans une variable, je saute lors de l'excution du programme l'instruction qui appelle fgets();
Mais après avoir lu certains posts, je sais maintenant que cela provient de l'utilisation antérieure d'un scanf() qui laisse trainer un '\n' que récupère fgets();
Du coup je vide le buffer clavier avec cette instruction :

Code :
  1. int c;
  2. while ((c = getchar()) != '\n' && c != EOF);


Ca marche, seulement voilà, lorsque je veux afficher et enregistrer dans un fichier la chaine de caractères entrée par fgets(), elle fait sauter une ligne dans l'affichage et de même dans le fichier.
 
Y-a-t-il un moyen de remédier à cela ?

Reply

Marsh Posté le 27-12-2006 à 18:59:03   

Reply

Marsh Posté le 27-12-2006 à 19:09:50    

Moi je me ferai jamais au C, vous declarez des variable 'Int' et vous leur affectez des 'char', c'est exceptionnel tout de même.

Message cité 4 fois
Message édité par Profil supprimé le 27-12-2006 à 19:10:04
Reply

Marsh Posté le 27-12-2006 à 20:39:54    

vi bon je me suis trompé
je remets :

Code :
  1. char c;
  2. while ((c = getchar()) != '\n' && c != EOF)


Le problème reste le même...


Message édité par HomerJK le 27-12-2006 à 20:40:15
Reply

Marsh Posté le 27-12-2006 à 22:20:07    

Ben donne le code qui va pas, on y verra plus clair, car là on ne voit point de fgets

Reply

Marsh Posté le 27-12-2006 à 22:32:19    


 
d'un autre coté, en C, un char est un int...

Reply

Marsh Posté le 27-12-2006 à 22:34:32    

HomerJK a écrit :

Bonjour  :hello:  
j'ai un ptit probleme avec le fontion fgets()
En effet, quand j'utilise cette methode pour faire rentrer une chaine de caracteres dans une variable, je saute lors de l'excution du programme l'instruction qui appelle fgets();
Mais après avoir lu certains posts, je sais maintenant que cela provient de l'utilisation antérieure d'un scanf() qui laisse trainer un '\n' que récupère fgets();
Du coup je vide le buffer clavier avec cette instruction :

Code :
  1. int c;
  2. while ((c = getchar()) != '\n' && c != EOF);


Ca marche, seulement voilà, lorsque je veux afficher et enregistrer dans un fichier la chaine de caractères entrée par fgets(), elle fait sauter une ligne dans l'affichage et de même dans le fichier.
 
Y-a-t-il un moyen de remédier à cela ?


Si tu es l'auteur du "scanf" parasite, remplace-le par un "fgets" et tu n'auras plus aucun problème. D'ailleurs, ce "scanf" n'est pas n'importe quel scanf car le seul moment ou "scanf" laisse un "\n", c'est quand tu l'utilises pour faire saisir un nombre (à ce moment là, "scanf" s'arrête au premier caractère qui n'est pas "nombre" ). Donc t'as plusieurs solutions
1) tu remplaces TOUS les scanf par des "fgets". Et si tu dois faire saisir un nombre, tu fais d'abord un "fgets" dans une zone tampon puis ensuite un "sscanf" de la zone tampon vers ton nombre
ou alors
2) chaque fois que tu fais saisir un nombre par "scanf", tu fais ensuite un "getchar()" pour supprimer le "\n" résiduel
Personnellement, je préfère la "1".
 
 
 
Eh non. Ce qui est exceptionnel, c'est que tu ne cherches pas à comprendre le pourquoi du comment du C et que tu te contentes de critiquer sans réaliser que ceux qui ont écrit les choses avaient quand-même réfléchi bien avant toi...
En C, le char et le int sont quasiment pareil... ce ne sont que des nombres. Le char est un nombre codé sur 8 bit, le int est un nombre codé sur 16 bits. Donc leur seule différence sera la plage de valeurs qu'on peut coder. Avec un char on peut coder 256 valeurs de -128 à 127 en signé ou de 0 à 255 en non-signé; avec un int on peut coder 65536 valeurs de -32768 à 32767 en signé ou de 0 à 65535 en non-signé. Maintenant qu'on utilise un char ou un int pour coder le nombre "64" importe peu puisque les deux conviennent.
 
Maintenant la fonction "getchar". Son but est de renvoyer un caractère saisi au clavier, donc un caractère codé dans la plage des codes ascii (entre 0 et 255). Mais il faut que "getchar()" puisse renvoyer une valeur supplémentaire signifiant "j'ai rien lu" ou bien "le tampon stdin est vide". Donc getchar doit pouvoir coder au total une valeur supplémentaire ne faisant pas partie de la plage "[0-255]". Mais comme le char s'arrête justement à cette plage "[0-255], la fonction "getchar" ne peut pas être de type "char". C'est pourquoi, bien que dans 99,99% des cas la valeur renvoyée par "getchar" soit un char, cette fonction est de type "int". Et chaque fois qu'elle renverra un caractère saisi elle renverra une valeur de type "0x00nn" ("nn" étant le code ascii du caractère saisi)... jusqu'au moment où elle devra renvoyer "il n'y a plus rien" elle là, renverra la valeur "0xffff"

Message cité 1 fois
Message édité par Sve@r le 27-12-2006 à 22:41:01

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 27-12-2006 à 23:16:35    

Sve@r a écrit :


... le int est un nombre codé sur 16 bits...


Peut-être était-ce la norme au temps de Kernighan & Ritchie, mais il me semble que maintenant c'est 32 bits pour les int et 64 pour les long.

Reply

Marsh Posté le 27-12-2006 à 23:33:39    

apprentitux a écrit :

Peut-être était-ce la norme au temps de Kernighan & Ritchie, mais il me semble que maintenant c'est 32 bits pour les int et 64 pour les long.


Pour un int, la plage garantie par la norme est -32767 à + 32767. Evidemment, selon l'implémentation, ça peut être plus, mais pas moins.
 
 


---------------
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/
Reply

Marsh Posté le 27-12-2006 à 23:35:20    

HomerJK a écrit :

Y-a-t-il un moyen de remédier à cela ?


Oui, utiliser fgets() exclusivement et correctement.
 
http://mapage.noos.fr/emdel/notes.htm#saisie
http://mapage.noos.fr/emdel/notes.htm#fichier
 
 


---------------
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/
Reply

Marsh Posté le 27-12-2006 à 23:36:49    


Pas de Int en C. C'est int. C'est le type retourné par fgetc() et celui de EOF. C'est donc tout à fait adapté.
 
Tu voulais prouver que tu ne connaissais rien au C ? C'est réussi.
 


---------------
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/
Reply

Marsh Posté le 27-12-2006 à 23:36:49   

Reply

Marsh Posté le 28-12-2006 à 00:34:23    

Merci pour vos réponses !
Sve@r, personnellement je préfère la solution 2, parce que j'ai mis énormément de scanf pour les entiers, ca va être plus facile d'y remédier.
J'essaye ca et je vous en parle demain.

Reply

Marsh Posté le 28-12-2006 à 00:45:09    

HomerJK a écrit :

personnellement je préfère la solution 2, parce que j'ai mis énormément de scanf pour les entiers,


Grave erreur... scanf() n'est une fonction difficile à utiliser correctement...

 

http://xrenault.developpez.com/tutoriels/c/scanf/

 

Je recommande d'écrire une bonne fois pour toutes, une fonction de saisie pour les entiers, basée sur une fonction de saisie pour les lignes, basée sur fgets() ou fgetc().

 

http://mapage.noos.fr/emdel/inputs.htm

 

http://mapage.noos.fr/emdel/clib.htm
Module IO


Message édité par Emmanuel Delahaye le 28-12-2006 à 00:45:37

---------------
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/
Reply

Marsh Posté le 28-12-2006 à 02:25:58    

Emmanuel Delahaye a écrit :

Pas de Int en C. C'est int. C'est le type retourné par fgetc() et celui de EOF. C'est donc tout à fait adapté.
 
Tu voulais prouver que tu ne connaissais rien au C ? C'est réussi.


 
Voulez-vous le prototype de fgets ? Ca m'etonne de votre par Emmanuel

Message cité 2 fois
Message édité par Profil supprimé le 28-12-2006 à 02:29:17
Reply

Marsh Posté le 28-12-2006 à 02:39:08    

[:arrakys]  
Quel rapport ? Tu as fait une remarque sur un code contenant getchar(), c'est à dire fgetc(stdin). Donc je parle de fgetc(). Quel rapport avec fgets() ?
 
Rappel des faits :  

Code :
  1. int c;
  2.       while ((c = getchar()) != '\n' && c != EOF);


ce que tu as commenté ainsi :  
 
<<Moi je me ferai jamais au C, vous declarez des variable 'Int' et vous leur affectez des 'char', c'est exceptionnel tout de même.>>
 
Ce qui a fait réagir mon troll-o-meter, soit dit en passant...


Message édité par Emmanuel Delahaye le 28-12-2006 à 02:42:25

---------------
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/
Reply

Marsh Posté le 28-12-2006 à 02:45:52    

Bref, je me suis embrouillé entre lee prototype des fonction utilisé dans le code donné et les prototype des fonction utilisé dans le code à debuger. C'est vrai que c'est un langage surprenant  :pt1cable:
 
Mes excuses HomerJK, je t'ai un induit(e) en erreur, mea culpa.

Message cité 2 fois
Message édité par Profil supprimé le 28-12-2006 à 03:00:50
Reply

Marsh Posté le 28-12-2006 à 11:10:45    

HomerJK a écrit :

Sve@r, personnellement je préfère la solution 2, parce que j'ai mis énormément de scanf pour les entiers, ca va être plus facile d'y remédier.


T'es totalement libre de tes préférences. Mais le problème de "scanf" c'est que ça attend une entrée "formatée". Et, par définition, ce que tape le gogelu à qui on lui dit "entrez un chiffre" est tout sauf formaté et souvent tout sauf du chiffre. Donc la solution optimale est de tout accepter "en vrac" et de faire le tri ensuite. Ca permet au-moins d'avoir un tampon stdin toujours clean. Et c'est pas tellement difficile de transformer du scanf en fgets; même s'il y en a beaucoup
 
Exemple

int nb;
printf("Entrez un chiffre:" );
scanf("%d", &nb);


 
Solution 1

int nb;
char tampon[1024];
printf("Entrez un chiffre:" );
fgets(tampon, 1024, stdin);
sscanf(tampon, "%d", &nb);


 
Solution 2

int nb;
printf("Entrez un chiffre:" );
scanf("%d", &nb);
getchar();


 
Moi je ne choisirais pas une solution plutôt que l'autre par facilité d'écriture... mais plutôt par l'accroissement de sécurité qu'elle donne...


Message édité par Sve@r le 28-12-2006 à 11:15:52

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 11:55:06    


 
Ce qui est surprenant pour l'instant c'est ta stupidité.

Reply

Marsh Posté le 28-12-2006 à 16:36:37    

nyrk a écrit :

Ce qui est surprenant pour l'instant c'est ta stupidité.


Ben quand-même !!!
Il a reconnu son erreur et il s'est excusé. Moi je n'ai vu aucune stupidité dans ses propos... seulement de l'ignorance. Et, de mon point de vue, ce n'est absolument pas une tare. Mais peut-être que tu sais tout sur tout et que tu n'es donc pas de mon avis...
 
Voici quand-même la définition de "stupide" vue par Bernard Werber (tu devrais connaître si tu lis autre-chose que oui-oui au pays des jouets) :

Citation :

Stupide du latin "stupidus", signifie étonné, frappé de stupeur. Le stupide est celui qui s'étonne de tout. Il a conservé sa capacité d'émerveillement face à la nouveauté. Il est le contraire du blasé.

Message cité 1 fois
Message édité par Sve@r le 28-12-2006 à 16:38:56

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 17:13:45    

C'est bon j'ai réglé mon problème !  
J'ai donc mis getchar() après chaque scanf() (la solution la plus simple car j'ai énormément de scanf dans mon programme).
Mais la prochaine fois j'utiliserais une autre de vos méthodes, promis !
Merci beaucoup !

Reply

Marsh Posté le 28-12-2006 à 17:32:51    

HomerJK a écrit :

C'est bon j'ai réglé mon problème !


YES !!! J'étais en effet terriblement inquiet quand à la réussite de ton prog...

HomerJK a écrit :

Mais la prochaine fois j'utiliserais une autre de vos méthodes, promis !


Aujourd'hui encore, Emmanuel et moi pourrons nous coucher le coeur en paix en sachant que nous avons sauvé une âme de plus de la perdition. Devoir accompli...
http://www.smemoranda.it/files/esorcG_7053.jpg


Message édité par Sve@r le 28-12-2006 à 17:58:30

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 18:18:16    

HomerJK a écrit :

C'est bon j'ai réglé mon problème !  
J'ai donc mis getchar() après chaque scanf() (la solution la plus simple car j'ai énormément de scanf dans mon programme).
Mais la prochaine fois j'utiliserais une autre de vos méthodes, promis !
Merci beaucoup !


 
y'a que moi qui trouve cette solution hyper crade ? ca tient plus du bricolage que d'autre chose...

Reply

Marsh Posté le 28-12-2006 à 18:22:02    

Tamahome a écrit :

y'a que moi qui trouve cette solution hyper crade ? ca tient plus du bricolage que d'autre chose...


On a proposé autre chose, mais il se croit plus malin que nous, alors laisse tomber...
 


---------------
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/
Reply

Marsh Posté le 28-12-2006 à 18:29:02    

Tamahome a écrit :

y'a que moi qui trouve cette solution hyper crade ? ca tient plus du bricolage que d'autre chose...


Ce n'est pas vraiment "hyper" crade. Il a un "\n" parasite donc il l'enlève et c'est bon. C'est juste que ce getchar ne marche que s'il n'y a qu'un seul "\n" parasite. S'il y a autre chose (parce que l'utilisateur débile a tapé "azertuiop" là où on lui demandait un nombre) ça ne marche plus alors que l'autre solution à base de "fgets" marche encore. Je préfère aussi le "fgets()" et d'autres probablement aussi... mais chacun est (encore) libre de programmer comme il le sent.

Message cité 1 fois
Message édité par Sve@r le 28-12-2006 à 18:43:47

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 18:36:32    

Sve@r a écrit :

chacun est (encore) libre de programmer comme il le sent.

 

C'est pas de la liberté, c'est ne pas vouloir prendre suffisament de recul pour reconnaître que son code doit être revu.

 

J'ai un collègue qui code au copier-coller et qui crée des fonctions de 5000 lignes. Je lui ai dit de créer une fonction plutôt que de recopier un bout de code qu'il réutilise plusieurs fois (j'ai beaucoup réduit mes attentes sur sa qualité de code), mais c'est toujours si je ne passe pas pour un chieur.

 

Et au final, que ce soit un mois plus tard pour ajouter une fonctionnalité, ou trois ans après lorsque le code est repris, on se retrouve avec un taux de suicide anormalement haut pour la profession.
Donc si l'on envisage le taux considérable de dépressions nerveuses, j'estime que l'on a une responsabilité envers ses collègues et toute personne qui, un jour ou l'autre, lira notre code. Et comme je suis un bon citoyen et que j'aspire à réduire les dépenses de la sécurité sociale, je trouve inadmissible que l'on se permette encore de coder avec les pieds comme tout roumain schyzophrène dyslexique en camisole.

Message cité 1 fois
Message édité par Elmoricq le 28-12-2006 à 18:38:51
Reply

Marsh Posté le 28-12-2006 à 18:47:00    

Elmoricq a écrit :

C'est pas de la liberté, c'est ne pas vouloir prendre suffisament de recul pour reconnaître que son code doit être revu.
 
Donc si l'on envisage le taux considérable de dépressions nerveuses, j'estime que l'on a une responsabilité envers ses collègues et toute personne qui, un jour ou l'autre, lira notre code. Et comme je suis un bon citoyen et que j'aspire à réduire les dépenses de la sécurité sociale, je trouve inadmissible que l'on se permette encore de coder avec les pieds comme tout roumain schyzophrène dyslexique en camisole.


 
Totalement d'accord. J'aurais du être plus explicite et dire "chacun est encore libre de programmer comme il le sent à condition qu'il programme pour lui tout seul pour se faire plaisir ou bien pour faire un truc dont la durée de vie n'excède pas la demi-semaine".
Dans le cas où évidemment il oeuvre en communauté, sa liberté de programmeur s'arrête là où commence celle de celui qui va le relire...
 

Elmoricq a écrit :

J'ai un collègue qui code au copier-coller et qui crée des fonctions de 5000 lignes. Je lui ai dit de créer une fonction plutôt que de recopier un bout de code qu'il réutilise plusieurs fois (j'ai beaucoup réduit mes attentes sur sa qualité de code), mais c'est toujours si je ne passe pas pour un chieur.


J'ai connu ça aussi. Le type qui se gargarisait en disant "je code des millions de lignes de C par jour". Bon... ça passe et ça s'oublie...

Message cité 1 fois
Message édité par Sve@r le 28-12-2006 à 18:53:28

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 19:07:15    

Sve@r a écrit :

J'ai connu ça aussi. Le type qui se gargarisait en disant "je code des millions de lignes de C par jour". Bon... ça passe et ça s'oublie...


J'ai lu quelque part (je crois que c'est dans 'Tout sur le code' de Steve McConnell) qu'un programmeur sérieux écrivait 10 à 25 lignes de code testé par jour en moyenne...


---------------
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/
Reply

Marsh Posté le 28-12-2006 à 19:10:15    

Emmanuel Delahaye a écrit :

J'ai lu quelque part (je crois que c'est dans 'Tout sur le code' de Steve McConnell) qu'un programmeur sérieux écrivait 10 à 25 lignes de code testé par jour en moyenne...


Il n'y a aucune incohérence entre ton chiffre et le mien. Ce type ne m'as jamais dit qu'il était sérieux... ni que ses millions de lignes étaient testées. Il m'a juste dit qu'il les écrivait... :D


Message édité par Sve@r le 28-12-2006 à 19:11:01

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 19:37:10    


 
 
 
 
 

Sve@r a écrit :

Ben quand-même !!!
Il a reconnu son erreur et il s'est excusé. Moi je n'ai vu aucune stupidité dans ses propos... seulement de l'ignorance. Et, de mon point de vue, ce n'est absolument pas une tare. Mais peut-être que tu sais tout sur tout et que tu n'es donc pas de mon avis...
 
Voici quand-même la définition de "stupide" vue par Bernard Werber (tu devrais connaître si tu lis autre-chose que oui-oui au pays des jouets) :

Citation :

Stupide du latin "stupidus", signifie étonné, frappé de stupeur. Le stupide est celui qui s'étonne de tout. Il a conservé sa capacité d'émerveillement face à la nouveauté. Il est le contraire du blasé.



 
C'est marrant, cette définition me semble coller à ce que disait jovalise. ;)
 
Pour ce qui est de Bernard Werber, c'est de la sous S.-F. qui convient bien aux jeunes gens qui veulent passer au stade immédiatement supérieur à "Oui-oui".

Reply

Marsh Posté le 28-12-2006 à 20:28:37    

Sve@r a écrit :

Ce n'est pas vraiment "hyper" crade. Il a un "\n" parasite donc il l'enlève et c'est bon.


 
La tu soignes les symptomes, pas la maladie...

Reply

Marsh Posté le 28-12-2006 à 20:46:56    

Tamahome a écrit :

La tu soignes les symptomes, pas la maladie...


Ben parfois, si t'as mal à la tête tu prends une aspirine sans chercher plus loin. Si ton mal de tête est récurrent, là tu peux commencer à voir plus loin.
 
Pour son pb, Emmanuel et moi lui avons expliqué la cause du problème et les différentes façons de le résoudre, avec les avantages et inconvénients de chacune des façons. Apparemment HomerJK a bien compris. Maintenant si "soigner le symptôme" lui convient et que son programme qu'il écrit pour se faire plaisir pour lui tout seul fonctionne comme ça, pourquoi aller plus loin ?
 
PS: T'es plus "lt-commander Data" ??? Je ne connais pas "Pilote Gundam" bien que je connaisse un bouquin de P-J Hérault nommé "Pilote Gurvan"...

Message cité 1 fois
Message édité par Sve@r le 28-12-2006 à 20:54:40

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 28-12-2006 à 21:46:32    

Sve@r a écrit :

PS: T'es plus "lt-commander Data" ??? Je ne connais pas "Pilote Gundam" bien que je connaisse un bouquin de P-J Hérault nommé "Pilote Gurvan"...


 
aucun rapport :p  
 
http://www.gundam.jp/

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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