Je viens de passer douze heures en vain à comprendre un bug concernant la
saisie d'un float avec fgets et sscanf. Voici le code et un exemple
d'execution. Je pourrais perfectionner ma saisie en m'inspirant de l'exemple
donné par E. Delahaye dans la faq, mais j'aimerais comprendre le
comportement de ma programme.
5 * Saisie des notes obtenues par un patineur et affichage de sa moyenne
6 *
7 */
8
9
10 #include <stdio.h>
11 #include <stdlib.h>
12
13 #define NB_JUGES 5
14 #define NOTE_MIN 1.0
15 #define NOTE_MAX 6.0
16
17
18 int
19 main (void)
20 {
21 float somme = 0;
22 float moyenne;
23 float note;
24 char saisie[5];
25 int i;
26
27 printf ("\n---------- Saisie des notes du patineur ---------\n\n\n");
28 for (i = 0; i < NB_JUGES; i++)
29 {
30 while (1)
31 {
32 printf ("Note du juge no.%d: ", i + 1);
33 if (fgets (saisie, sizeof(saisie), stdin) == NULL)
34 {
35 fprintf (stderr, "Fin de fichier inattendu \n");
36 return (1);
37 }
38 if (sscanf (saisie, "%f", ¬e) != 1)
39 printf ("\nErreur, un nombre svp\n");
40 else
41 {
42 if ((note >= NOTE_MIN) && (note <= NOTE_MAX))
43 break;
44 printf ("\nErreur, un nombre entre %.2f et %.2f svp\n",
45 NOTE_MIN, NOTE_MAX);
46 }
47 printf ("debug: note = %f\n\n", note);
48 }
49 somme += note;
50 }
51 moyenne = somme / NB_JUGES;
52 printf ("\nMoyenne du patineur: %.2f\n\n", moyenne);
53 return EXIT_SUCCESS;
54 }
55
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
MagicalTux
Le Fri, 13 Jan 2006 20:14:07 +0100, Eric Guirbal a écrit :
Bonjour,
Je viens de passer douze heures en vain à comprendre un bug concernant la saisie d'un float avec fgets et sscanf. Voici le code et un exemple d'execution. Je pourrais perfectionner ma saisie en m'inspirant de l'exemple donné par E. Delahaye dans la faq, mais j'aimerais comprendre le comportement de ma programme.
Le bug est simple, et est lié a la taille du buffer de saisi.
Supposont la note 2.4682. Notre buffer fait 5 de taille. On peut donc y faire entrer "2.46 " (ne jamais oublier le final). Toutefois il reste 82 dans le "buffer" système. Cette valeur est obtenue a l'appel suivant de fgets().
La solution : augmenter saisie[5] a une valeur un peu plus grande.
-- MagicalTux - Developpement PHP, C et un peu de tout http://ookoo.org/
Le Fri, 13 Jan 2006 20:14:07 +0100, Eric Guirbal a écrit :
Bonjour,
Je viens de passer douze heures en vain à comprendre un bug concernant la
saisie d'un float avec fgets et sscanf. Voici le code et un exemple
d'execution. Je pourrais perfectionner ma saisie en m'inspirant de l'exemple
donné par E. Delahaye dans la faq, mais j'aimerais comprendre le
comportement de ma programme.
Le bug est simple, et est lié a la taille du buffer de saisi.
Supposont la note 2.4682. Notre buffer fait 5 de taille. On peut donc y
faire entrer "2.46 " (ne jamais oublier le final). Toutefois il reste
82 dans le "buffer" système. Cette valeur est obtenue a l'appel suivant
de fgets().
La solution : augmenter saisie[5] a une valeur un peu plus grande.
--
MagicalTux - Developpement PHP, C et un peu de tout
http://ookoo.org/
Le Fri, 13 Jan 2006 20:14:07 +0100, Eric Guirbal a écrit :
Bonjour,
Je viens de passer douze heures en vain à comprendre un bug concernant la saisie d'un float avec fgets et sscanf. Voici le code et un exemple d'execution. Je pourrais perfectionner ma saisie en m'inspirant de l'exemple donné par E. Delahaye dans la faq, mais j'aimerais comprendre le comportement de ma programme.
Le bug est simple, et est lié a la taille du buffer de saisi.
Supposont la note 2.4682. Notre buffer fait 5 de taille. On peut donc y faire entrer "2.46 " (ne jamais oublier le final). Toutefois il reste 82 dans le "buffer" système. Cette valeur est obtenue a l'appel suivant de fgets().
La solution : augmenter saisie[5] a une valeur un peu plus grande.
-- MagicalTux - Developpement PHP, C et un peu de tout http://ookoo.org/
Emmanuel Delahaye
Je viens de passer douze heures en vain à comprendre un bug concernant la saisie d'un float avec fgets et sscanf. Voici le code et un exemple d'execution. Je pourrais perfectionner ma saisie en m'inspirant de l'exemple donné par E. Delahaye dans la faq, mais j'aimerais comprendre le comportement de ma programme.
33 if (fgets (saisie, sizeof(saisie), stdin) == NULL) Pour saisir
9.99<enter>
soit
{'9','.','9','9','n',0}
il faut 6 caractères. Si il n'y a la place qur pour 5, fgets() va laisser le 'n'. Comme tu ne le testes pas, le prochain appel de fgets() ne sera pas blocant...
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK.
-- A+
Emmanuel Delahaye
Je viens de passer douze heures en vain à comprendre un bug concernant la
saisie d'un float avec fgets et sscanf. Voici le code et un exemple
d'execution. Je pourrais perfectionner ma saisie en m'inspirant de l'exemple
donné par E. Delahaye dans la faq, mais j'aimerais comprendre le
comportement de ma programme.
33 if (fgets (saisie, sizeof(saisie), stdin) == NULL)
Pour saisir
9.99<enter>
soit
{'9','.','9','9','n',0}
il faut 6 caractères. Si il n'y a la place qur pour 5, fgets() va
laisser le 'n'. Comme tu ne le testes pas, le prochain appel de fgets()
ne sera pas blocant...
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK.
Je viens de passer douze heures en vain à comprendre un bug concernant la saisie d'un float avec fgets et sscanf. Voici le code et un exemple d'execution. Je pourrais perfectionner ma saisie en m'inspirant de l'exemple donné par E. Delahaye dans la faq, mais j'aimerais comprendre le comportement de ma programme.
33 if (fgets (saisie, sizeof(saisie), stdin) == NULL) Pour saisir
9.99<enter>
soit
{'9','.','9','9','n',0}
il faut 6 caractères. Si il n'y a la place qur pour 5, fgets() va laisser le 'n'. Comme tu ne le testes pas, le prochain appel de fgets() ne sera pas blocant...
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK.
-- A+
Emmanuel Delahaye
Guillaume R.
Salut
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK J'ai souvent ce problème aussi, y'a til un moyen d'allouer
dynamiquement l'espace dont j'ai ou peux avoir besoin pour une chaine donnée? Par exemple la même s'il met 16 un ptit malin pourra toujours bloquer le prog en saisissant 20 caractères par exemple. Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
Salut
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK
J'ai souvent ce problème aussi, y'a til un moyen d'allouer
dynamiquement l'espace dont j'ai ou peux avoir besoin pour une chaine
donnée?
Par exemple la même s'il met 16 un ptit malin pourra toujours bloquer
le prog en saisissant 20 caractères par exemple.
Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK J'ai souvent ce problème aussi, y'a til un moyen d'allouer
dynamiquement l'espace dont j'ai ou peux avoir besoin pour une chaine donnée? Par exemple la même s'il met 16 un ptit malin pourra toujours bloquer le prog en saisissant 20 caractères par exemple. Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
Harpo
Guillaume R. wrote:
Salut
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK J'ai souvent ce probl
Guillaume R. wrote:
Salut
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK
J'ai souvent ce probl
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK J'ai souvent ce probl
Emmanuel Delahaye
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK
J'ai souvent ce probl�me aussi, y'a til un moyen d'allouer dynamiquement l'espace dont j'ai ou peux avoir besoin pour une chaine donn�e?
Ben oui. malloc()... n
Par exemple la m�me s'il met 16 un ptit malin pourra toujours bloquer le prog en saisissant 20 caract�res par exemple.
Il ne va rien bloquer si le programmeur lit les conseils d'utilisation que j'ai donné dans articles dont j'ai fourni les liens.
Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
On peut écrire une fonction de saisie qui alloue/réalloue dynamiquement ce qu'il faut. Il faut écrire un petit algo qui évite de réallouer à chaque caractère (disons, pas doublage... on commence par 8, puis on agrandit à 16, 32 etc. selon les besoins...). C'est un exercice 'semi-avancé' courant en C... En plus, on se retrouve avec une fonction de saisie solide et souple, ce qui est *très* pratique (penser à libérer le bloc après usage, bien sûr, on est pas des brutes...)
Genre :
char *getline_dyn(void);
Le suffixe '_dyn' est un aide mémoire : penser à libérer le bloc...
-- A+
Emmanuel Delahaye
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK
J'ai souvent ce probl�me aussi, y'a til un moyen d'allouer
dynamiquement l'espace dont j'ai ou peux avoir besoin pour une chaine
donn�e?
Ben oui. malloc()... n
Par exemple la m�me s'il met 16 un ptit malin pourra toujours bloquer
le prog en saisissant 20 caract�res par exemple.
Il ne va rien bloquer si le programmeur lit les conseils d'utilisation
que j'ai donné dans articles dont j'ai fourni les liens.
Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
On peut écrire une fonction de saisie qui alloue/réalloue dynamiquement
ce qu'il faut. Il faut écrire un petit algo qui évite de réallouer à
chaque caractère (disons, pas doublage... on commence par 8, puis on
agrandit à 16, 32 etc. selon les besoins...). C'est un exercice
'semi-avancé' courant en C... En plus, on se retrouve avec une fonction
de saisie solide et souple, ce qui est *très* pratique (penser à libérer
le bloc après usage, bien sûr, on est pas des brutes...)
Genre :
char *getline_dyn(void);
Le suffixe '_dyn' est un aide mémoire : penser à libérer le bloc...
Pourquoi est-tu si radin ? Met 8 ou 16 char et c'est OK
J'ai souvent ce probl�me aussi, y'a til un moyen d'allouer dynamiquement l'espace dont j'ai ou peux avoir besoin pour une chaine donn�e?
Ben oui. malloc()... n
Par exemple la m�me s'il met 16 un ptit malin pourra toujours bloquer le prog en saisissant 20 caract�res par exemple.
Il ne va rien bloquer si le programmeur lit les conseils d'utilisation que j'ai donné dans articles dont j'ai fourni les liens.
Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
On peut écrire une fonction de saisie qui alloue/réalloue dynamiquement ce qu'il faut. Il faut écrire un petit algo qui évite de réallouer à chaque caractère (disons, pas doublage... on commence par 8, puis on agrandit à 16, 32 etc. selon les besoins...). C'est un exercice 'semi-avancé' courant en C... En plus, on se retrouve avec une fonction de saisie solide et souple, ce qui est *très* pratique (penser à libérer le bloc après usage, bien sûr, on est pas des brutes...)
Genre :
char *getline_dyn(void);
Le suffixe '_dyn' est un aide mémoire : penser à libérer le bloc...
-- A+
Emmanuel Delahaye
Harpo
Emmanuel Delahaye wrote:
Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
On peut écrire une fonction de saisie qui alloue/réalloue dynamiquement ce qu'il faut. Il faut écrire un petit algo qui évite de réallouer à chaque caractère (disons, pas doublage... on commence par 8, puis on agrandit à 16, 32 etc. selon les besoins...).
C'est petit de commencer à moins de 256.
C'est un exercice 'semi-avancé' courant en C... En plus, on se retrouve avec une fonction de saisie solide et souple, ce qui est *très* pratique (penser à libérer le bloc après usage, bien sûr, on est pas des brutes...)
Je préfère utiliser une bibliothèque comme GNU Getline, l'utilisateur peut utiliser les touches up et down pour accéder à l'historique de ce qu'il a déjà entré et aussi plein de choses fournies par la bibliothèque. En plus, ça marchait bien depuis longtemps à la fin du millénaire dernier.
Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
On peut écrire une fonction de saisie qui alloue/réalloue
dynamiquement ce qu'il faut. Il faut écrire un petit algo qui évite de
réallouer à chaque caractère (disons, pas doublage... on commence par
8, puis on agrandit à 16, 32 etc. selon les besoins...).
C'est petit de commencer à moins de 256.
C'est un
exercice 'semi-avancé' courant en C... En plus, on se retrouve avec
une fonction de saisie solide et souple, ce qui est *très* pratique
(penser à libérer le bloc après usage, bien sûr, on est pas des
brutes...)
Je préfère utiliser une bibliothèque comme GNU Getline, l'utilisateur
peut utiliser les touches up et down pour accéder à l'historique de ce
qu'il a déjà entré et aussi plein de choses fournies par la
bibliothèque.
En plus, ça marchait bien depuis longtemps à la fin du millénaire
dernier.
Y'a t-il une solution pour allouer dynamiquement ces espaces en C?
On peut écrire une fonction de saisie qui alloue/réalloue dynamiquement ce qu'il faut. Il faut écrire un petit algo qui évite de réallouer à chaque caractère (disons, pas doublage... on commence par 8, puis on agrandit à 16, 32 etc. selon les besoins...).
C'est petit de commencer à moins de 256.
C'est un exercice 'semi-avancé' courant en C... En plus, on se retrouve avec une fonction de saisie solide et souple, ce qui est *très* pratique (penser à libérer le bloc après usage, bien sûr, on est pas des brutes...)
Je préfère utiliser une bibliothèque comme GNU Getline, l'utilisateur peut utiliser les touches up et down pour accéder à l'historique de ce qu'il a déjà entré et aussi plein de choses fournies par la bibliothèque. En plus, ça marchait bien depuis longtemps à la fin du millénaire dernier.