Scanf bzw. getchar wird übersprungen. Was tun?
Abend,
tut mir leid erstmal -- Ist bestimmt eine totale Anfänger frage, aber ich bin Anfänger und hab da ein kleines Problem:
Bei diesem simplen Code:
Wird nur Eingabe 1 abgefragt.
Das zweite scanf (Eingabe 2) wird dabei allerdings übersprungen.
Ausgabe:
Genau:
"Ich betätige die Taste B und drücke Enter".
Nach meiner Internet Recherche liegt dass wohl dadran, dass
scanf das "B" einliest und der Variable zuweist. Das Enter allerdings im Einlese Speicher liegen lässt. Das nächst scanf liest diesen dann aus und macht sofort weiter da er noch das "\n" von der vorherigen Eingabe vorfindet.
Kann mir bitte jemand weiterhelfen dieses simple Problem zu lösen?
Im Grunde sollen halt beide scanf ausgeführt werden. Das zweite wird ja wegen dem Enter vom vorherigen Befehl übersprungen.
Danke im Vorraus und Viele Grüße
pelzfrucht
PS: Mit getchar(); besteht das gleiche Problem.
tut mir leid erstmal -- Ist bestimmt eine totale Anfänger frage, aber ich bin Anfänger und hab da ein kleines Problem:
Bei diesem simplen Code:
#include <stdio.h>
main() {
char menue_eingabe;
char menue_eingabe2;
printf("\nEingabe 1: ");
scanf("%c", &menue_eingabe);
printf("\nEingabe 2: ");
scanf("%c", &menue_eingabe2);
printf("\n\n==============================\n\nEingabe 1 ==> %c\nEingabe 2 ==> %c\n\n", menue_eingabe, menue_eingabe2);
return 0;
}
Wird nur Eingabe 1 abgefragt.
Das zweite scanf (Eingabe 2) wird dabei allerdings übersprungen.
Ausgabe:
Eingabe 1: B
Eingabe 2:
Eingabe 1 ==> B
Eingabe 2 ==>
Program ended with exit code: 0
Eingabe 2:
Eingabe 1 ==> B
Eingabe 2 ==>
Program ended with exit code: 0
Genau:
"Ich betätige die Taste B und drücke Enter".
Nach meiner Internet Recherche liegt dass wohl dadran, dass
scanf das "B" einliest und der Variable zuweist. Das Enter allerdings im Einlese Speicher liegen lässt. Das nächst scanf liest diesen dann aus und macht sofort weiter da er noch das "\n" von der vorherigen Eingabe vorfindet.
Kann mir bitte jemand weiterhelfen dieses simple Problem zu lösen?
Im Grunde sollen halt beide scanf ausgeführt werden. Das zweite wird ja wegen dem Enter vom vorherigen Befehl übersprungen.
Danke im Vorraus und Viele Grüße
pelzfrucht
PS: Mit getchar(); besteht das gleiche Problem.
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 297833
Url: https://administrator.de/forum/scanf-bzw-getchar-wird-uebersprungen-was-tun-297833.html
Ausgedruckt am: 02.04.2025 um 02:04 Uhr
23 Kommentare
Neuester Kommentar
Moin,
Du hast da glaubeich einen Denkfehler:
Dadruch, daß Du nach dem B auf enter drückst, hast Du schon mehrere zeichen eingegeben. Das erste Zeichen ist das B, das das erste scanf abbekommt. Das zweite zeichen bekommt das "Enter" ab. Wenn Du da etwas eingeben willst, mußt Du zuerst den Puffer leeren, bevor Du das scanf losläßt. Wenn Du das sehen wilst, gibt die zeichen statt als Character als Zahl aus.
lks
Nachtrag:
ergibt:
Nachtrag: Du könntest einfach per while und scanf einfach den Puffer leeren, bevor Du die zweite Ausgabe machst. den Einzeiler überlasse ich Dir als Übung.
Du hast da glaubeich einen Denkfehler:
Dadruch, daß Du nach dem B auf enter drückst, hast Du schon mehrere zeichen eingegeben. Das erste Zeichen ist das B, das das erste scanf abbekommt. Das zweite zeichen bekommt das "Enter" ab. Wenn Du da etwas eingeben willst, mußt Du zuerst den Puffer leeren, bevor Du das scanf losläßt. Wenn Du das sehen wilst, gibt die zeichen statt als Character als Zahl aus.
lks
Nachtrag:
#include <stdio.h>
main() {
char menue_eingabe;
char menue_eingabe2;
printf("\nEingabe 1: ");
scanf("%c", &menue_eingabe);
printf("\nEingabe 2: ");
scanf("%c", &menue_eingabe2);
printf("\n\n==============================\n\nEingabe 1 ==> %i\nEingabe 2 ==> %i\n\n", (int) menue_eingabe, (int) menue_eingabe2);
return 0;
}
ergibt:
Eingabe 1: a
Eingabe 2:
==============================
Eingabe 1 ==> 97
Eingabe 2 ==> 10
Nachtrag: Du könntest einfach per while und scanf einfach den Puffer leeren, bevor Du die zweite Ausgabe machst. den Einzeiler überlasse ich Dir als Übung.

