Hallo erstmal,
ich bin grade ganz am Anfang des lernens von C mittels folgenden Online
Lehrbuch:
http://openbook.rheinwerk-verlag.de/c_von_a_bis_z/index.htm#_top
Ich versuche das Buch durchzuarbeiten und dabei die Beispiele so weit
wie möglich auch zu verstehen. Jetzt bin ich auf eine Stelle gestoßen,
die ich leider nicht verstehe, daher hoffe ich das mir dies jemand
erklären kann. Es geht wohl um die Pufferung von Eingaben, ist Kapitel
4.1.2 des Buchs. Die Beispiele sind alle so vom Autor übernommen.
Folgendes Beispiel soll den Fehler zeigen, wenn man die Pufferung nicht
berücksichtigt:
1
/* scanf2.c */
2
#include<stdio.h>
3
4
intmain(void){
5
chara,b,c;
6
printf("1. Buchstabe : ");
7
scanf("%c",&a);
8
printf("2. Buchstabe : ");
9
scanf("%c",&b);
10
printf("3. Buchstabe : ");
11
scanf("%c",&c);
12
printf("Sie gaben ein : %c %c %c ",a,b,c);
13
return0;
14
}
Ich denke verstanden zu haben, dass hier durch den noch gespeicherten
Wert aus dem stdin die zweite Zeile zur Eingabe übersprungen wird. Jetzt
bietet der Autor folgende Lösungsansätze dafür:
Möglichkeit 1:
1
/* scanf3.c */
2
#include<stdio.h>
3
4
intmain(void){
5
chara,b,c;
6
printf("1. Buchstabe : ");
7
scanf("%c",&a);
8
fflush(stdin);
9
printf("2. Buchstabe : ");
10
scanf("%c",&b);
11
fflush(stdin);
12
printf("3. Buchstabe : ");
13
scanf("%c",&c);
14
printf("Sie gaben ein : %c %c %c ",a,b,c);
15
return0;
16
}
Möglichkeit 2:
1
/* scanf4.c */
2
#include<stdio.h>
3
4
intmain(void){
5
chara,b,c;
6
printf("1. Buchstabe : ");
7
do{scanf("%c",&a);}while(getchar()!='\n');
8
printf("2. Buchstabe : ");
9
do{scanf("%c",&b);}while(getchar()!='\n');
10
printf("3. Buchstabe : ");
11
do{scanf("%c",&c);}while(getchar()!='\n');
12
printf("%c %c %c\n",a,b,c);
13
return0;
14
}
Möglichkeit 3:
1
/* scanf5.c */
2
#include<stdio.h>
3
4
intmain(void){
5
charch;
6
charbuf[2];
7
8
printf("Ein Zeichen bitte : ");
9
fgets(buf,2,stdin);
10
sscanf(buf,"%c",&ch);
11
printf("Das Zeichen : %c\n",ch);
12
return0;
13
}
Die erste und zweite Möglichkeit funktionieren so und ich denke ich
verstehe auch warum. Im ersten wird der stdin nach der Eingabe gelöscht,
in der zweiten Möglichkeit wird die Abfrage nur gestartet, wenn kein
Newline mehr im Speicher ist.
Nun habe ich versucht die 3. Möglichkeit um eine weitere
Eingabeaufforderung zu verändern:
1
/* scanf2.c */
2
#include<stdio.h>
3
4
intmain(void){
5
charch;
6
charbuf[2];
7
charch2;
8
printf("Ein Zeichen bitte : ");
9
fgets(buf,2,stdin);
10
sscanf(buf,"%c",&ch);
11
// fflush(stdin);
12
printf("Zweites Zeichen bitte : ");
13
fgets(buf,2,stdin);
14
sscanf(buf,"%c",&ch2);
15
printf("Das Zeichen : %c %c \n",ch,ch2);
16
17
return0;
18
}
Dabei passiert wieder der gleiche Effekt, wie im Ausgangsbeispiel des
Autos, dass die zweite Eingabe nicht abgewartet wird, bzw der
Pufferspeicher noch belegt ist. Erst wenn ich wieder den Speicher
flushe, funktioniert das ganze wie gewollt. Nun erschließt sich mir
jedoch nicht, warum die Erweiterung nicht funktioniert, ohne den
Speicher zu flushen.
Leider zu früh auf den Antwortbutton gekommen, daher sry für den
Doppelpost. Ich wollte eigentlich noch fragen, mit welchem Datentyp ich
hierbei arbeiten müsste, bzw wie der Code angepasst werden muss, wenn
ich Beispielsweise ein Datum eingeben lassen will. Erstmal nur eine
Zeile z.B. als Input 13, die nächste 5 und die letzte 1995. Wenn ich das
mit dem aktuellen Code mache, dann gibt er immer nur das erste
eingegebene Zeichen von jeder Abfrage zurück.
C Anfänger schrieb:> Möglichkeit 1:
Kann man so machen.
Man könnte auch das Terminal umstellen, sodass es nicht mehr puffert.
Aber klar, du hast das Problem ja erkannt und das kannst du später immer
noch tun.
C Anfänger schrieb:> Möglichkeit 2:
Das ist Frickel.
Wenn der Benutzer auf die erste Frage zwei Zeichen eingibt, muss er auch
zweimal Return drücken, denn in jedem Schleifendurchlauf wird das scanf
ja auch wieder aufgerufen.
Vermutlich sollte es eher so aussehen(*):
1
scanf("%c",&a);while(getchar()!='\n');
C Anfänger schrieb:> Möglichkeit 3:
An und für sich ein sinnvoller Weg. Und sogar fgets benutzt (und nicht
das verbotene gets). Aber es ist halt falsch implementiert. Les dir mal
eine Beschreibung von fgets durch.
Vermutlich sollte es so aussehen (Puffer länger!):
1
charch;
2
charbuf[20];
3
4
printf("Ein Zeichen bitte : ");
5
fgets(buf,20,stdin);
6
sscanf(buf,"%c",&ch);
Mit buf[2] hast du dasselbe Problem wie eingangs: fgets wird nur exakt
ein einzelnes Zeichen lesen. Der Puffer hat zwar Platz für zwei Zeichen,
aber fgets braucht noch einen Platz für ein abschließendes 0-Zeichen.
1. Die Online-Version ist noch die 1. Auflage mit allen Fehlern.
2. Der Autor des Buches ist in anderen Foren nicht gerade beliebt.
3. fflush auf Eingabeströme (z.B. stdin) ist vom Standard nicht gedeckt.
Da kann alles Mögliche passieren. Windows macht da was. Linux nicht.
Alle Lösungen haben unterschiedliches Verhalten.
Das eigentliche Problem lässt sich einfach lösen: mit einem Leerzeichen
im Formatstring von scanf vor dem %c
C Anfänger schrieb:> Erstmal nur eine> Zeile z.B. als Input 13, die nächste 5 und die letzte 1995.
1
inttag,monat,jahr;
2
scanf("%d%d%d",&tag,&monat,&jahr);
Du kannst da nach jeder Zahl ein Enter machen oder alles in einer Zeile
mit Leerzeichen getrennt eingeben.
scanf benutzt bei die meisten Formatspecifiern sog. Whitespace als
Trennzeichen.
Aber gerade bei %c nicht, da du ja (möglicherweise) genau diese Zeichen
einlesen möchtest.
Das Leerzeichen im Formatstring sagt scanf "überlese alle Whitespace"
scanf lässt auch Zeichen, die nicht mehr zum Formatspecifier passen,
im Eingabestrom stehen, so dass sie bei nächsten mal eingelesen werden.
Das macht Probleme, wenn du Ziffern lesen willst, aber Buchstaben
eingibst.
Der Buchstabe verschwindet nicht aus dem Eingabestrom.
Dagegen hilft
1
intc;// int c, nicht char c.
2
while((c=getchar())!=EOF&&c!='\n');
Überlesen bis zum nächsten '\n' (Quelle:
https://www.c-plusplus.net/forum/39349 )
Das fflush(stdin) löscht alle bisher noch nicht eingelesenen Zeichen.
Ist aber nicht portabel.
fgets betrachtet das '\n' als Endekennung und liest es auch mit ein.
Danke erstmal für die Hilfe, ich bastel jetzt grade ein wenig damit
herum.
Wenn das eine alte Onlineversion ist und die scheinbar eh nicht den
besten Ruf hat, gibt es denn gute Alternativen? Ebook (muss nicht
zwingend kostenlos sein) oder als Online Lehrbuch würde mir sehr helfen.
Da kommen die Fragen
- deutsch und/oder englisch
- kannst du schon Programmieren (eine andere Sprache)
Es gibt keine guten, freien Online-Tutorials für C auf deutsch.
Wie es mit englisch und/oder kostenpflichtig aussieht, kann ich dir
nicht sagen.
Sicher gibt es mittlerweile auch die gedruckten Bücher als EBook
Eine englische Liste gibt es bei
http://stackoverflow.com/questions/562303/the-definitive-c-book-guide-and-list
Grade nochmal bissel gesucht, ich versuchs jetzt erstmal mit:
http://publications.gbdirect.co.uk/c_book/
Danke erstmal für die Hilfe, ich bin gespannt wie ich vorran komme :)