![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() ![]()
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...
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...
|
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...
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*/ |
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*/ |
2.Möglichkeit :
Sie benutzen die Funkion fflush zum entleeren des Tastatur-Puffers.
Was aber wiederum nicht überall funkioniert...
/*Download:scanf3.c*/ |
3.Möglichkeit :
Wir basteln uns eine eigene Wrapper - Funktion die dies Problem behebt...
/*Download:scanf4.c*/ |
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*/ |
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*/ |
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*/ |
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> |
Hier gibt es die Lösung!