getchar() et stdin
Une question connexe est de ici, mais ma question est différente.
Mais, j'aimerais en savoir plus sur le fonctionnement interne de getchar() et de l'entrée standard. Je sais que getchar() en fin de compte les appels fgetc(stdin).
Ma question est sur le tampon, stdin et getchar() le comportement. Compte tenu de la classique de K&R exemple:
#include <stdio.h>
main()
{
int c;
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
Il me semble que getchar()'comportement pourrait être décrit comme suit:
Si il n'y a rien dans le stdin de la mémoire tampon, laissez le système d'exploitation accepter la saisie de l'utilisateur jusqu'à ce que [entrer] est pressée. Puis retour au premier caractère dans le tampon.
Supposons que le programme est exécuté et que l'utilisateur tape "anchois."
Ainsi, dans l'exemple de code ci-dessus, le premier appel à getchar() attend la saisie de l'utilisateur et attribue le premier caractère dans le tampon à c variable. L'intérieur de la boucle, la première itération de l'appel à getchar() dit: "Hey, il y a des choses dans la mémoire tampon, retour le caractère suivant dans la mémoire tampon." Mais la n-ième itération de la boucle while résultats dans getchar() en disant: "Hey, il n'y a rien dans le tampon, de sorte laisser stdin rassembler les types de l'utilisateur.
J'ai passer un peu de temps avec la source en c, mais il semble que c'est plus un comportement artefact de stdin plutôt que fgetc().
Je suis mal ici? Merci pour votre perspicacité.
fflush(stdin)
Comportement Indéfini! Je ne peux pas vérifier dans l'immédiat ...Vous avez raison, j'ai corrigé l'exemple.
Merci, j'ai collé une sale exemple, qui contenait un peu de gravats à partir de mon expérimentation.
OriginalL'auteur ybakos | 2011-10-12
Vous devez vous connecter pour publier un commentaire.
Pas nécessairement.
getchar
etgetc
pourrait ainsi étendre à la procédure de lecture à partir d'un fichier, avecfgetc
mis en œuvre commeJe peux seulement vous dire ce que je sais, et c'est de cette façon Unix/Linux fonctionne. Sur cette plate-forme, un
FILE
(y compris la chose quistdin
points) est titulaire d'un descripteur de fichier (unint
) qui est transmis à l'OS afin d'indiquer à partir de quel source d'entrée de laFILE
obtient des données, en plus d'une mémoire tampon et quelques autres de comptabilité choses.Les "rassembler" partie "signifie" appeler le
read
appel système sur le descripteur de fichier pour remplir la mémoire tampon de nouveau". Cela varie en fonction de la mise en œuvre de C, si.yep, c'est ce qui se passe. Le
fgetc
de mise en œuvre de truc, btw., n'est pas une fiction: autant que je me souvienne, j'ai vu cela dans l'4.4 BSD UNIX C de la bibliothèque, dont l'un dans Mac OS X est en fin de compte provenant.Grâce larsmans. Gee, un autre point à ajouter à votre 42k.<g>
OriginalL'auteur Fred Foo
getchar () l'entrée est de la ligne de tampon, et à l'entrée de la mémoire tampon est limitée, habituellement, il est de 4 ko. Ce que vous voyez au premier abord est l'écho de chaque caractère que vous tapez. Lorsque vous appuyez sur ENTER, puis getchar() permet de retourner les caractères jusqu'à la LF (qui est converti CR-LF). Lorsque vous maintenez les touches sans LF pour un certain temps, il s'arrête en écho après 4096 caractères, appuyez sur ENTRÉE pour continuer.
OriginalL'auteur ott--
Le comportement que nous observons n'a rien à voir avec le C et
getchar()
, mais avec le téléscripteur (ATS) sous-système dans le noyau de système d'exploitation.Pour cela, vous devez connaître la façon dont les processus d'obtenir leur entrée de votre clavier et la façon dont ils écrivent leur sortie de votre fenêtre de terminal (je suppose que vous utilisez UNIX et les explications suivantes s'appliquent spécifiquement à UNIX, c'est à dire Linux, macOS, etc.):
La case intitulée "Terminal" dans le diagramme ci-dessus est de votre fenêtre de terminal, par exemple, xterm, iTerm, ou d'un Terminal.app. Dans les temps anciens, les terminaux où le matériel distinct des appareils, composé d'un clavier et d'un écran, et ils étaient connectés à l' (éventuellement à distance) de l'ordinateur sur une ligne série (RS-232). Chaque caractère tapé sur le clavier du terminal a été envoyé sur cette ligne à l'ordinateur et consommé par une application qui a été connecté à la borne. Et chaque personnage que l'application produite a été envoyé au cours de la même ligne pour le terminal qui s'affiche sur l'écran.
De nos jours, les terminaux ne sont pas les périphériques matériels plus, mais ils se sont déplacés à l'intérieur de l'ordinateur et est devenu les processus qui sont désignés comme émulateurs de terminal. xterm, iTerm2, Terminal.app, etc., sont tous les émulateurs de terminal.
Cependant, le mécanisme de communication entre les applications et les émulateurs de terminal resté le même comme c'était pour le matériel pour les terminaux. Émulateurs de Terminal émuler matériel pour les terminaux. Cela signifie que, du point de vue d'une application, en parlant à un émulateur de terminal d'aujourd'hui (p. ex. iTerm2) fonctionne de la même chose que de parler à un vrai terminal (par exemple, un DEC VT100) en 1979. Ce mécanisme n'a pas été modifié de sorte que les applications développées pour le matériel terminaux va continuer à travailler avec le logiciel émulateurs de terminal.
Alors, comment fonctionne ce mécanisme de communication de travail? UNIX est un sous-système appelé ATS dans le noyau (ATS est synonyme de télétype, qui était la forme la plus ancienne de terminaux informatiques qui n'ont même pas besoin d'un écran, un clavier et une imprimante). Vous pouvez penser à l'ATS comme un pilote générique pour les terminaux. ATS lit des octets sur le port sur lequel un terminal est connecté (entrée à partir du clavier de la borne), et écrit les octets à ce port (envoyé à l'écran de la borne).
Il y a un ATS instance pour chaque terminal est connecté à un ordinateur (ou pour chaque émulateur de terminal processus en cours d'exécution sur l'ordinateur). Par conséquent, un ATS instance est également mentionné comme un appareil TTY (du point de vue de la demande, de parler à un TTY exemple, c'est comme parler à un terminal). Dans le monde UNIX façon de faire des interfaces de pilote disponible sous forme de fichiers, ces périphériques TTY sont apparus comme
/dev/tty*
dans une certaine forme, par exemple, sur macOS ils sont/dev/ttys001
,/dev/ttys002
, etc.Une application peut avoir son flux standard (stdin, stdout, stderr) dirigé vers un appareil TTY (en fait, c'est la valeur par défaut, et vous pouvez savoir à qui TÉLÉIMPRIMEUR votre shell est connecté avec le
tty
de commande). Cela signifie que tout ce que l'utilisateur tape sur le clavier devient la norme d'entrée de l'application, et quelle que soit l'application écrit sur sa sortie standard est envoyé à l'écran du terminal (ou une fenêtre de terminal d'un émulateur de terminal). Tout cela se passe à travers le dispositif TTY, c'est l'application communique avec le dispositif TTY (ce type de pilote) dans le noyau.Maintenant, le point crucial: le dispositif TTY ne se contente pas de passer chaque entrée de caractères sur l'entrée standard de l'application. Par défaut, l'appareil TTY applique un soi-disant ligne de discipline les caractères reçus. Cela signifie que, localement, les tampons et interprète supprimer, retour arrière et d'autres édition de la ligne de caractères, et ne transmet à l'entrée standard de la demande lorsqu'il reçoit une retour chariot ou saut de ligne, ce qui signifie que l'utilisateur a terminé la saisie et l'édition d'un ensemble de la ligne.
Cela signifie que jusqu'à ce que l'utilisateur appuie retour,
getchar()
ne pas voir quoi que ce soit dans stdin. C'est comme si rien avait été saisie à ce jour. Seulement lorsque l'utilisateur appuie retour, le dispositif TTY envoie ces caractères sur l'entrée standard de l'application, oùgetchar()
immédiatement lit comme.En ce sens, il n'y a rien de spécial au sujet du comportement de
getchar()
. Il vient immédiatement lit les caractères dans stdin qu'ils seront disponibles. La ligne de mise en mémoire tampon que vous observez qui se passe dans le TÉLÉIMPRIMEUR dans le noyau.Maintenant à la partie intéressante: ce dispositif TTY peut être configure. Vous pouvez le faire, par exemple, à partir d'un shell avec le
stty
de commande. Cela vous permet de configurer presque tous les aspects de la ligne de la discipline que l'appareil TTY s'applique à de nouveaux personnages. Ou vous pouvez désactiver à tout traitement que ce soit par la configuration de l'appareil TTY pour mode raw. Dans ce cas, le dispositif TTY transmet toutes les a reçu caractère immédiatement à stdin de l'application sans aucune forme d'édition.Si vous activez le mode raw dans le TÉLÉIMPRIMEUR, vous verrez que
getchar()
immédiatement reçoit chaque caractère que vous tapez sur le clavier. Le programme C suivant illustre cela:Le programme définit le processus actuel' appareil TTY mode raw, puis utilise
getchar()
de lire et d'imprimer les caractères à partir de stdin dans une boucle. Les caractères sont imprimés sous forme de codes ASCII en hexadécimal et octal notation. Le programme spécialement interprète leETX
de caractères (code ASCII 0x03) comme un déclencheur pour terminer. Vous pouvez produire ce personnage sur votre clavier en tapantCtrl-C
.OriginalL'auteur weibeld