IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Problème de lecture d'un entier au clavier


Sujet :

C

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Juin 2005
    Messages
    23
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2005
    Messages : 23
    Points : 25
    Points
    25
    Par défaut Problème de lecture d'un entier au clavier
    Bonsoir,
    J'ai remarqué que la lecture au clavier, en langage C, pose souvent des problèmes, surtout dans le cas de la lecture d'entiers : quand on doit entrer un entier au clavier, et que celui qui execute le programme tape quelque chose avec au moins une lettre,l'entier prend une valeur bizarre(toujours la même : 1075028800).
    Mais c'est encore pire quand la lecture de l'entier se situe dans une boucle : dans ce cas,il suffit de lire une fois une mauvaise valeur au clavier pour le programme boucle ensuite indéfiniment sans jamais rendre la main à l'utilisateur.

    Le programme ci-dessous est censé lire un entier au clavier jusqu'à ce que cette valeur lue soit égale à 0.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #include<stdio.h> 
     
    main() 
    { int entier; float reel; char caractere;char* chaine; 
    do { 
    puts("Entrez un entier : 0 pour arreter"); 
    scanf("%d",&entier); 
    printf("entier = %d\n",entier); 
    } while(entier); exit(0);
    Lorsque je l'execute et que j'entre,par exemple, abc, voici les resultats de l'execution :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Entrez un entier : 0 pour arreter 
    entier = 1075028800 
    Entrez un entier : 0 pour arreter 
    entier = 1075028800 
    Entrez un entier : 0 pour arreter 
    entier = 1075028800 
    Entrez un entier : 0 pour arreter 
    entier = 1075028800 
    Entrez un entier : 0 pour arreter 
    entier = 1075028800 
    ............................................. (et ceci des centaines de fois)
    En Java, ce problème est evitable grace à l'exception declenchée lors de l'appel de la méthode parseInt,mais en C, je ne vois pas du tout comment résoudre le problème. Si qqn pouvait me dépanner...
    Merci d'avance.

  2. #2
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Tu devrais fouiller un peu sur ce forum, celà a déjà été évoqué mille fois : il ne faut jamais utiliser scanf !!!
    La lecture ce fais de cette façon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char buflec[256]; // ou autre longueur
    long int val;
    // on lit les caractères dans un buffer
    fgets(buflec, sizeof(buflec), stdin);
    // on étudie la saisie avec strtol, seule fonction adéquate pour transformer une chaîne en nombre
    val = strtol(buflec, NULL, 10);
    Tu peux approfondir l'étude de la chaîne en passant un deuxième paramètre à strtol, vois les détails sur l'aide en ligne de strol.

  3. #3
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Je suis pas d'accord pourquoi s'embrouyer avec un buffer, un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    scanf("%d%*c", &entier);
    Et tout va bien plus de probleme de retour chariot.

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut Re: Problème de lecture d'un entier au clavier
    Citation Envoyé par Yakurena
    J'ai remarqué que la lecture au clavier, en langage C, pose souvent des problèmes
    Si on utilise pas les bonnes fonctions, oui. Sinon, ça fonctionne très bien :

    http://emmanuel-delahaye.developpez....tes.htm#saisie
    http://emmanuel-delahaye.developpez....s.htm#fichiers

    http://emmanuel-delahaye.developpez.com/clib.htm
    Module IO

  5. #5
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par Skyrunner
    Je suis pas d'accord pourquoi s'embrouyer avec un buffer, un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    scanf("%d%*c", &entier);
    Et tout va bien plus de probleme de retour chariot.
    Si tu es un expert de scanf(), je te suggère d'écrire un mode d'emploi détaillé et de l'ajouter aux documents du forum.

  6. #6
    Membre actif Avatar de Gamdwin
    Inscrit en
    Avril 2005
    Messages
    186
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 186
    Points : 207
    Points
    207
    Par défaut
    Citation Envoyé par Emmanuel Delahaye
    Si tu es un expert de scanf(), je te suggère d'écrire un mode d'emploi détaillé et de l'ajouter aux documents du forum.
    Moi ça m'intéresse. Pas de l'écrire, de le lire.
    Les fonctions ...scanf m'inspirent toujours aussi peu confiance, je ne sais pas les utiliser.

  7. #7
    Rédacteur/Modérateur
    Avatar de Trap D
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    4 942
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2003
    Messages : 4 942
    Points : 6 498
    Points
    6 498
    Par défaut
    Citation Envoyé par Gamdwin
    Citation Envoyé par Emmanuel Delahaye
    Si tu es un expert de scanf(), je te suggère d'écrire un mode d'emploi détaillé et de l'ajouter aux documents du forum.
    Moi ça m'intéresse. Pas de l'écrire, de le lire.
    Les fonctions ...scanf m'inspirent toujours aussi peu confiance, je ne sais pas les utiliser.
    Pas de quoi rougir, moi c'est pareil

  8. #8
    Membre régulier
    Inscrit en
    Août 2004
    Messages
    101
    Détails du profil
    Informations forums :
    Inscription : Août 2004
    Messages : 101
    Points : 95
    Points
    95
    Par défaut
    Salut

    Je suis debutant en C et je voudrais savoir pourquoi il en faut pas utiliser scanf(); ?

    Moi je l'utilise et je n'est aucun problème.

    Merci

  9. #9
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par phoenix440
    Je suis debutant en C et je voudrais savoir pourquoi il ne faut pas utiliser scanf(); ?
    On peut l'utiliser si on maîtrise. Problème, très peu de gens maitrisent scanf(), qui est une fonction extrêmement complexe et certainement pas pour débutants.
    Moi je l'utilise et je n'est aucun problème.
    Ok. Montre comment tu résoudrais le problème posé par le posteur original.

  10. #10
    Membre éprouvé
    Profil pro
    Eleveur de cornichons
    Inscrit en
    Juin 2002
    Messages
    1 074
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Eleveur de cornichons
    Secteur : Finance

    Informations forums :
    Inscription : Juin 2002
    Messages : 1 074
    Points : 1 166
    Points
    1 166
    Par défaut
    Même si il y a des façons de bidouiller scanf() pour obtenir de bons résultats, pourquoi perdre ce temps et ne pas utiliser fgets() ?

    Pour limiter la saisie à 10 caractères en prenant en compte les espaces, on peut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char test[10];
    scanf("%9[^\n]s",test);
    printf() donne la possibilité de fixer le nombre de caractère à afficher grâce à une variable (donc plus pratique que de mettre en dur la valeur). Avec scanf(), ca ne semble pas marcher...

    Nas'

  11. #11
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par Skyrunner
    Je suis pas d'accord pourquoi s'embrouyer avec un buffer, un simple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    scanf("%d%*c", &entier);
    Et tout va bien plus de probleme de retour chariot.
    Mouais... Mais si je fais une saisie de ce genre la :
    123a
    Le '\n' reste dans le buffer d'entrée, et on boucle toujours....

    Bref, pour en revenir au code initial, je propose la solution suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    #include <stdio.h>
    #include <stdlib.h>
     
    int main(void){
     
      int entier = 1;
      do {
        puts("Entrez un entier : 0 pour arreter");
        if ( ! scanf("%d%*[^\n]%*c",&entier) ){
          char c;
          /* erreur d'entree */
          fprintf(stderr, "erreur de format, veuillez resaisir un nombre entier\n");
          /* de plus, le buffer n'a pas ete vide (echec de scanf...) */
          while ( (c = getchar() ) && c != '\n');
        }
        else {
          printf("entier = %d\n",entier);
        }
      } while(entier); exit(0);
     
      printf("vous etes sortis\n");
     
      return 0;
    }
    On remarque plusieurs choses.
    Tout d'abord, la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    scanf("%d%*[^\n]%*c",&entier)
    permet de capturer l'entier saisi, ET de vider le buffer d'entree.
    Malgré cela, si la scanf ECHOUE (sur le format d'entree), il ne poursuit pas les conversions suivantes : le buffer ne sera pas vidé !! il faut le faire manuellement dans le cas d'erreur du retour de scanf, avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    while ( (c = getchar() ) && c != '\n');
    Cela sous-entend qu'il faut a tout prix tester le retour de scanf (surtout quand on cherche à récuperer autre chose que des chaînes de caractères (cas plus permissif) ).

    Par ailleurs, je n'ai pas traité dans mon code les problèmes suivant, qui peuvent (et doonc doivent être traités) suivants :
    1) l'entier saisi est supérieur à INT_MAX
    2) les saisies de la forme "123azeazeaze" sont considérées comme correctes (on récupère 123), ce qui n'est pas forcément le comportement attendu..

    Bref, pour ce genre de saisie, scanf est loin d'être évident à utiliser (correctement en tout cas )

  12. #12
    Membre éprouvé
    Avatar de Pouic
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    669
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 669
    Points : 977
    Points
    977
    Par défaut
    Citation Envoyé par Nasky
    Même si il y a des façons de bidouiller scanf() pour obtenir de bons résultats, pourquoi perdre ce temps et ne pas utiliser fgets() ?

    Pour limiter la saisie à 10 caractères en prenant en compte les espaces, on peut faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    char test[10];
    scanf("%9[^\n]s",test);
    printf() donne la possibilité de fixer le nombre de caractère à afficher grâce à une variable (donc plus pratique que de mettre en dur la valeur). Avec scanf(), ca ne semble pas marcher...

    Nas'
    On peut bien évidemment faire de même avec scanf, en utilisant à fond les avantages du préprocesseur.

    Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    #include <stdio.h>
     
    /* twin macros : do not separate */
    #define xstr(s) str(s)
    #define str(s) #s
    /* ***************************** */
     
    #define TAILLE 80
    #define S_TAILLE xstr(TAILLE)
     
    int main(void) {
     
      char tab[TAILLE] = {0};
      scanf("%"S_TAILLE"s", tab);
    <...>
     
      return 0;
    }
    On utilise deux define afin d'expanser la macro passée ET de la transformer en chaine de caractere (sinon ca ne marche pas )
    Cette solution est plus "propre".

    Mais on aurait pu bêtement faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    #define TAILLE 80
    #define S_TAILLE "80"
    Ce qui est pénible en cas de maintenance...

    <edit>
    Je viens de lire les posts que j'avais "sauté", et je veux bien (sans pour autant me prétendre expert) écrire une documentation sur l'utilisation de scanf..
    (Par contre, ça viendra quand mon stage m'en laissera le temps )
    </edit>

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Débutant] Problème de lecture au clavier
    Par -papinou- dans le forum Pascal
    Réponses: 5
    Dernier message: 06/02/2008, 16h23
  2. Réponses: 7
    Dernier message: 13/03/2007, 11h20
  3. problème de lecture base de registre
    Par pafounet3 dans le forum MFC
    Réponses: 10
    Dernier message: 31/12/2003, 14h06
  4. [fread] Problème de lecture de buffer
    Par karl3i dans le forum C
    Réponses: 2
    Dernier message: 25/09/2003, 09h21
  5. Réponses: 4
    Dernier message: 23/07/2003, 13h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo