2010-09-04 9 views
10

Je suis confus par un morceau de code qui se trouve dans une fonction que je suis en train d'étudier:C getchar vs scanf

char GetCommand(void) 
{ 
    char command; 

    do { 
     printf("Enter command (q=quit, n=new, l=list): "); 
     scanf("%c", &command); 
     Flush(); 
    } 
    while ((command != 'q') && (command != 'n') 
      && (command != 'l')); 

    printf("\n----------\n"); 
    return(command); 
} 

void Flush(void) { 
    while (getchar() != '\n') 
     ; 
} 

Ce que je ne comprends pas tout à fait ici est l'utilisation de la fonction Flush(). Je veux dire, le livre que je suis en train de lire l'explique en disant qu'il empêche l'utilisateur d'entrer plus d'un caractère et de le lire quand il est invité à entrer la deuxième fois. Ce que je ne comprends pas, c'est comment Flush() empêche cela. Cela ne fait rien. Tout ce qu'il est est une commande while. (Alors que c'est vrai ...... quoi ?????) n'a pas de sens.

Répondre

8

getchar() a pour effet secondaire de supprimer le caractère suivant du tampon d'entrée. La boucle dans Flush lit et rejette les caractères jusqu'à ce que - et y compris - la nouvelle ligne \n se terminant la ligne.

Puisque le scanf est dit de lire un et un seul caractère (%c) cela a pour effet d'ignorer tout le reste sur cette ligne d'entrée.

Il serait probablement plus clair si le scanf était le remplacer par

command = getchar(); 

mais il est en fait un exemple généralement mauvais qu'il ne gère pas bien Fin de fichier.

En général scanf est le mieux oublié; fgets et sscanf fonctionnent beaucoup mieux car l'un est responsable de l'entrée et l'autre pour l'analyser. Essayez de faire trop de travaux en même temps.

+0

OHHHH, je ne savais pas que getchar enlevé le prochain caractère dans le tampon d'entrée - ce qui explique ma confusion. Je vous remercie. – startuprob

2

getchar lit un caractère à partir de l'entrée standard. Si vous le placez dans une boucle while, il continuera à lire un caractère à la fois jusqu'à ce que la condition soit fausse.

Ce que fait la fonction Flush est la lecture jusqu'à ce qu'elle rencontre une nouvelle ligne (\n). C'est le caractère produit lorsque l'utilisateur appuie sur la touche Entrée. Donc, le code que vous avez lu va lire un caractère (je ne sais pas pourquoi il utilise scanf pour cela au lieu de simplement getchar, ce qui serait plus rapide), puis rejette le reste de l'entrée jusqu'à ce que l'utilisateur frappe entrer .

Si vous deviez alimenter ce programme foobar, cela prendrait le f et abandonnerait le oobar dans la fonction Flush. Sans appeler flush, le f pourrait aller à un scanf, et le deuxième scanf obtiendrait le premier o.

+0

Je ne comprends toujours pas. Qu'est-ce que Flush fait exactement? Cela semble équivalent à une condition d'instruction if mais pas de commande. Je comprends que scanf contiendra toutes les entrées de l'utilisateur, puis l'exécuter à nouveau, mais comment Flush empêche-t-il d'exécuter le 'o' sur votre exemple? – startuprob

-1

L'exemple de code suivant peut vous aider à trouver la logique derrière l'utilisation Flush():

std::cerr << "Save this data (y for yes/Enter for no)? "; 
int chr = getchar(); 
if(chr != '\n') while(getchar() != '\n'); // Flush() 
if(chr == 'y') 
    std::cerr << "The current data was saved\n";