ein Kapitel zurück                                           ein Kapitel weiter

So jetzt können wir zwar schon Wörter und Zahlen auf dem Bildschirm ausgeben aber irgendwie fehlt doch noch was zur Eingabe um mehr mit unseren Programmen zu machen. Also auf zum Input-Befehl Namens 'scanf', das Gegenstück zu 'printf'. Hierzu erst einmal der Syntax zu scanf...

#include <stdio.h>

int scanf(const char *format, ...);

Mit der Funktion scanf können wir Werte, unterschiedlicher Datentypen, formatiert Einlesen. Eingelesen wird dabei von der Standard-Eingabe. Mit Standard-Eingabe ist die Tastatur gemeint. Bevor wir scanf etwas genauer betrachten wollen wir zuerst mit einem Beispiel beginnen...

/*Download:scanf.c*/
#include <stdio.h>

int main ()
{
int i;
printf("Bitte geben Sie eine Zahl ein : ");
scanf("%d",&i); /*Wartet auf Eingabe*/
printf("Die Zahl die sie eingegeben haben war %d\n",i);
return 0;
}

Nun wenn das Programm läuft wie es soll werden sie nach einer Zahl gefragt. Geben sie eine Zahl ein und drücken ENTER. Anschließend gibt das Programm die Zahl die sie eingegeben haben zurück und das Programm ist beendet.

Bildlich dürfen sie sich diesen Vorgang folgendermaßen vorstellen...

scanf


So bis zur Zeile scanf dürfte Ihnen alles noch bekannt vorkommen. Sehen wir uns scanf mal genauer an. scanf ist ähnlich aufgebaut wie printf.
Und wie auch bei printf werden hier zwei Klammern und zwei Hochkommata verwendet. Also formatiert eingelesen. Das Formatzeichen %d steht für die formatierte Eingabe einer dezimalen Zahl. Was aber bedeutet hier das Zeichen '&'.

Das Zeichen '&' jetzt schon besser zu verstehen kann nicht schaden. Später wenn wir auf das Thema Pointer ( Zeigern) zu sprechen kommen, wird Ihnen dieses Verständnis sehr helfen. Sollten Sie diesen Abschnitt mit dem Zeichen '&' nicht Verstanden haben, ist dies, vorerst, nicht so schlimm. Dies wird in einem späteren Kapitel noch ausführlicher behandelt.

Ein Variable kann man in vier einzelne Teile aufteilen....

Typ Name Adresse Wert

In unserem Programmbeispiel oben heißt das jetzt konkret, der Typ ist 'int', der Name ist 'i', die Adresse wird während der Laufzeit zugewiesen, darauf haben sie keinen Einfluss. Wir nehmen hier z.B. $0001. Der Wert ist der den sie mit 'scanf' noch eingeben müssen. Wenn sie jetzt z.B. 5 eingeben heißt das in unserem Fall...

Typ Name Adresse Wert
int i $0001 5

Das '&'- Zeichen ist in diesem Fall nichts anderes als der Adressoperator, das heißt der Variablen 'i' vom Typ 'int' mit der Adresse '0001' wird der Wert 5 zugewiesen. Oder einfacher: Verschicken sie mal eine E-Mail an jemanden ohne die E-Mailadresse anzugeben.

Jetzt haben sie gelernt wie es Möglich ist Interaktive Programme zu schreiben. Eine 2-Wege-Kommunikation mit dem Computer, wenn sie so wollen. Mit scanf lesen wir die Daten von Tastatur ein und mit printf geben wir diese auf dem Monitor aus.

Ein häufiger Fehler den Anfänger machen ist das weglassen das Adressoperators &. Was zwar im Falle zum Einlesen eines Strings (Zeichenkette) wieder richtig wäre ist bei anderen Datentypen wie Dezimal.-oder-Gleitpunktzahlen wieder falsch...

scanf("%d",zahl);  //FALSCH da Adressoperator & fehlt

scanf("%s",string);  //Richtig Zeichenkette benötigt keinen Adressoperator


Auch wenn scanf das Gegenstück zu printf ist und sich beide in Ihrer Schreibweise ähneln, kommen sie bitte nicht auf die Idee folgendes zu schreiben....

scanf("Bitte geben sie eine Zahl ein : %d\n",&zahl);  //FALSCH

Das kommt daher weil scanf für die Standard-Eingabe programmiert ist und printf für die Standardausgabe. Wobei wir die Standardausgabe auf der Kommandozeile umleiten könnten. Aber dazu später mehr.


Für Fortgeschrittene zum Nachschlagen :

Eine häufiges Problem das Auftritt wenn sie scanf für die Eingabe verwenden, ist die Pufferung. Die je nach System und Anwendung Zeilen.-oder-Vollgepuffert sind. Dies gilt wiederum nicht für die Standardfehlerausgabe (stderr), die laut ANSI-C, niemals Vollgepuffert sein darf. Bevor ich weitererkläre testen testen sie folgendes Programm...

/*Download:scanf1.c*/
#include <stdio.h>

