Hi Leute,
Ich sitz gerade an einem C Projekt und muss dazu sagen, dass ich ein
ziemlicher Anfänger in C bin.
Das konkrete Problem sieht so aus, dass mein Programm auffordert,
verschiedene Werte einzugeben und dann Berechnungen dazu anstellt.
wir haben jetzt nach einigen fehlversuchen, bei denen char Variabeln
"falsch" eingelesen wurden, festgestellt, dass bei einem scanf befehl
auf einen char, zuerst das letzte "Enter" eingelesen wird, das noch von
der Bestätigung der letzten Eingabe "im Raum schwebt". Der einzige
Lösungansatz, den wir ergoogeln konnten ist, die "Enter" mit getchar()
abzufangen und quasi ins Nirvana zu schicken.
Aber gibts da keine elegantere Lösung?
Wäre sehr froh über eure Hilfe,
Grüße
Sascha
Am besten den Code zeigen und das OS nennen.
Aber allgemein ist <return> auch ein Zeichen - und nicht ausschliesslich
, wie man spontan annehmen könnte - irgendein "Kontrollknopf für das
System" der Eingaben beendet.
Da Ihr, - wie ich ohne den Code nur annehmen kann -, ein einzelnes
Zeichen mit scanf lest, gibt das System zwar ein einzelnes Zeichen
weiter; es ist zunächst etwas verwirrend, dass <return> noch dazu auch
diesen Weitergabe-Vorgang anstösst. Aber das <return->-Zeichen ist immer
noch im Buffer und wird daher beim nächsten scanf eines Zeichens, als
nächstes weitergegeben.
printf("Sie waren zu dumm, die erste Eingabe zu verstehen. Bitte fahren Sie das System herunter und benutzen Sie nie wieder einen PC\n");
34
}
35
}
36
printf("Moechten Sie beenden?\n");
37
/**getchar();**/
38
scanf(" %c",&c);
39
getchar();
40
}while(c!='j');
41
}
Also das ist der Code. wir sind jetzt darauf gekommen, dass wir die
ersten 2 getchar() nicht mehr brauchen, da wir einfach bei scanf vor der
flag eine leerstelle lassen, die dann das return frisst. komischerweise
funktioniert es aber andersrum nicht, also mit leerstelle nach der flag.
daher muss das letzte getchar auch nach wie vor aktiv bleiben, da unsere
variable c ansonsten im nächsten loop direkt wieder mit return belegt
werden würde und das programm dann nicht mehr funktioniert.
Nun. Ich muss da mal grinsen. :-}
Das ist, meiner Meinung nach, allenfalls ein "Würgaround", auf den Ihr
durch raten gekommen seid, aber keine gedankliche Ableitung aus der
Beschreibung von scanf oder getc. (Offen gesagt, ist mir das noch nie
begegnet und ich habe es auch nie selbst so gemacht).
Als Lehrer würde ich das, ohne eine Erklärung, wie sich das aus der
Spezifikation und Implementierung von scanf ergibt, um eine Note
abwerten.
Ihr habt hier vier Möglichkeiten (abgesehen von Eurer Lösung):
1. Renès Lösung mit getline, wenn Ihr nichts verstehen wollt, sondern
nur die Aufgabe lösen.
2. Die Implementierung von getline anschauen - um zu lernen wie das
zusammenhängt. Kann zu Punkt 3 oder 4 führen.
3. Versuchen, das Problem korrekt (wie ich meine) mit scanf/flush bzw.
dem Terminal-Mode zu lösen - nicht einfach aber lehrreich.
4. Eine eigene, explizit hingeschriebene Lösung mit getc implementieren
- nicht einfach, aber lehrreich.
Sascha schrieb:> Also das ist der Code. wir sind jetzt darauf gekommen, dass wir die> ersten 2 getchar() nicht mehr brauchen, da wir einfach bei scanf vor der> flag eine leerstelle lassen, die dann das return frisst. komischerweise> funktioniert es aber andersrum nicht, also mit leerstelle nach der flag.> daher muss das letzte getchar auch nach wie vor aktiv bleiben, da unsere> variable c ansonsten im nächsten loop direkt wieder mit return belegt> werden würde und das programm dann nicht mehr funktioniert.
Schreib vor jedem %c bei scanf ein Leerzeichen (auch bei dem hinter dem
do).
Vor dem %lf braucht es nicht stehen, da %f automatisch Whitespace
überliest.
Theor schrieb:> Als Lehrer würde ich das, ohne eine Erklärung, wie sich das aus der> Spezifikation und Implementierung von scanf ergibt, um eine Note> abwerten.
In den Beschreibung zu scanf steht sehr wohl, dass jede Art von
Whitespace im Formatstring eben diese überliest.
Es spielt keine Rolle ob da eine Leerzeichen steht oder ein \n (oder ein
\r oder ein \t).
Theor schrieb:> 3. Versuchen, das Problem korrekt (wie ich meine) mit scanf/flush
fflush auf stdin ist nicht vom Standard gedeckt.
Dirk B. schrieb:> Theor schrieb:>> 3. Versuchen, das Problem korrekt (wie ich meine) mit scanf/flush>> fflush auf stdin ist nicht vom Standard gedeckt.
Macht bei Input-Streams auch eigentlich wenig Sinn.
Ich würde sowas machen wie:
1
while(getchar()!='\n')
2
;
Dann hab ich alles, was in der Zeile noch vielleicht so rumstand,
verworfen, egal ob whitspace oder nicht, und ich kann in der nächsten
Zeile sauber neu aufsetzen.
Wenn man das Ganze in eine hübsche Funktion verpacken will, dann sollte
man dafür sorgen, dass der Buffer die Lebenszeit des Aufrufes überlebt
(Stichwort: static).
(s)scanf() kann eine sinnvolle Funktion zum Parsen von Dateien oder
anderen Datenquellen sein. Für das Lesen von stdin ist sie weniger
geeignet.