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 :

getchar et scanf : valeur non prise en compte


Sujet :

C

  1. #1
    Membre à l'essai
    Inscrit en
    Décembre 2006
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 34
    Points : 23
    Points
    23
    Par défaut getchar et scanf : valeur non prise en compte
    Bonsoir tout le monde
    après des heures de recherches à devenir fou
    je décide de m'en réferer à vous car sinon ...

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
    #include <stdio.h>
    #include <stdlib.h>
     
    void initialiserPile(Pile** p);
    void affichePile(Pile* p);
    void push (Pile **p, char a);
     
    int main(){
    	Pile* p;
     
    	char car;
     
    	initialiserPile(&p);
    	affichePile(p);
     
    	printf("Entrer un mot se finissant par '.'\n");
    	printf("Entrer la valeur de c : \n");
     
     
    	do{
    		car=getchar();
    		if(car!='.'){
    			push (&p, car);
    			printf("Valeur rajouté !!\n");
    		}
    		else printf("Valeur non rajouté !!");
    	}while(car!='.');
     
    	push (&p, 'z');
    	push (&p, 'u');
     
    	affichePile(p);
     
    	return(0);
    }
     
     
     
     
     
    void initialiserPile(Pile** p){
    	*p=NULL;
    }
     
    void affichePile(Pile* p){
    	int n=0;	
    	while(p!=NULL){
    		printf("val de a : %c\n",p->valeur);
    		p=p->prec;
    		n++;
    	}	
    	printf("TAILLE DE LA PILE : %d\n",n);
    }
     
    void push (Pile **p, char a){
    	Pile *tmp;
    	tmp=(Pile*) malloc(sizeof(Pile));
    	tmp->valeur=a;
    	tmp->prec=*p;
    	*p=tmp;
    }
    Le problème, est que la boucle while, à chaque
    passage, est éxécutée deux fois pour je ne sais quelle raison;
    et exactement le même comportement si j'utilise un scanf à la place de getchar()



    Vous ne le voyez pas, mais quand j'affiche la taille de la pile suite à cette
    exemple, elle est également doublé, donc à chaque fois qu'il y a eu :
    "Entrer la valeur de a :"
    il a rajouté "RIEN?" à la pile


    J'ai alors essayé de me passer du while, et utilisé ceci à la place pour
    essayer de deviner d'où vient ce fameux problème :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    ....
     
    	printf("===>Entrer la valeur de c : \n");
    	scanf_s("%c",&car);
    	if(car!='.') push (&p, car);
     
    	printf("===>Entrer la valeur de c : \n");
    	scanf_s("%c",&car);
    	if(car!='.') push (&p, car);
     
    	push (&p, 'z');
    	push (&p, 'u');
    ....
    et cette fois-ci, le premier scanf marche parfaitement, mais le 2è
    n'a pas du tout l'air d'avoir été pris en comte, et le caractère espace,
    ou NULL, semble avoir été mis dedans ...
    Dans les deux cas, les caractères 'z', et 'u', sont bien rajoutés à la pile




    J'aimerais bien connaître mes erreurs dans les deux cas si possible

  2. #2
    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
    Simplement quand tu tapes ta lettre et que tu appuis sur la touche Entrée, ton buffer d'entrée contient la lettre tapée et le \n du Entrée.

    Ton getchar prend la lettre tapée et lors du tour de boucle suivant getchar prend directement le \n sans te laisser le temps de taper quoi que ce soit.

    Solution : utiliser fclean que tu trouveras sur ce forum (fais une recherche sur fclean).

    fclean sera a utiliser après chaque getchar.

    Voilà.

    Au fait je n'ai pas regardé le reste du code.
    Introduction à Silverlight 4 (new) ; Localisation d'une application Silverlight (new) ;
    Mon espace perso[/B]

    La connaissance s’acquiert par l’expérience, tout le reste n’est que de l’information. Albert Einstein[/SIZE]

  3. #3
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Skyrunner Voir le message
    Simplement quand tu tapes ta lettre et que tu appuis sur la touche Entrée, ton buffer d'entrée contient la lettre tapée et le \n du Entrée.

    Ton getchar prend la lettre tapée et lors du tour de boucle suivant getchar prend directement le \n sans te laisser le temps de taper quoi que ce soit.

    Solution : utiliser fclean que tu trouveras sur ce forum (fais une recherche sur fclean).

    fclean sera a utiliser après chaque getchar.

    Voilà.

    Au fait je n'ai pas regardé le reste du code.
    La plupart des implantations de fclean() proposées sur ce forum sont prévues pour fonctionner avec fgets() et prennent un tableau de caractères en argument duquel elles eliminent le caractère de fin de ligne saisi par fgets(). Le tampon du flux entrant est purgé lorsque saisie a été tronquée par fgets. Voici une implantation qui permet d'utiliser fclean() indifféramment pour faire le ménage après utilisation de fgets() ou fclean():

    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
    26
    27
    28
    #include <stdio.h>
    #include <string.h>
     
    void fclean(char *tampon, FILE *fp)
    {
        if (fp != NULL)
        {
            char *pc = NULL;
     
            if (tampon != NULL)
            {
                pc = strchr(tampon, '\n');
            }
     
            if (pc != NULL)
            {
                *pc = 0;
            }
            else
            {
                int c;
     
                while ((c = fgetc(fp)) != '\n' && c != EOF)
                {
                }
            }
        }
    }
    Lorsque tu utilises la fonction fclean() ci-dessus après getchar(), il faut passer NULL en 1er argument.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  4. #4
    Membre à l'essai
    Inscrit en
    Décembre 2006
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 34
    Points : 23
    Points
    23
    Par défaut
    Merci beaucoup de votre aide

    Par contre, je n'ai pas tout bien compris la fonction
    void fclean(char *tampon, FILE *fp)
    Notemment à quoi correspond FILE *fp

    Par contre, grâce à votre aide, j'ai trouvé deux solutions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    	do{
    		printf("Entrer la valeur de c : \n");
    		car=getchar();
    		if(car!='.' && car !='\n'){
    			push (&p, car);
    			printf("Valeur Pushe !!\n");
    		}
    		else printf("Valeur non Pushe !!\n");
    	}while(car!='.');
    et

    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
    
    static void purger(void){
        int c;
        while ((c = getchar()) != '\n' && c != EOF){}
    }
    	do{
    		printf("Entrer la valeur de c : \n");
    		car=getchar();
    		purger();
    		if(car!='.'){
    			push (&p, car);
    			printf("Valeur Pushe !!\n");
    		}
    		else printf("Valeur non Pushe !!\n");
    	}while(car!='.');
    Mais je pense que la 2è solution est plus "propre" à moins que je me trompe

    Merci beaucoup !!

  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 Angelina007 Voir le message
    Merci beaucoup de votre aide

    Par contre, je n'ai pas tout bien compris la fonction
    void fclean(char *tampon, FILE *fp)
    Notemment à quoi correspond FILE *fp
    C'est le flux entrant. Par exemple, ici, c'est stdin...

    Pour les raison expliquées ici, je conseille de ne pas s'éloigner des solutions proposées (fgets(), fclean() etc.), à moins d'être un expert du langage C.
    Pas de Wi-Fi à la maison : CPL

  6. #6
    Membre à l'essai
    Inscrit en
    Décembre 2006
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 34
    Points : 23
    Points
    23
    Par défaut
    Cela signifierait-il que les méthodes que j'emploie ne sont pas très "propres" ?

  7. #7
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 684
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 684
    Points : 30 973
    Points
    30 973
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Angelina007 Voir le message
    Cela signifierait-il que les méthodes que j'emploie ne sont pas très "propres" ?
    Exact. scanf est une fonction déstinée à traiter une entrée formatée. Exemple: tu veux traiter une info contenant "12 c toto" tu peux utiliser scanf("%d %c %s").
    Maintenant scanf() utilisé pour traiter ce qui vient de l'utilisateur est une très mauvaise idée car l'utilisateur peut taper n'importe quoi. Dans le meilleur des cas tu te retrouves toujours avec ce "\n" qui est forcément tapé pour valider la saisie et qui est enregistré aussi dans le buffer.

    Une première solution est de supprimer ce "\n" par un getchar() juste après mais si l'utilisateur tape "zorglub" quand tu attends un nombre ça va pas t'avancer beaucoup...

    La solution habituellement préconisée est d'utiliser fgets() pour traiter ce qui vient du clavier comme une chaîne (le "\n" est inclus dedans) puis de traiter cette chaîne par sscanf() pour en extraire les infos qui t'intéressent. Et le reste tu le laisses tomber (ou tu t'en sers pour prévenir l'utilisateur qu'il a mal rentré ses trucs).

    Bien que scanf() soit une fonction habituellement présentée en premier aux débutants (car sa mise en oeuvre ne nécessite pas de grandes connaissances et permet de suite de commencer à faire de petits trucs) il convient, quand on commence à vouloir faire un travail plus important, de s'en séparer assez vite...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  8. #8
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Points : 5 360
    Points
    5 360
    Par défaut
    Citation Envoyé par Angelina007 Voir le message
    Cela signifierait-il que les méthodes que j'emploie ne sont pas très "propres" ?
    Je n'ai pas regardé en détails, mais la deuxième de tes solutions convient. Ta fonction est équivalente à un appel à fclean(NULL, stdin) proposé plus haut.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  9. #9
    Membre à l'essai
    Inscrit en
    Décembre 2006
    Messages
    34
    Détails du profil
    Informations forums :
    Inscription : Décembre 2006
    Messages : 34
    Points : 23
    Points
    23
    Par défaut
    Merci beaucoup pour ces compléments !
    Je vois un peu plus clair maintenant

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

Discussions similaires

  1. [XL-2003] Valeurs non prise en comptes
    Par jeandani2012 dans le forum Macros et VBA Excel
    Réponses: 19
    Dernier message: 07/11/2012, 18h28
  2. Valeur au clavier non prise en compte
    Par benstan dans le forum x86 16-bits
    Réponses: 1
    Dernier message: 03/06/2011, 11h39
  3. Valeur champs non prise en compte
    Par alexking2005 dans le forum ASP.NET
    Réponses: 1
    Dernier message: 05/11/2009, 11h56
  4. Réponses: 1
    Dernier message: 06/08/2008, 15h58
  5. [VBA-A] valeur non prise en compte par un composant
    Par robert_trudel dans le forum VBA Access
    Réponses: 4
    Dernier message: 01/07/2006, 22h25

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