Get_Line nach Get
Es kommt häufig vor, dass zunächst eine
Zahl gelesen wird und danach ein Text
(String). Die Semantik der
Unterprgrogramme aus den Ada
Standardbibliotheken können hier
überraschende Effekte haben.
Sämtliche Eingabe, die z.B. über die
Tastatur eingegeben wird, wird zunächst
zwischengespeichert. Aus Sicht eines
Ada-Programms existiert also eine Sequenz
verfügbarer Zeichen, die nacheinander aus
dem Zwischenspeicher herausgenommen werden
können. Leerzeichen, Zeilenumbrüche
u.ä. (White Space ) sind
dabei ebenfalls Zeichen.
Semantik von Get
Die Prozedur
Ada.Integer_Text_IO.Get liest
aus der Eingabe solange White Space, bis
eine Ziffernfolge kommt oder ein anderes
Zeichen angetroffen wird und zu einem
Lesefehler führt. Direkt nach dem Lesen
der Ziffernfolge stoppt Get
insbesondere bleibt also ein Zeilenumbruch
direkt nach der Ziffenfolge in der
Eingabesequenz.
Gibt ein Benutzer eine Zahl ein, so
drückt er nach Ende der Eingabe die
Return-Taste. Diese hat zur Folge, dass
dieser abschließende Zeilenumbruch in die
Eingabe gelangt (und nach Aufruf von
Ada.Integer_Text_IO.Get dort
auch bleibt)
Semantik von Get_Line
Die Prozedur
Ada.Text_IO.Get_Line liest
soviele Zeichen aus der Eingabe, bis
entweder die übergebene String-Variable
voll ist oder ein
Zeilenumbruch gelesen wurde.
Problem
Da Ada.Integer_Text_IO.Get
einen Zeilenumbruch in der Eingabe stehen
lässt und
Ada.Text_IO.Get_Line nur bis
zum nächsten Zeilenumbruch liest, ist der
von Get_Line zurückgegebene
Text nur das Ende der Zeile hinter der
Zahl.
Beispiel (falsch):
with Ada.Integer_Text_IO;
with Ada.Text_IO;
procedure Bad
is
Buffer : String (1 .. 256);
Last : Natural;
Num : Integer;
begin
Ada.Text_IO.Put ("Zahl: ");
Ada.Integer_Text_IO.Get (Num);
Ada.Text_IO.Put ("Text: ");
Ada.Text_IO.Get_Line (Buffer, Last);
Ada.Text_IO.Put_Line ("Gelesen (Zahl):" & Integer'Image (Num));
Ada.Text_IO.Put_Line ("Gelesen (Text): " & Buffer (Buffer'First .. Last));
end Bad;
Eingabe:
123
Ablauf:
Zahl: 123
Text: Gelesen (Zahl): 123
Gelesen (Text):
Eingabe:
123 abcde
Ablauf:
Zahl: 123 abcde
Text: Gelesen (Zahl): 123
Gelesen (Text): abcde
Lösung
Um diesem Problem vorzubeugen sollte die
Prozedur
Ada.Text_IO.Skip_Line
verwendet werden. Sie löscht Zeichen aus
der Eingabe solange bis ein Zeilenumbruch
gelöscht wird oder die Eingabe leer ist.
Beispiel (korrigiert):
with Ada.Integer_Text_IO;
with Ada.Text_IO;
procedure Good
is
Buffer : String (1 .. 256);
Last : Natural;
Num : Integer;
begin
Ada.Text_IO.Put ("Zahl: ");
Ada.Integer_Text_IO.Get (Num);
Ada.Text_IO.Skip_Line;
Ada.Text_IO.Put ("Text: ");
Ada.Text_IO.Get_Line (Buffer, Last);
Ada.Text_IO.Put_Line ("Gelesen (Zahl):" & Integer'Image (Num));
Ada.Text_IO.Put_Line ("Gelesen (Text): " & Buffer (Buffer'First .. Last));
end Good;
Eingabe:
123
abcde
Ablauf:
Zahl: 123
Text: abcde
Gelesen (Zahl): 123
Gelesen (Text): abcde
Eingabe:
123 xyz
abcde
Ablauf:
Zahl: 123 xzy
Text: abcde
Gelesen (Zahl): 123
Gelesen (Text): abcde
|