Moin,
schreib einfach beide scanf Zeilen so das du vor dem %c noch ein Leerzeichen setzt:
Dann werden nicht sichtbare Zeichen bei der Eingabe ignoriert und nicht übernommen.
Oder Alternativ noch zwischen den beiden Abfragen noch ein getchar() setzen das die überflüssigen Zeichen konsumiert/aufnimmt.
Gruß jodel32
schreib einfach beide scanf Zeilen so das du vor dem %c noch ein Leerzeichen setzt:
scanf(" %c", &menue_eingabe);
Oder Alternativ noch zwischen den beiden Abfragen noch ein getchar() setzen das die überflüssigen Zeichen konsumiert/aufnimmt.
Gruß jodel32
Hallo pelzfrucht.
Ja, das '\n' bleibt im Eingabepuffer, korrekt. Noch verrückter wird es wenn du mehrere Zeichen eingegeben hast, denn dann bleibt nicht nur das '\n' sondern auch die vorherigen Zeichen im stdin stehen und warten darauf gelesen zu werden. Im Normalfall würdest du jetzt mit einer while Schleife die überflüssigen Zeichen ignorieren, beim Einlesen eines char musst du aber den Fall, dass nur Enter gedrückt wurde, ohne eine Eingabe zu tätigen, auch noch berücksichtigen.
Grüße
rubberman
Ja, das '\n' bleibt im Eingabepuffer, korrekt. Noch verrückter wird es wenn du mehrere Zeichen eingegeben hast, denn dann bleibt nicht nur das '\n' sondern auch die vorherigen Zeichen im stdin stehen und warten darauf gelesen zu werden. Im Normalfall würdest du jetzt mit einer while Schleife die überflüssigen Zeichen ignorieren, beim Einlesen eines char musst du aber den Fall, dass nur Enter gedrückt wurde, ohne eine Eingabe zu tätigen, auch noch berücksichtigen.
#include <stdio.h>
int main(void)
{
int menue_eingabe = 0, menue_eingabe2 = 0;
printf("\nEingabe 1: ");
menue_eingabe = getchar();
while (menue_eingabe != '\n' && getchar() != '\n');
printf("\nEingabe 2: ");
menue_eingabe2 = getchar();
while (menue_eingabe2 != '\n' && getchar() != '\n');
printf("\n\n==============================\n\nEingabe 1 ==> %c\nEingabe 2 ==> %c\n\n", menue_eingabe, menue_eingabe2);
return 0;
}
rubberman
warum != '\n'
Im Schleifenkopf steht die Bedingung. Ist sie WAHR, wird die Schleife abgearbeitet, ist sie FALSCH, wird die Schleife abgebrochen. Bedeutet für das Beispiel, sobald das '\n' gelesen wurde, wird die Schleife abgebrochen.Yay, der Tipp ist gold wert
Jein. Für deine Anforderung, nur das '\n' als 2. Zeichen zu ignorieren, ja. Aber: wenn der Benutzer fälschlicherweise mehrere Zeichen eingegeben hat, schlägt die Methode fehl (und Benutzer machen so etwas üblicherweise Gibts etwas ähnlich simples für "getchar();" ?
Nein.Aber wenn man das "Enter ohne Eingabe" Szenario rauslässt, müsste die gleiche Schleife nur mit dem "Nicht EOF" Vergleich trotzdem funktionieren?
Warum tut es das nicht?
Weil es kein EOF im stdin gibt. Auch in dem Fall musst du prüfen, ob das '\n' gelesen wurde. Lediglich der erste Teil (Prüfung ob bereits die Variable ein '\n' beinhaltet) würde entfallen.Warum tut es das nicht?
Grüße
rubberman
Wenn es kein EOF im stdin gibt
Hehe, das ist etwas schwierig zu verstehen. EOF wird nie erreicht, also wird getchar() erneut aufgerufen. Solange noch Zeichen im stdin liegen, werden diese ausgelesen. Liegen keine mehr im stdin, wartet getchar() auf eine Benutzereingabe. Wie du siehst, landest du so in einer Endlosschleife, die abwechselnd das '\n' aus der vorherigen Eingabe weg liest, um bei der nächsten Schleifeniteration wieder auf eine Benutzereingabe zu warten.Grüße
rubberman
Zitat von @rubberman:
Aber wenn man das "Enter ohne Eingabe" Szenario rauslässt, müsste die gleiche Schleife nur mit dem "Nicht EOF" Vergleich trotzdem funktionieren?
Warum tut es das nicht?
Weil es kein EOF im stdin gibt.Warum tut es das nicht?
Stimmt so nicht.
Natürlich gibt es ein EOF in stdin. Nämlich dann, wenn der User Ctrl-D drückt, oder wenn stdin aus einer Datei kommt, die Datei zu Ende ist.
Das Konstrukt des TO hat halt auf das Dateiende statt Zeilenende gewartet.
lks
Zitat von @rubberman:
Hallo lks.
)
Hallo lks.
wenn der User Ctrl-D drückt
Davon hab ich schon gehört. (Sorry bin auf Windows unterwegs ... Ctrl-Z?
oder wenn stdin aus einer Datei kommt
Wir reden von einer Benutzereingabe.Aber ja, grundsätzlich alles gültige Einwände, nur hier nicht wirklich relevant.
Doch - das ist hiier relevant, weil der User das Ding irgendwann vielleicht ein Programm mit diesen Kenntnissen erstellt und dann jemand anders das Ding mit Eingabedaten aus einer Pipe oder Eingabeumleitung füttert. Das ist dann der Stoff aus dem exploits gemacht werden.
lks
Hallo lks.

Aber OK, auch da kann man sich noch absichern.
getchar() soll ja schließlich nicht umsonst ein int zurückgeben ...
Einverstanden?
Grüße
rubberman
Ctrl-Z?
Yep Doch - das ist hiier relevant
Naja, da steht was von menue_eingabe
. Da wäre jetzt eine Umleitung aus einer Datei nicht gerade das erste, was mir einfallen würde while (menue_eingabe != '\n' && menue_eingabe != EOF && getchar() != '\n' && !feof(stdin));
getchar() soll ja schließlich nicht umsonst ein int zurückgeben ...
Einverstanden?
Grüße
rubberman
Zitat von @rubberman:
Naja, da steht was von
Naja, da steht was von
menue_eingabe
. Da wäre jetzt eine Umleitung aus einer Datei nicht gerade das erste, was mir einfallen würde Da hast Du aber bisher selten "Menüprogramme" für automatisches scripting verhackwurstelt.
Irgendwann kommt garantiert der Tag, an dem ein Schlippssträger den einfall hat, so ein Programm automatisiert haben zu wollen udn das möglichst vorgestern, weil man damit den Affen vor der tastatur sparen kann, der immer da sgleiche eintippt. Und da der ursprüngliche Programmierer nicht mehr greifbar ist, wird halt schnell irgendetwas zusammengestümpert, daß das Programm mit einer Eingabedatei füttert. und schon hat man eine wudnerscjöne Vorlage für einen exploit.
lks
Da hast Du aber bisher selten "Menüprogramme" für automatisches scripting verhackwurstelt.
Hehe, um ehrlich zu sein kenne ich nicht ein einziges menügeführtes, professionelles Konsole-Tool. In der *nixoiden Welt mag das aber anders sein.Irgendwann kommt garantiert der Tag, an dem ein Schlippssträger den einfall hat, so ein Programm automatisiert haben zu wollen udn das möglichst vorgestern, weil man damit den Affen vor der tastatur sparen kann...
Der verdient es dann aber auch, dass das in die Hose geht, oder? Grüße
rubberman
while (getchar() != '\n' && getchar() != EOF) { getchar(); }
Sollte ich jetzt schon verstehen wozu das EOF dient
Darin liegt kein großes Geheimnis. EOF ist ein Makro und mit dem Wert -1 definiert. EOF steht für "End Of File".Nun verstehst du vielleicht auch, warum alle C Funktionen, die ein char einlesen, ein int zurückgeben (und warum ich oben die Variablen als int deklariert habe). Anderenfalls wäre eine Unterscheidung zwischen dem char 0xFF und EOF aka -1 nicht möglich.
hab ich mal nachgefragt
Schadet nie.BTW Aus welchem Buch lernst du?
Grüße
rubberman
"C - Programmieren von Anfang an" von Helmut Erlenkötter.
Hmm, das Buch erfreut sich rätselhafterweise großer Beliebtheit. Das Wissen, das dort vermittelt wird ist aber etwa so alt wie ich. Ein main()
anstatt int main(void)
oder zumindest einer Deklaration mit int als Rückgabetyp ist K&R Style und bereits seit der ersten Standardisierung von C im Jahre 1989 obsolet.Das würde im Grunde heißen dass der Aufruf von getchar() ein Zeichen ausliest, was auch immer damit gemacht wird und es aus dem stdin löscht.
Richtig. So wie ich es oben schon geschrieben habe, liest jeder Aufruf von getchar() ein Zeichen aus dem stdin. Da es bereits im Schleifenkopf für den Vergleich aufgerufen wird, ist kein Schleifenrumpf/Anweisungsblock nötig. In dem Fall ist es also völlig in Ordnung wenn die Schleife gleich nach dem Kopf mit einem Semikolon abgeschlossen wird. So wird lediglich der Vergleich wiederholt und somit auch der Aufruf von getchar().Grüße
rubberman
sehr verständlich und einfach
Das wird wohl der Grund sein.Würdest du denn von dem Buch abraten?
Andere Bücher haben auch ihre Schwachstellen.Nimm dir aber zumindest die Errata des Autors an die Seite, gewöhne dir an, dass main() vom Typ int ist und mach dich im Nachgang noch einmal mit den Änderungen und Ergänzungen vertraut, die seit K&R C in den Standard gewandert sind.
Grüße
rubberman
Und jetz überlegen wir uns als Übung, welcher Denkfehler in diesem Konstrukt steckt und warum es trotzdem funktioniert.
lks
PS: Hint: Eingabe "AB\n" statt "B\n"
Hey lks,
das haben wir doch schon geklärt
Jeder Aufruf von getchar() frisst ein Zeichen aus dem stdin oder wartet auf Eingabe. Zusätzlich ist zu berücksichtigen, dass die Prüfung bzw. der Aufruf entsprechend eher abgebrochen wird. Bei der && Verkettung wird das 2. und 3. getchar() nicht aufgerufen, wenn das erste ein '\n' zurückgibt, das 3. getchar() wird nur aufgerufen, wenn die Bedingung aus dem Schleifenkopf erfüllt ist etc pp...
Mist ist das so trotzdem, da (zumindest unter Windows) nach Ctrl+Z noch ein Enter erfolgen muss, damit ein getchar() zurückgibt usw.
Sowas
fängt den ganzen Kram incl. deiner Einwände bei Dateiumleitung mit unabgeschlossener letzten Zeile noch am besten ab, wobei man die ersten beiden Prüfungen in ein vorgelagertes if Statement auslagern könnte ... Viele Wege führen nach Rom.
Grüße
rubberman
das haben wir doch schon geklärt
Mist ist das so trotzdem, da (zumindest unter Windows) nach Ctrl+Z noch ein Enter erfolgen muss, damit ein getchar() zurückgibt usw.
Sowas
while (menue_eingabe != '\n' && menue_eingabe != EOF && getchar() != '\n' && !feof(stdin));
Grüße
rubberman
Zitat von @rubberman:
Hey lks,
das haben wir doch schon geklärt
Jeder Aufruf von getchar() frisst ein Zeichen aus dem stdin oder wartet auf Eingabe.
Hey lks,
das haben wir doch schon geklärt
Nee noch nicht nicht ganz. worauf ich hinaus will, ist, daß wenn man dem Ding statt einem zeichen + newline zwei Zeichen plus newline gibt, wartet das Ding "endlos", weil getchar das newline von der getchar-Abrfage auf EOF gefressen wird.
lks