Leyla S. schrieb:
> Warum braucht man die do while Schleife hier nicht, aber in diesem Code
> beim Einlesen von drei Zeichen? Wenn ich do entferne klappt das Programm
> immer noch.
****** ACHTUNG: Update geenüber dem vorhergehenden (und mitlerweile
gelöschten) Posting *********
Weil das %d den noch vorhandenen \n aus dem Eingabestrom entfernt, was
ein %c nicht tut.
OK, Machen wir ein Gedankenexperiment.
Du bist Computer. Du hältst dich exakt an die Regeln.
Bei einem %d liest du, wobei deine Lesestrategie so aussieht:
wenn im Eingabestrom ein Leeerzeichen oder ein \n kommt, dann
überliest
du das einfach. Solange bis du auf etwas stösst was kein derartiges
Whitespace Zeichen ist. Alles danach folgende versuchst du Zeichen für
Zeichen zu einer Zahl zusammenzusetzen, so lange bis du auf etwas
stösst
was ganz sicher nicht mehr zur Zahl gehören kann. Das lässt du dann im
Eingabestrom übrig, so dass sich die nächste Leseoperation mit diesem
Zeichen beschäftigen kann.
Bei einem %c liest du genau 1 Zeichen vom Eingabestrom. Egal was dieses
Zeichen tatsächlich ist. Genau eines und nicht mehr
Dein Eingabestrom sei die Zeichenfolge
und die Operationen sind
1 | scanf( "%d", &i );
|
2 | scanf( "%d", &j );
|
3 | scanf( "%c", &c );
|
wie läuft da die Abarbeitung und welche Werte landen in welchen
Variablen?
Fang so an
Der erste scanf( "%d", &i ) ist drann.
Aus dem Eingabestrom
wird das erste Zeichen geholt. Das hier
Das ist ein Leerzeichen. Getreu Vorschrift ignoriert der %d dieses
Leerzeichen und holt sich das nächste zeichen. Das ist dann das hier
Wieder ein Leerzeichen. Laut Vorschrift wird auch das ignoriert und
weiter gelesen. Das nächste Zeichen ist ein \n
wieder: wird ignoriert. Nächstes Zeichen
Aha. Das Zeichen '3'. Damit ist die Ignorierphase für Whitespace vorbei.
Ab jetzt gilt: es wird solange bearbeitet, solange das Zeichen zu einer
int-Zahl gehören kann. '3' kann Teil eines int sein, daher gehört es zur
Zahl. Nächstes zeichen
'4'. Passt. Kann zur Zahl gehören. Die Zahl könnte als 34 sein. Nächstes
Zeichen
'5'. Kann immer noch zur Zahl gehören. Die Zahl wäre also 345. Nächstes
Zeichen
Ein Leerzeichen. Nope. Das kann ganz sicher nicht mehr zur Zahl gehören.
D.h. die Zahl war 345. Damit ist der erste scanf, bzw. sein %d
abgearbeitet und der nächste kommt zum Zug
1 | ...
|
2 | scanf( "%d", &j );
|
3 | ...
|
wieder ein %d.
Wie immer bei einem %d beginnt auch der damit, Whitespace (also
Leerzeichen, tabulatoren und Zeilenvorschub zu ignorieren. Das ist seine
Strategie. Mal sehen, wo waren wir?
1 | [code]
|
2 | \n345 \n765\na
|
3 | ^
|
4 | *
|
Ein Leerzeichen. Passt. wird ignoriert. Näächstes Zeichen
Ein \n. Wird ignoriert. Nächstes
EIn '7'. D.h. es taucht das erste mal ein nicht Whitespace Zeichen auf.
Damit ist die Ignorierphase beendet. Die Zahl hat begonnen und könnte 7
sein. Nächstes Zeichen
Ein '6'. Passt zu einem int. Zahl könnte also 76 sein. Nächstes Zeichen
'5'. passt immer noch. Zahl könnte 765 sein. Nächstes
Ein \n. Nope der passt nicht mehr. Die Zahl war also 765 und mit dem \n
soll sich die nächste Eingabeoperation rumschlagen.
Damit ist dieser scanf beendet und der nächste kommt drann.
1 | ...
|
2 | scanf( "%c", &c );
|
Achtung: Das ist jetzt ein %c!
Der funktioniert anders. Der liefert einfach nur das nächste zeichen.
Egal was das ist.
nun, welches ist das?
Der \n. Ganz klar. D.h. der %c gibt sich mit dem \n zufrieden. Das ist
das nächste Zeichen und das liefert er.
Nur: Das war nicht ganz das, was du eigentlich wolltest. Du warst auf
das 'a' aus, das da in der Eingabe noch wartet. Daher: Du musst das \n,
welches noch im Eingabestrom noch lauert gezielt überlesen. Bzw. wenn
die Eingabe
gelautet hätte, dann eben auch noch all die Leerzeichen bis zu (und
inklusive) dem \n. Denn erst dann ist das nächste zeichen ein 'a' und
der
1 | ...
|
2 | scanf( "%c", &c );
|
würde das dann auch nach c lesen.