Répondre à la discussion
Affichage des résultats 1 à 20 sur 20

[C] Utilisation de fgets



  1. #1
    dj_titeuf

    Question [C] Utilisation de fgets


    ------

    Bonsoir,

    Je ne comprends pas bien l'utilisation de la fonction fgets.

    Considérons tout d'abord le code suivant:

    Code:
    int main(void)
    
    {
    
    	int nombre = 0;
    	char stockage[10];
    
    	while (nombre != 1)
    
    	{
    
    		printf("Tapez 1 pour quitter: \n");
    		scanf("%d", &nombre);
    
    	}
    
    	return 0;
    
    }
    L'inconvénient avec ce code, c'est que lorsque l'utilisateur tape autre chose qu'un nombre (une lettre par exemple), on rentre dans une boucle infinie.. Il semblerait que l'utilisation de la fonction fgets puisse résoudre le problème:

    Code:
    int main(void)
    
    {
    
    	int nombre = 0;
    	char stockage[10];
    
    	while (nombre != 1)
    
    	{
    
    		printf("Tapez 1 pour quitter.\n");
    		fgets(stockage, 10, stdin);
    
    	}
    
    	return 0;
    
    }
    Malheureusement, ceci ne fonctionne pas... Ce serait trop simple!
    Pouvez-vous m'expliquer comment faire svp? Déjà, je ne vois pas comment faire "rentrer" dans la variable nombre la valeur lue par fgets..

    Merci d'avance!

    -----
    La différence entre le génie et la bêtise, c'est que le génie a des limites. [Byrne]

  2. Publicité
  3. #2
    univscien

    Re : [C] Utilisation de fgets

    fget c'est pour lire dans un fichier. Ton code ne risque donc pas de marcher ^^
    68 74 74 70 3A 2F 2F 77 77 77 2E 6A 65 72 72 6F 72 34 30 34 2E 66 72

  4. #3
    dj_titeuf

    Re : [C] Utilisation de fgets

    Dans ce cas, as-tu une solution à proposer?

    Au passage, j'ai lu la page suivante: http://c.developpez.com/faq/index.ph...scanf_vs_fgets... mais je suis loin de tout comprendre, c'est juste vu qu'il était conseillé d'utiliser fgets au lieu de scanf...J'attends vos précisions!
    La différence entre le génie et la bêtise, c'est que le génie a des limites. [Byrne]

  5. #4
    univscien

    Re : [C] Utilisation de fgets

    J'ai peu être parlé trop vite, désolé. (jsuis plus C++ moi )
    Ton code marche très bien chez moi, en fait fget va stocker dans ta variable la sortie standard (stdin), donc ce que tu aura tapé.
    68 74 74 70 3A 2F 2F 77 77 77 2E 6A 65 72 72 6F 72 34 30 34 2E 66 72

  6. A voir en vidéo sur Futura
  7. #5
    SuperTux

    Re : [C] Utilisation de fgets

    Salut,

    Tu peux convertir ta chaine de caractère en int avec la fonction atoi (qui est un "racourcie" de la fonction strtol) de la bibliothèque standard <stdlib.h>. Cela donne donc tout betement :
    Code:
    nombre = atoi(stockage);
    cf: http://www.linux-kheops.com/doc/man/...n3/atoi.3.html
    http://www.linux-kheops.com/doc/man/.../strtol.3.html

  8. #6
    dj_titeuf

    Re : [C] Utilisation de fgets

    Citation Envoyé par univscien Voir le message
    J'ai peu être parlé trop vite, désolé. (jsuis plus C++ moi )
    Ton code marche très bien chez moi, en fait fget va stocker dans ta variable la sortie standard (stdin), donc ce que tu aura tapé.
    Le deuxième code fonctionne?? Quand tu tapes 1, il se termine??
    La différence entre le génie et la bêtise, c'est que le génie a des limites. [Byrne]

  9. Publicité
  10. #7
    univscien

    Re : [C] Utilisation de fgets

    Oui il se termine. Je compile avec g++
    68 74 74 70 3A 2F 2F 77 77 77 2E 6A 65 72 72 6F 72 34 30 34 2E 66 72

  11. #8
    dj_titeuf

    Re : [C] Utilisation de fgets

    Perso, je compile avec Visual C++ 2008, et pas moyen de sortir de la boucle en tapant 1.. Vois-tu d'où peut venir le problème?

    D'un autre côté, il y a quelque chose qui m'échappe dans mon code!
    Je déclare la variable nombre mais... je ne l'utilise pas dirait-on! Car en effet, lorsque je tape quelque chose au clavier quand c'est demandé, ce n'est pas "nombre" qui récupère la donnée me semble-t-il, d'où mon problème non? Je ne sais pas si je suis clair ...
    La différence entre le génie et la bêtise, c'est que le génie a des limites. [Byrne]

  12. #9
    Towl

    Re : [C] Utilisation de fgets

    Ton premier code ne vide pas stdin après lecture non réussie, donc il reprend ou il en était. En effet, la lecture de scanf n'avance que si elle a réussie (et donc lue un entier). Dans le cas contraire, elle reprend ou elle était avant l'erreur.
    Un code corrigeant cela :
    Code:
    int main(void)
    {
    	int nombre = 0;
    	char stockage[10];
    
    	while (nombre != 1)
    	{
    		printf("Tapez 1 pour quitter: \n");
    		if (scanf("%d", &nombre) == 0)
                            /* boucle qui lit un caractère mais ne le stocke pas jusqu'a vider stdin */
                             while(fgetc(stdin)!=EOF); 
    	}
    	return 0;
    }
    Concernant ton second code, il faut bien convertir ta chaine de caractère en entier, et faire attention : stockage à une taille de 10, et peut donc contenir 9 caractères et le caractère de fin de chaine (9 + '\0' = 10 caractères). Et pense à tester tes valeurs de retour

    Code:
    int main(void)
    
    {
    	int nombre = 0;
    	char stockage[10];
    
    	while (nombre != 1)
    	{
    		printf("Tapez 1 pour quitter.\n");
    		if (fgets(stockage, 9, stdin) == NULL)
                                printf("Erreur de lecture\n");
                    nombre = atoi(stockage);
    	}
    	return 0;
    }
    The only limiting factor of the Linux operating system, is his user. - Linus Torvalds

  13. #10
    univscien

    Re : [C] Utilisation de fgets

    Citation Envoyé par dj_titeuf Voir le message
    Je déclare la variable nombre mais... je ne l'utilise pas dirait-on!
    Je pensais que ton problème avec le second code était le méme que le premier (boucle infini quand on tape une lettre). Donc effectivement, pour sortir de la boucle il faut bien stocker la valeur entré dans nombre ^^
    68 74 74 70 3A 2F 2F 77 77 77 2E 6A 65 72 72 6F 72 34 30 34 2E 66 72

  14. #11
    dj_titeuf

    Re : [C] Utilisation de fgets

    Citation Envoyé par Towl
    Concernant ton second code, il faut bien convertir ta chaine de caractère en entier, et faire attention : stockage à une taille de 10, et peut donc contenir 9 caractères et le caractère de fin de chaine (9 + '\0' = 10 caractères). Et pense à tester tes valeurs de retour
    Merci, mais je en comprends pas bien ce que le if fait réellement... De plus, dans quel cas "Erreur de lecture" apparaîtra à l'écran?
    La différence entre le génie et la bêtise, c'est que le génie a des limites. [Byrne]

  15. #12
    univscien

    Re : [C] Utilisation de fgets

    fgets retour un pointeur vers un char. Donc si ce pointeur ne pointe vers rien (il est NULL), la condition est remplie (je pense que c'est quand tu ne rentre rien).
    68 74 74 70 3A 2F 2F 77 77 77 2E 6A 65 72 72 6F 72 34 30 34 2E 66 72

  16. Publicité
  17. #13
    Towl

    Re : [C] Utilisation de fgets

    Une citation de la page de manuel de fgets (man fgets):
    char *fgets (char *s, int size, FILE *stream);
    [...]
    gets() et fgets() renvoient le pointeur s si elles
    réussissent, et NULL en cas d'erreur, ou si la fin de
    fichier est atteinte avant d'avoir pu lire au moins un
    caractère.
    Donc cela sert pour toute erreur : fin de fichier (Ctrl+D sous linux pour "fermer" stdin par exemple), fichier supprimé en cours de lecture, ...
    The only limiting factor of the Linux operating system, is his user. - Linus Torvalds

  18. #14
    SuperTux

    Re : [C] Utilisation de fgets

    Citation Envoyé par Towl
    Concernant ton second code, il faut bien convertir ta chaine de caractère en entier, et faire attention : stockage à une taille de 10, et peut donc contenir 9 caractères et le caractère de fin de chaine (9 + '\0' = 10 caractères).
    Code:
    if (fgets(stockage, 9, stdin) == NULL)
    Humm, je ne crois pas :

    fgets() lit au plus size - 1 caractères depuis stream et les place dans le tampon pointé par s. [...] Un octet nul « \0 » est placé à la fin de la ligne.
    (manpage de ma fedora)

  19. #15
    Towl

    Re : [C] Utilisation de fgets

    Exact.. C'est la que l'on apprécie toute la saveur du C et du traitement de chaines de caractères j'ai confondu le comportement de fgets et fgetln, l'une renvoyant une chaine de caractère C, terminée par un '\0', et l'autre non.

    D'ou l'importance de faire un man avant chaque fonction de traitement de chaines de caractères

    L'extrait du man de fgetln
    char *
    fgetln(FILE *stream, size_t *len);

    DESCRIPTION
    The fgetln() function returns a pointer to the next line from the stream
    referenced by stream. This line is not a C string as it does not end
    with a terminating NUL character. The length of the line, including the
    final newline, is stored in the memory location to which len points and
    is guaranteed to be greater than 0 upon successful completion. (Note,
    however, that if the last line in the stream does not end in a newline,
    the returned text will not contain a newline.)
    The only limiting factor of the Linux operating system, is his user. - Linus Torvalds

  20. #16
    dj_titeuf

    Re : [C] Utilisation de fgets

    Du coup, qu'est-ce que cela change?

    D'autre part, si vous le permettez, j'aurais une autre question à vous poser concernant un autre code:

    Code:
       1. #include<stdio.h>
       2.
       3. double calculAire(double longueur, double largeur)
       4. {
       5. return longueur*largeur;
       6. }
       7.
       8. int main(int argc, char *argv[])
       9. {
      10.
      11.
      12. double laLongueur, laLargeur;
      13. double aire;
      14.
      15.
      16. printf("Quelle est la longueur du rectangle svp?\n" );
      17. scanf("%f",&laLongueur);
      18. printf("Quelle est la largeur du rectangle svp?\n" );
      19. scanf("%f",&laLargeur);
      20.
      21. aire = calculAire(laLongueur,laLargeur);
      22.
      23. printf("L'aire de votre rectangle est de %f.\n",aire);
      24.
      25. return 0;
      26. }
    C'est un programme tout simple, qui est censé retourner l'aire d'un rectangle à partir de ses dimensions. Or, ça me retourne 0... Comment cela se fait-il?
    La différence entre le génie et la bêtise, c'est que le génie a des limites. [Byrne]

  21. #17
    univscien

    Re : [C] Utilisation de fgets

    En remplaçant les %f par %ld ?
    68 74 74 70 3A 2F 2F 77 77 77 2E 6A 65 72 72 6F 72 34 30 34 2E 66 72

  22. #18
    Towl

    Re : [C] Utilisation de fgets

    Du coup, qu'est-ce que cela change?
    qu'a la place d'un 9, tu peux mettre un 10 dans
    Code:
    if (fgets(stockage, 9, stdin) == NULL)
    Le test sur la valeur de retour est quand à lui toujours nécessaire.


    Sinon, tu as un soucis d'un coté, tu lis des float ("%f") de l'autre tu as un pointeur sur un double (&LaLongueur). Or tu ne peux pas faire de casting à l'arrache comme sur les int / long / char, donc tu vas obtenir un résultat aléatoire, dépendant du compilateur etc. De mon coté, j'obtiens un joli Not A Number

    Pour corriger cela, passe plutot un "%lf" qui indique un double :
    l (ell) Indicates either that the conversion will be one of dioux
    or n and the next pointer is a pointer to a long int
    (rather than int), or that the conversion will be one of
    efg and the next pointer is a pointer to double (rather
    than float).

    f Matches an optionally signed floating-point number; the next point-
    er must be a pointer to float.

    Edit :
    Citation Envoyé par univscien Voir le message
    En remplaçant les %f par %ld ?
    un %ld te donnera juste un long int et non un double:
    d Matches an optionally signed decimal integer; the next pointer must
    be a pointer to int.

    l (ell) Indicates either that the conversion will be one of dioux
    or n and the next pointer is a pointer to a long int
    (rather than int), or that the conversion will be one of
    efg and the next pointer is a pointer to double (rather
    than float).
    Dernière modification par Towl ; 25/07/2009 à 19h49.
    The only limiting factor of the Linux operating system, is his user. - Linus Torvalds

  23. Publicité
  24. #19
    dj_titeuf

    Re : [C] Utilisation de fgets

    Merci pour ces précisions!

    Par contre, concernant le %lf, je ne saisis pas trop... Lorsqu'on a affaire à une variable de type int, on utilise %d pour un printf, ainsi que pour scanf. Lorsqu'il s'agit d'une variable de type double, on utilise %f pour printf mais... pourquoi est-ce alors %lf pour scanf et non %f aussi??
    La différence entre le génie et la bêtise, c'est que le génie a des limites. [Byrne]

  25. #20
    Towl

    Re : [C] Utilisation de fgets

    %f c'est pour les float et non les doubles. Un double et un float sont relativement différent d'un point de vue représentation mémoire, il n'y a pas juste que la taille qui change. Il n'est donc pas possible de lire un double avec un float (et inversement). Et si tu regarde dans les pages de manuels, l'option l permet de définir un double quand elle est en préfixe d'un f. D'ou :
    - %f --> float
    - %lf --> double
    The only limiting factor of the Linux operating system, is his user. - Linus Torvalds

Discussions similaires

  1. utilisation voltmetre
    Par mathier dans le forum Électronique
    Réponses: 1
    Dernier message: 15/11/2008, 23h01
  2. Langage C / fgets
    Par lui dans le forum Logiciel - Software - Open Source
    Réponses: 5
    Dernier message: 13/05/2007, 23h41
  3. Utilisation Transformateur
    Par Olivier_34 dans le forum Électronique
    Réponses: 2
    Dernier message: 21/04/2007, 16h44
  4. Ti 89: utilisation
    Par Amethyste dans le forum Logiciel - Software - Open Source
    Réponses: 1
    Dernier message: 26/03/2006, 16h25
  5. utilisation de netbeans 5.0
    Par sylvain45 dans le forum Logiciel - Software - Open Source
    Réponses: 2
    Dernier message: 22/03/2006, 01h55
Découvrez nos comparatifs produits sur l'informatique et les technologies.