5.2 Probleme und deren Behandlung mit scanf()
 
Ein häufiges Problem, das auftritt, wenn Sie scanf() für die Eingabe verwenden, ist die Pufferung. Diese ist je nach System und Anwendung zeilen- oder vollgepuffert. Dies gilt wiederum nicht für die Standardfehlerausgabe (stderr), die laut ANSI C niemals vollgepuffert sein darf. Bevor ich dies weiter erkläre, folgendes Programm zum Testen:
/* scanf2.c */
#include <stdio.h>
int main(void) {
char a,b,c;
printf("1. Buchstabe : ");
scanf("%c",&a);
printf("2. Buchstabe : ");
scanf("%c",&b);
printf("3. Buchstabe : ");
scanf("%c",&c);
printf("Sie gaben ein : %c %c %c ",a,b,c);
return 0;
}
Folgendes könnte nun vom Programm auf den Bildschirm ausgegeben werden:
 Hier klicken, um das Bild zu Vergrößern
Abbildung 5.4
Ein mögliches Problem mit scanf unter Linux
Was ist hier passiert? Warum wird der zweite Buchstabe immer übersprungen? Wie gesagt, das Problem ist hier die Pufferung. Und in C gibt es keinen Befehl (wie etwa chomp bei Perl), um das letzte Zeichen zu entfernen.
In diesem Beispiel wurde als erster Buchstabe »a« eingegeben und (¢) gedrückt. Dieses (¢) (ASCII-Code = 10 = \n = newline) befindet sich immer noch im Puffer der Standardeingabe und wird automatisch für das zweite Zeichen verwendet. Was können Sie dagegen tun? Hierzu ein paar Möglichkeiten, die allerdings auch systemabhängig sind:
5.2.1 Möglichkeit 1
 
Sie benutzen die Funktion fflush() zum Entleeren des Tastaturpuffers. Möglicherweise gelingt dies nicht auf jedem Betriebssystem (speziell nicht unter Linux):
/* scanf3.c */
#include <stdio.h>
int main(void) {
char a,b,c;
printf("1. Buchstabe : ");
scanf("%c",&a);
fflush(stdin);
printf("2. Buchstabe : ");
scanf("%c",&b);
fflush(stdin);
printf("3. Buchstabe : ");
scanf("%c",&c);
printf("Sie gaben ein : %c %c %c ",a,b,c);
return 0;
}
5.2.2 Möglichkeit 2
 
Sie benutzen eine do while-Schleife und ziehen das Newline-Zeichen aus dem Puffer heraus:
/* scanf4.c */
#include <stdio.h>
int main(void) {
char a,b,c;
printf("1. Buchstabe : ");
do {scanf("%c",&a);} while ( getchar() != '\n' );
printf("2. Buchstabe : ");
do {scanf("%c",&b);} while ( getchar() != '\n' );
printf("3. Buchstabe : ");
do {scanf("%c",&c);} while ( getchar() != '\n' );
printf("%c %c %c\n",a,b,c);
return 0;
}
Mehr zur do while-Schleife finden Sie in Kapitel 10. Dieses Beispiel lässt sich natürlich auch mit einer while()-Schleife als Makro verpackt realisieren:
#define Fflush(int_keyboard_buffer)\
while(( (int_keyboard_buffer) = getchar()) != '\n')
Mehr zu diesem Beispiel erfahren Sie in Kapitel 12, Präprozessor-Direktiven.
5.2.3 Möglichkeit 3
 
Sie verwenden scanf() erst gar nicht und greifen auf eine der vielen anderen Standardeingaben-Funktionen zurück. Ideal wäre es beispielsweise, die Funktion fgets() zum Einlesen zu verwenden und diese Eingabe mit der Funktion sscanf() in ein entsprechendes Format zu konvertieren. Entsprechendes Beispiel könnte so aussehen:
/* scanf5.c */
#include <stdio.h>
int main(void) {
char ch;
char buf[2];
printf("Ein Zeichen bitte : ");
fgets(buf, 2, stdin);
sscanf(buf, "%c", &ch);
printf("Das Zeichen : %c\n",ch);
return 0;
}
Hinweis Im Laufe dieses Buchs wird noch des Öfteren die Funktion scanf() verwendet. Sollte etwas nicht so funktionieren, wie es sollte, beziehen Sie sich auf dieses Kapitel.
|
Achtung Die Funktion scanf() ist nicht gegen einen Pufferüberlauf (Buffer Overflow) geschützt und somit unsicher, d.h., sie könnte für einen Hack des Programms durch eine andere Person missbraucht werden. Damit ist gemeint, dass die Funktion nicht die Anzahl der eingegebenen Zeichen überprüft und es damit zu Fehlern kommen kann bzw. ein Fehlverhalten von außen provoziert werden kann.
|
|