Forum Programmation.c scanf didju.

Posté par  .
Étiquettes : aucune
0
28
mai
2006
Bonjour,


Voila j'expose mon problème lors d'un programme je demande a l'utilisateur si oui ou non il désire continuer. Mais voila, le programme passe le scanf. J'ai donc retirer la demande juste avant (faite avec un scanf aussi) et la , ho miracle le deuxième scanf fonctionne. Donc en claire mon problème est que je peut utilisé que une seul fois scanf dans mes programmes car sinon les autres sont ignoré. Pour palier a ce problème sous windows un fflush(stdin) suffisait et bien ici que neni. Cela ne va pas.

Quelqu'un peut-il m'aider?
  • # code ?

    Posté par  (site web personnel) . Évalué à 1.

    Tu as un exemple de code minimaliste reproduisant le problème ? Parceque, pour ma part, je n'ai jamais eu ce genre de problème avec scanf.
    • [^] # Re: code ?

      Posté par  . Évalué à 1.

      exemple :

      #include <stdlib.h>
      #include<stdio.h>

      int main() {

      int i;
      scanf("%d",&i);
      scanf("%*c");
      scanf("%d",&i);

      }


      il prend bien le 1er scanf, mais après il passe les autres
      • [^] # Re: code ?

        Posté par  . Évalué à 1.

        certainement pas. regarde le retour de scanf et le contenu de tes variables selon.
      • [^] # Re: code ?

        Posté par  (site web personnel) . Évalué à 1.

        En tout cas, chez moi, le comportement est le suivant :

        - il attend
        - je saisis un nombre -> i est valué
        - le second scanf consomme le retour à la ligne (code ascii 10) sans assignation
        - il attend
        - je saisis un second nombre -> i est re-valué

        Ce n'est pas le comportement attendu ?
      • [^] # Re: code ?

        Posté par  . Évalué à 1.

        Le scanf sous bsd aurait un comportement différent ?

        Euh, ça veut dire quoi scanf("%*c"); sinon ?

        Je pose ces questions aussi parce que, des fois qu'elles contiendraient un début de réponse...
        • [^] # Re: code ?

          Posté par  (site web personnel) . Évalué à 1.

          le * supprime l'assignation, c'est pour ça que tu n'as pas d'argument après.

          Pour plus de détails : man scanf ;o)
  • # fgets + sscanf

    Posté par  . Évalué à 3.

    Bonjour,

    Ce problème est bien connu en C.
    Il est pratiquement toujours rencontré ce fameux buffer.

    Il y a une façon de faire qui permet de bien contrôler les entrées. Et ainsi d'éviter des problèmes avec le buffer.
    La combinaison des fonctions fgets et sscanf :
    fgets (char * s, int size, FILE * stream)
    sscanf (const char * str, const char * format, ...)

    On lit sur l'entrée standard et on place la chaîne dans une variable.

    fgets(buffer, sizeof(buffer), stdin);


    On scanne cette variable en fonction du résultat souhaité (si il doit être une chaîne, entier, caractère, ...).
    Et on stocke celle ci dans la variable de destination.

    sscanf(buffer, "%s", &vardest);

    Je ne sais pas si c'est la meilleure façon de faire ...
    Mais cela permet d'avoir un bon contrôle sur les dépassements de buffer etc ...
    • [^] # Re: fgets + sscanf

      Posté par  . Évalué à 0.

      Je ne sais pas si c'est la meilleure façon de faire ...

      Si. Enfin, presque: la meilleure façon de le faire, c'est d'utiliser une fonction spécifique qui encapsule le fgets car, comme je l'ai dit ici ( http://linuxfr.org/comments/713347.html#713347 ), son utilisation n'est pas triviale. http://cbfalconer.home.att.net/download/index.htm propose une fonction fggets simple d'utilisation qui prend une ligne entière d'un flux pour la mettre dans une zone allouée avec un *alloc.
      Pour traiter la chaîne "brute" ainsi récupérée, il faut ensuite utiliser des fonctions comme sscanf ou strto*, suivant les besoins, en vérifiant les conditions d'erreur.
  • # Vieux souvenirs....

    Posté par  (site web personnel) . Évalué à 1.

    Il me semble (mais ça fait longtemps) avoir eu le même problême il y a quelques années, et je résolvais le problème en vidant les buffers (je crois qu'un printf("\n"); faisait l'affaire). Mais je peux me tromper.

    Mais sinon comme dit au dessus, scanf est à bannir de toutes les façons (buffer overflows, backspace mal géré...).
    • [^] # Re: Vieux souvenirs....

      Posté par  . Évalué à 1.

      je crois qu'un printf("\n"); faisait l'affaire

      printf("\n") ne fait que vider le buffer du flux stdout (une implémentation pourrait profiter de ce moment pour vider les tampons d'autres flux sortants en même temps, pour optimiser les accès I/O, mais c'est aléatoire). Le flux stdin ne peut être "vidé" ainsi, comme je l'ai dit plus bas.
      • [^] # Re: Vieux souvenirs....

        Posté par  (site web personnel) . Évalué à 1.

        Oui, on est bien d'accord, le printf n'est sensé vider que stdout. Si ça vidait aussi stdin (comme il me semble me rappeler), c'était certainement une spécificité de la glibc. Il s'agit bien alors d'une rustine toute caca ; mais comme je lui dit aussi de jeter scanf, il faudra aussi jeter la rustine (j'espère :).
  • # fflush(stdin) = comportement indéfini

    Posté par  . Évalué à 1.

    Pour palier a ce problème sous windows un fflush(stdin) suffisait et bien ici que neni. Cela ne va pas.

    Appliquer fflush à un flux entrant comme stdin résulte en un comportement indéfini. Windows peut aussi bien faire dans ce cas ce que tu voudrais qu'il fasse, comme une autre implémentation (ou le même Windows un autre jour) peut ne rien faire... cf. http://c-faq.com/stdio/stdinflush.html et http://c-faq.com/stdio/stdinflush2.html

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.