Ich habe folgendes Programm:
int main(int argc, char *argv[])
{
char ch1, ch2;
printf("Input the first character:"); // Line 1
scanf("%c", &ch1);
printf("Input the second character:"); // Line 2
ch2 = getchar();
printf("ch1=%c, ASCII code = %d\n", ch1, ch1);
printf("ch2=%c, ASCII code = %d\n", ch2, ch2);
system("PAUSE");
return 0;
}
Wie der Autor des obigen Codes erklärt hat: Das Programm funktioniert nicht richtig, da es in Zeile 1, wenn der Benutzer die Eingabetaste drückt, im Eingabepuffer 2 Zeichen belässt: Enter key (ASCII code 13)
und \n (ASCII code 10)
. Daher liest es in Zeile 2 das \n
und wartet nicht darauf, dass der Benutzer ein Zeichen eingibt.
OK, ich habe das verstanden. Aber meine erste Frage ist: Warum liest die zweite getchar()
( ch2 = getchar();
) nicht das Zeichen Enter key (13)
, sondern \n
das?
Als nächstes schlug der Autor zwei Möglichkeiten vor, um solche Probleme zu lösen:
verwenden
fflush()
schreibe eine Funktion wie diese:
void clear (void) { while ( getchar() != '\n' ); }
Dieser Code hat tatsächlich funktioniert. Aber ich kann mir nicht erklären, wie es funktioniert? Weil in der while-Anweisung, die wir verwenden getchar() != '\n'
, bedeutet dies, dass Sie ein einzelnes Zeichen außer '\n'
? wenn ja, bleibt im eingabepuffer noch das '\n'
zeichen?
getchar()
werden diese Zeichen gelesen und zurückgegeben. Ein Benutzer muss die Eingabetaste nicht ein anderes Mal drücken. Obwohl Termios unter Linux häufig vorkommen , sind sie nicht Teil der C-Standardbibliothek .Sie können es (auch) so machen:
quelle
fseek
verfügbar fürstdin
?Eine tragbare Methode zum Löschen bis zum Ende einer Zeile, die Sie bereits teilweise gelesen haben, ist:
Dies liest und verwirft Zeichen, bis es
\n
das Ende der Datei signalisiert. Es wird auch geprüft,EOF
ob der Eingabestream vor dem Zeilenende geschlossen wird. Der Typ vonc
mussint
(oder größer) sein, um den Wert halten zu könnenEOF
.Es gibt keine tragbare Möglichkeit, um herauszufinden, ob nach der aktuellen Zeile weitere Zeilen vorhanden sind (wenn dies nicht der Fall ist,
getchar
wird die Eingabe blockiert).quelle
Die Linien:
liest nicht nur die Zeichen vor dem Zeilenvorschub (
'\n'
). Es liest alle Zeichen im Stream (und verwirft sie) bis einschließlich des nächsten Zeilenvorschubs (oder EOF wird angetroffen). Damit der Test wahr ist, muss zuerst der Zeilenvorschub gelesen werden. Wenn die Schleife stoppt, war der Zeilenvorschub das letzte gelesene Zeichen, aber es wurde gelesen.Der Grund, warum ein Zeilenvorschub anstelle eines Wagenrücklaufs gelesen wird, liegt daran, dass das System den Zeilenvorschub in einen Zeilenvorschub übersetzt hat. Wenn die Eingabetaste gedrückt wird, signalisiert dies das Zeilenende ... aber der Stream enthält stattdessen einen Zeilenvorschub, da dies die normale Zeilenende-Markierung für das System ist. Das könnte plattformabhängig sein.
Die Verwendung
fflush()
in einem Eingabestream funktioniert nicht auf allen Plattformen. Zum Beispiel funktioniert es im Allgemeinen nicht unter Linux.quelle
while ( getchar() != '\n' );
ist eine Endlosschleife solltegetchar()
zurückkehrenEOF
aufgrund End-of-Datei.int ch; while ((ch = getchar()) != '\n' && ch != EOF);
kann verwendet werdenMöglicherweise stellen Sie nicht fest, dass der Vergleich erfolgt, nachdem
getchar()
das Zeichen aus dem Eingabepuffer entfernt wurde. Also , wenn Sie das erreichen'\n'
, ist es verbraucht und dann brechen Sie aus der Schleife heraus.quelle
Du kannst es versuchen
Dabei akzeptiert% * c die neue Zeile und ignoriert sie
eine weitere Methode anstelle von fflush (stdin), die undefiniertes Verhalten aufruft, das Sie schreiben können
Vergessen Sie nicht das Semikolon nach der while-Schleife
quelle
"%*c"
scannt ein beliebiges Zeichen (und speichert es nicht), sei es eine neue Zeile oder etwas anderes. Code setzt voraus, dass das 2. Zeichen eine neue Zeile ist. 2)while((getchar())!='\n');
ist eine unendliche Schleife solltegetchar()
zurückkehrenEOF
aufgrund end of file.-oder-
benutze vielleicht benutze
_getch_nolock()
.. ???quelle
kbhit()
undgetch()
Funktionen deklariert sind<conio.h>
und nur unter Windows als Standard verfügbar sind. Sie können auf Unix-ähnlichen Computern emuliert werden, dies erfordert jedoch einige Sorgfalt.Beim Versuch, die Lösung zu implementieren, tritt ein Problem auf
Ich poste eine kleine Anpassung 'Code B' für alle, die vielleicht das gleiche Problem haben.
Das Problem war, dass ich mit dem Programm das Zeichen '\ n' unabhängig vom Eingabezeichen abfing. Hier ist der Code, der mir das Problem gab.
Code A.
und die Anpassung bestand darin, das (n-1) -Zeichen kurz vor der Auswertung der Bedingung in der while-Schleife zu "fangen". Hier ist der Code:
Code B.
Die mögliche Erklärung ist, dass die while-Schleife, um zu unterbrechen, der Variablen y den Wert '\ n' zuweisen muss, damit sie der zuletzt zugewiesene Wert ist.
Wenn ich etwas mit der Erklärung, Code A oder Code B verpasst habe, sag mir bitte, ich bin kaum neu in c.
hoffe es hilft jemandem
quelle
while
Schleife befassen . Nach der Schleife können Sie prüfen ,stdin
um sauber / klar undy
halten wird entweder ‚\n
oder‘EOF
.EOF
wird zurückgegeben, wenn kein Zeilenumbruch vorhanden ist und der Puffer erschöpft ist (wenn die Eingabe den Puffer überlaufen würde, bevor er[ENTER]
gedrückt wurde). - Sie verwenden das effektivwhile((ch=getchar())!='\n'&&ch!=EOF);
, um jedes einzelne Zeichen imstdin
Eingabepuffer zu zerkauen .Eine andere noch nicht erwähnte Lösung ist die Verwendung von: Rücklauf (stdin);
quelle
Versuche dies:
stdin->_IO_read_ptr = stdin->_IO_read_end;
quelle
Kurz, tragbar und in stdio.h deklariert
Wird nicht in einer Endlosschleife aufgehängt, wenn auf stdin nichts zu spülen ist, wie in der folgenden bekannten Zeile:
Ein wenig teuer, verwenden Sie es also nicht in einem Programm, das den Puffer wiederholt löschen muss.
Von einem Kollegen gestohlen :)
quelle
freopen
ist, dass Sie nicht portabel zuweisen könnenstdin
. Es ist ein Makro.