2017-02-14 2 views
7

Dies ist eine sehr grundlegende C-Frage, die von Seite 18 von Kernighan und Ritchie kommt.Warum liest getchar() Zeichen wie Backspace nicht?

ich diesen sehr einfachen Code kompiliert haben für Zeichen von der Tastatur eingegeben zählen:

#include <stdio.h> 

/* count characters in input; 1st version */ 
main() 
{ 
    long nc; 

    nc = 0; 
    while (getchar() != EOF) 
    ++nc; 
    printf("%1d\n", nc); 
} 

Dies kompiliert gut, läuft gut, und verhält sich so ziemlich wie erwartet das heißt, wenn ich eintrete „Hallo Welt“, es gibt einen Wert von 11 zurück, wenn ich CTRLD drücke, um das EOF-Zeichen zu geben.

Was mich verwirrt, ist, wenn ich einen Fehler mache, kann ich Backspace verwenden, um die Zeichen zu löschen und sie erneut eingeben, und es gibt nur die Anzahl der Zeichen vom Terminal angezeigt, wenn ich EOF aufrufen.

Wenn der Code jedes Zeichen zählt, einschließlich Sonderzeichen, wenn ich vier Zeichen eingeben, zwei löschen und zwei weitere eingeben, sollte dies nicht als 8 Zeichen ausgegeben werden (4 Zeichen + 2 Zeichen + 2 Zeichen), nicht 4?

Ich verstehe offensichtlich, wie C Backspace behandelt, und wie/wann der Code die Variable nc inkrementiert?

+4

Die Bearbeitung wird von der Terminal-Anwendung behandelt, so dass die 'getchar' nie die Löschungen liest. –

+0

Hinweis: Sie sollten 'int main (void)' anstelle von 'main()' verwenden, da das erstere nach dem Standard gültig ist. –

+0

@CoolGuy: Eigentlich ist die zweite Version noch gültig, aber ein Vermächtnis. Es ist eine Obsoleszenz-Funktion und wird möglicherweise aus dem Standard entfernt. Sagte: Ja, die erste Version sollte definitiv verwendet werden. Im Allgemeinen sollten Prototypen-ähnliche Signaturen für Funktionen im Allgemeinen verwendet werden. – Olaf

Antwort

5

Normalerweise läuft Ihre Terminalsitzung im "Zeilenmodus", dh, es gibt nur Daten an Ihr Programm weiter, wenn eine Zeile abgeschlossen ist (z. B. Return, usw.). Sie sehen die Zeile also nur so, wie sie fertig ist (mit allen Bearbeitungen, bevor das Programm überhaupt etwas sieht). In der Regel ist dies eine gute Sache, daher muss sich jedes Programm nicht mit delete/etc befassen.

Auf den meisten Systemen (z. B. Unix-basierte Systeme usw.) ist es möglich, das Terminal in den "Raw" -Modus zu versetzen - das heißt, jedes Zeichen wird wie empfangen an das Programm übergeben. Zum Beispiel tun dies üblicherweise bildschirmorientierte Texteditoren.

5

Es ist nicht so, dass getchar() die "Löschungen" nicht zählt, aber es sieht die Eingabe nicht einmal, bis es vom Terminaltreiber an Ihr Programm übergeben wird.

Wenn Sie etwas eingeben, erreicht es Ihr C-Programm erst, wenn Sie \n drücken oder EOF (oder EOL) senden. Dies definiert POSIX als Canonical Mode Input Processing - das ist normalerweise der Standardmodus.

+0

Richtig, ich verstehe. Das ist eher mein Missverständnis, wie das Terminal funktioniert, und nicht der C-Code selbst. –

1

Rück Zeichen werden in der Regel bearbeiten Eingang in gekocht tty-Modus (siehe kanonischen Eingabemodus in tty(4) in BSD und termios(3) in Linux-Systemen) verwendet, so dass sie an dem tty Fahrer verbraucht, und nicht bekommen, an den Eingang des Prozess bekommt danach. Gleiches gilt für Ctrl-D als Dateiende oder Ctrl-K als Kill-Eingabezeichen. Es gibt einige Dinge, die der Fahrer hinter den Kulissen tut, die Ihr Prozess schließlich nicht bekommt. Diese sind darauf ausgerichtet, Benutzern und Programmierern das Leben zu erleichtern, da Sie normalerweise keine gelöschten Eingaben in Ihrem Leben wünschen (das ist der Grund, sie zu löschen), oder wollen, dass Zeilenenden \n und nicht \r sind, wie das tty normalerweise erzeugt, wenn Sie Drücken Sie die Taste [RETURN]. Wenn Sie jedoch aus einer Datei mit Backspaces lesen, erhalten Sie diese als normale Eingabe, erstellen Sie einfach eine Datei mit Backspaces und versuchen Sie, die Weiterleitung von Eingaben zu lesen, und Sie sehen diese Zeichen in Ihrer Eingabe.

Übrigens, wenn Sie Backspaces am Terminal generieren möchten, nur ein Ctrl-V vor jedem Zeichen (das wird auch beim tty-Treiber verwaltet und wird nicht beim Lesen aus einer Datei passieren), und Sie werden Ihre sehen Backspace-Zeichen als normale Eingabe in Ihrer Datei (zum Senden einer Ctrl-V einfach doppelt)