int main()
{
char a,b,c,tmp;

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 dürfte nun passiert sein...

1. Buchstabe : z
2. Buchstabe : 3.Buchstabe : x
Sie gaben ein : z
x
prompt>_


Was ist passiert? Warum wird der 2.Buchstabe immer übersprungen? Wie gesagt das Problem liegt hier an der Pufferung. Und C kennt nun mal keinen Befehl wie bei Perl chomp um das letzte Zeichen zu entfernen.
In unserem Beispiel haben wir als 1.Buchstaben z eingegeben und ENTER gedrückt. Und dieses ENTER (\n) befindet sich immer noch im Puffer der Standardeingabe und wird automatisch für das 2.Zeichen verwendet.
Was kann man nun dagegen tun? Sie haben 4 Möglichkeiten.

1.Möglichkeit :
Alle 3 Buchstaben auf einmal eingeben...

/*Download:scanf2.c*/
#include <stdio.h>

int main()
{
char a,b,c,tmp;

printf("1.2. und 3. Buchstabe : ");
scanf("%c %c %c",&a,&b,&c);
printf("Sie gaben ein : %c %c %c ",a,b,c);

return 0;
}


2.Möglichkeit :
Sie benutzen die Funkion fflush zum entleeren des Tastatur-Puffers. Was aber wiederum nicht überall funkioniert...

/*Download:scanf3.c*/
#include <stdio.h>

int main()
{
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;
}


3.Möglichkeit :
Wir basteln uns eine eigene Wrapper - Funktion die dies Problem behebt...

/*Download:scanf4.c*/
#include <stdio.h>

char Scanf(char *z)
{
char newline;
scanf("%c%c",z,newline);
}


int main()
{
char a,b,c;

printf("1. Buchstabe : ");
Scanf(&a);
printf("2. Buchstabe : ");
Scanf(&b);
printf("3. Buchstabe : ");
Scanf(&c);

printf("Sie gaben ein : %c %c %c ",a,b,c);

return 0;
}

Ein Wrapper ist nichts anderes als eine Funktion die eine andere Funktion überlagert. Wir überlagern hier ganz einfach scanf mit unserer Wrapper-Funktion Scanf. Die Funktion ließt einfach das Zeichen von Tastatur ein. Insklusive das Newline-Zeichen, was aber in der Funktion bleibt. Und sobald wir diese Funktion wieder verlassen existiert der Inhalt von newline nicht mehr.


4.Möglichkeit :
Wir benutzen eine do-while-Schleife und ziehen das newline-Zeichen aus dem Puffer heraus.......

/*Download:scanfx.c*/
#include <stdio.h> int main() { 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; }




5.Möglichkeit :
Die letzte Möglichkeit ist, scanf gar nicht einzusetzen und stattdessen auf eine der Vielen anderen elementaren Standard-Eingabe-Funktionen zurückgreifen.


Überprüfen auf das richtige Format :
Um sicher zu gehen ob der Benutzer das richtige eingegeben hat, müssen wir den Rückgabewert von scanf überprüfen...

/*Download:check.c*/
#include <stdio.h>

int main()
{
char a;
int b,check;

printf("Eingabe machen : ");
check=scanf("%c %d",&a,&b);
printf("Check = %d \n",check);

return 0;
}

Folgende Ausgaben könnten auftreten...

Eingabe : a 44
Check = 2
Eingabe : w W
Check = 1


Der Rückgabewert ist immer Anzahl der Richtig eingegebenen Formate. Mit einer kleine Überprüfung können sie das ganze noch Verbessern um undefiniertes Verhalten für die Weiterarbeit des Programms zu verhindern...

/*Download:check2.c*/
#include <stdio.h>

int main()
{
int a,b,check;
char newline;

printf("Bitte zwei Zahlen eingeben : ");
check=scanf("%d %d",&a,&b);

if(check==2)
printf("Beide Zahlen richtig %d und %d\n",a,b);
else if(check==1)
{
printf("Die 2.Zahl hat das falsche Format!!\n");
printf("Bitte Eingabe wiederholen : ");
scanf("%c",&newline); /*Entfernt das Zeichen \n */
if(check=scanf("%d",&b))
printf("Eingabe Ok. Ihre Zahl %d %d\n",a,b);
else
printf("Was ist so schwer daran ein Zahl einzugeben?\n");
}
else
printf("Die 1. oder beiden Eingaben waren falsche!!!\n");

return 0;
}

Sollten sie keine Probleme mit dem Tastatur-Puffer haben entfernen sie die Zeile...

scanf("%c",&newline);

...die nur dafür sorgt das Newline-Zeichen aus dem Tastatur-Puffer zu ziehen.

Aufgabe :
Was ist an diesem Programm falsch?

#include <stdio.h>

int main()
{
int alter, groesse, gewicht;
printf("Wie alt sind Sie :");
scanf("%d",alter);
printf("Wie gross sind Sie:");
scanf("%d",groesse);
printf("Wie schwer sind Sie:");
scanf("%d",gewicht);
printf("Ihr Alter %d, ihre Grösse: %d, ihr Gewicht %d\n" ,alter,groesse,gewicht);
return 0;
}

Hier gibt es die Lösung!

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf