2009-06-16 6 views
7

J'ai commencé à lire "The C Programming Language" (K & R) et j'ai un doute sur la fonction getchar().Où `getchar()` stocke-t-il l'entrée de l'utilisateur?

Par exemple, ce code:

#include <stdio.h> 

main() 
{ 
    int c; 

    c = getchar(); 
    putchar(c); 
    printf("\n"); 
} 

Taper toomanychars + CTRL +D impressions (EOF) juste t. Je pense que c'est attendu puisque c'est le premier personnage introduit.

Mais cet autre morceau de code:

#include <stdio.h> 

main() 
{ 
    int c; 

    while((c = getchar()) != EOF) 
    putchar(c); 
} 

Taper toomanychars + CTRL +D (EOF) imprime toomanychars.

Ma question est: pourquoi cela se produit-il si je n'ai qu'une seule variable char? Où sont stockés les autres caractères?

EDIT:

Merci à tous pour les réponses, je commence à le faire maintenant ... seul hic:

Les premières sorties du programme lorsque donné CTRL +D tout la seconde imprime la chaîne entière et attend ensuite plus d'entrée de l'utilisateur. Pourquoi attend-il une autre chaîne et ne sort pas comme la première?

+1

Votre seconde approche ne fait que boucler jusqu'à EOF. CTRL + D (sur les systèmes unix typiques) n'entraînera pas EOF sauf si vous l'avez frappé sur une ligne. En appuyant sur CTRL + D après avoir écrit un caractère ne résulte pas EOF – nos

Répondre

4

Il traite le flux d'entrée comme un fichier. C'est comme si vous ouvriez un fichier contenant le texte "toomanychars" et que vous le lisiez ou le reproduisiez un caractère à la fois.

Dans le premier exemple, en l'absence d'une boucle while, c'est comme si vous aviez ouvert un fichier et lu le premier caractère, puis l'avez sorti. Cependant, le deuxième exemple continuera à lire les caractères jusqu'à ce qu'il obtienne un signal de fin de fichier (ctrl+D dans votre cas), exactement comme s'il s'agissait de la lecture d'un fichier sur le disque.


En réponse à votre question, quel système d'exploitation utilisez-vous? Je l'ai couru sur mon ordinateur portable Windows XP et ça a bien fonctionné. Si j'appuyais sur Entrée, j'imprimerais ce que j'avais jusqu'ici, créerais une nouvelle ligne, et continuerais. (La fonction getchar() ne retourne pas tant que vous n'appuyez pas sur Entrée, ce qui signifie qu'il n'y a rien dans le tampon d'entrée quand il est appelé). Lorsque j'appuie sur CTRL+Z (EOF sous Windows), le programme se termine. Notez que dans Windows, l'EOF doit être sur une ligne propre à compter comme EOF dans l'invite de commande. Je ne sais pas si ce comportement est imité sous Linux, ou quel que soit le système que vous utilisez.

+0

@Carson, exactement! EOF doit être dans sa propre ligne. MERCI BEAUCOUP! –

+0

de rien. Je ai lutté avec cela aussi, mais l'a résolu grâce à SO :) –

9

getchar obtient un seul caractère de l'entrée standard, qui dans ce cas est le tampon du clavier.

Dans le second exemple, l'entrée jusqu'à ce que la fonction devient vide getchar est dans une boucle while qui continue jusqu'à ce qu'il rencontre un EOF, il gardera en boucle et récupérer un caractère (et imprimer le caractère à l'écran).

Les appels successifs au getchar recevront des caractères successifs provenant de l'entrée.

Oh, et ne vous sentez pas mal pour poser cette question - J'ai été intrigué quand j'ai d'abord rencontré ce problème.

+0

Est-ce qu'il commence à boucler juste après qu'il rencontre l'instruction 'while (c = getchar())', ou attend-il que l'entrée soit pressée, puis en boucle? D'après ce que je peux voir, il exécute le corps de la boucle 'while()' seulement après avoir appuyé sur enter. Ma question est: Est-ce que 'getchar()' fait que la boucle 'while()' attend jusqu'à ce que 'enter' ou' CTRL + D' (sur mon système) soit pressé et juste après que le retour à 'while() 'boucle, puis l'exécution du reste du corps. – dud3

3

Votre premier programme lit seulement un caractère, l'imprime et se termine. Votre deuxième programme a une boucle. Il continue à lire les caractères un à la fois et à les imprimer jusqu'à ce qu'il lise un caractère EOF. Un seul caractère est stocké à un moment donné.

2

Vous utilisez uniquement la variable c pour contenir chaque caractère un à la fois.

Une fois que vous avez affiché le premier char (t) en utilisant putchar(c), vous oubliez la valeur de c en attribuant le caractère suivant (o) à la c variable remplaçant la valeur précédente (t).

1

le code est fonctionnellement équivalent à

main(){ 
    int c; 
    c = getchar(); 
    while(c != EOF) { 
    putchar(c); 
    c = getchar(); 
    } 
} 

vous trouverez peut-être cette version plus facile à comprendre. la seule raison de placer l'assignation dans le conditionnel est d'éviter d'avoir à taper 'c = getchar()' deux fois.

4

Quelque chose ici est tamponné. par exemple. le fichier stdout FILE * que putchar écrit sur peut-être line.buffered. Lorsque le programme se termine (ou rencontre une nouvelle ligne) un tel FICHIER * sera fflush() et vous verrez la sortie.

Dans certains cas, le terminal réel que vous consultez peut mettre en mémoire tampon la sortie jusqu'à un retour à la ligne, ou jusqu'à ce que le terminal lui-même soit chargé de vider son tampon, ce qui pourrait être le cas. une nouvelle invite.

Maintenant, ce qui est susceptible d'être le cas ici, c'est que c'est l'entrée qui est tamponnée (en plus de la sortie :-)) Lorsque vous appuyez sur les touches, il apparaîtra sur votre fenêtre de terminal. Cependant, le terminal n'enverra pas ces caractères à votre application, il les tamponnera jusqu'à ce que vous lui demandiez d'être la fin de l'entrée avec Ctrl + D, et éventuellement un retour à la ligne. est ici une autre version pour jouer et réfléchir sur:

int main() { 
    int c; 
    while((c = getchar()) != EOF) { 
    if(c != '\n') 
     putchar(c); 
    } 
    return 0; 
} 

Essayez de nourrir votre programme une phrase, et appuyez sur Entrée. Et faites de même si vous commentez if (c! = '\ N') Peut-être pouvez-vous déterminer si votre entrée, sortie ou les deux sont tamponnés d'une manière ou d'une autre. Cela devient plus intéressant si vous exécutez ce qui précède comme: ./mytest | (Comme remarque, notez que CTRD + D n'est pas un caractère, pas plus que EOF, mais sur certains systèmes, cela entraînera la fermeture du flux d'entrée, ce qui soulèvera de nouveau EOF pour quiconque essayera de lire. le flux.)

0

Pour votre question mise à jour, dans le premier exemple, un seul caractère est lu. Il n'atteint jamais l'EOF. Le programme se termine parce qu'il n'y a rien à faire après avoir terminé l'instruction printf. Il lit juste un caractère. Imprime le. Met dans une nouvelle ligne. Et puis se termine car il n'a plus rien à faire. Il ne lit pas plus d'un caractère. Considérant que, dans le deuxième code, le getchar et le putchar sont présents dans une boucle while.En cela, le programme continue à lire les caractères un par un (comme le fait la boucle) jusqu'à ce que atteint le caractère EOF (^ D). À ce stade, il correspond à c! = EOF et comme les conditions ne sont pas satisfaites, il sort de la boucle. Maintenant, il n'y a plus d'instructions à exécuter. Donc, le programme se termine à ce stade.

Espérons que cela aide.