[Pascal] Computer "überspringt" read-Anweisungen anstatt auf Eingabe zu warten

Zweipunktnull

Commander
Registriert
Dez. 2004
Beiträge
2.546
Hallo,

ich habe ein kleines Problem mit einem Pascal-Programm. Wir haben im Informatikkurs den Datentyp record kennen gelernt und nun erste Übungsaufgaben zu diesem Thema bekommen. Unser Lehrer hat uns dazu amüsante Aufgaben aus einem Buch aus dem Jahre 1980 kopiert. Auf den Arbeitsblättern sind die Quelltexte der Programme praktisch komplett abgedruckt. Typendeklaration, Variablendeklaration, Prozeduren und Hauptprogramm sind vorgegeben und müssen "nur" noch in die Tastatur gehauen werden. Aber das ist leichter gesagt als getan, da die Quelltexte so dermaßen fehlerhaft sind, dass ich diese Schulbücher verbieten würde. Ich musste bereits etliche Fehler korrigieren, damit das Programm überhaupt einmal kompiliert werden kann. Ich habe jedoch noch immer mit einem Fehler zu kämpfen, dessen Ursache ich leider nicht finden kann.

Nach einer gewissen Zeit "überspringt" der Computer immer einige read-Anweisungen anstatt auf eine Eingabe zu warten. Ich habe einen Screenshot angehangen, auf dem man denke ich sehr gut erkennen kann, was ich genau meine.

Code:
program heiratsinstitut;

uses crt;

const
  n = 10;

type
  geschlecht = (maennlich, weiblich);
  hobby = (garten, basteln, sport, literatur, musik);
  kunde = record
    nameadresse: string;
    sex: geschlecht;
    alter: 18..80;
    interessen: set of hobby;
  end;

var
  neukunde: kunde;
  s: 1..n;
  kartei: array[1..n] of kunde;

procedure eingabe(var k: kunde);

  var
    antw: char;
    a: 0..100;
    int: hobby;

  begin

    write('Name und Adresse: ');
    readln(k.nameadresse);
    repeat
      write('Geschlecht? (m/w) ');
      readln(antw);
    until antw in ['m', 'w'];
    if antw = 'm'
    then k.sex := maennlich
    else k.sex := weiblich;
    write('Alter: ');
    read(a);
    if a < 18
    then writeln('Sie sind zu jung')
    else if a > 80
         then writeln('Sie sind zu alt')
         else k.alter := a;
    writeln('Interessen:');
    k.interessen := [];
    for int := garten to musik do
      case int of
        garten: begin
          write('Garten? (j/n)? ');
          read(antw);
          if antw = 'j'
          then k.interessen := k.interessen+[int];
        end;
        basteln: begin
          write('Basteln? (j/n)? ');
          read(antw);
          if antw = 'j'
          then k.interessen := k.interessen+[int];
        end;
        sport: begin
          write('Sport? (j/n)? ');
          read(antw);
          if antw = 'j'
          then k.interessen := k.interessen+[int];
        end;
        literatur: begin
          write('Literatur? (j/n)? ');
          read(antw);
          if antw = 'j'
          then k.interessen := k.interessen+[int];
        end;
        musik: begin
          write('Musik? (j/n)? ');
          read(antw);
          if antw = 'j'
          then k.interessen := k.interessen+[int];
        end;
      end;

  end;

function harmonisch(k1, k2: kunde): boolean;

  begin

    harmonisch :=
      (k1.sex <> k2.sex) and
      (abs(k1.alter-k2.alter) < 10) and
      (k1.interessen*k2.interessen <> []);

  end;

begin

  clrscr;
  writeln('Dateneingabe der Kartei');
  for s := 1 to n do
    eingabe(kartei[s]);
  writeln('Dateneingabe des neuen Kunden');
  eingabe(neukunde);
  for s := 1 to n do
    if harmonisch(neukunde, kartei[s])
    then writeln(kartei[s].nameadresse);
  readln;

end.
 
Zuletzt bearbeitet:
Wenn du erstmal auf jegliche Fehlerprüfung verzichten willst kannst du es so machen:
Code:
antw := readKey;
Für Fehlerbehandlung würde ich das ganze dann in eine repeat-until Schleife setzen, in der ich nach dem Einlesen den Wert auf 'j' oder 'n' prüfe (Oder was auch immer für eine Taste gedrückt werden soll. Das könnte dann so aussehen:
Code:
repeat
  antw := readKey;
until antw = 'j' or antw = 'n';
if antw = 'j' then
  k.interessen := k.interessen+[int];
 
Zuletzt bearbeitet:
Ich persönlich würde das Programm auch ein wenig anders realisieren, jedoch meinte unser Lehrer, wir sollen es erst einmal genauso programmieren, wie es auf dem Arbeitsblatt abgedruckt ist. Die abgedruckten Schnipsel sind augenscheinlich fehlerhaft und müssen ein wenig korrigiert werden. Jedoch wollte ich die Struktur des Programms weitgehend beibehalten.

Die Frage ist ja auch, wieso passiert das überhaupt, was da passiert? Ich finde dafür keine logische Erklärung, wieso einfach drei Hobbys auf einmal ausgegeben werden ohne auf eine Eingabe zu warten. Die case-Anweisung ist doch vollkommen korrekt, oder?
 
Das einzige, was da zwischen funken könnte, wäre der Tstaturpuffer. wenn der nicht leer ist, denkt die read-Funktion, "Ich hab was eingelesen", ohne das es auf dem Bldschirm auftaucht.

Prüf mal, ob das der Fall ist. Dazu einfach nach jedem read-Aufruf ein "write(antw);" Wenn dann mehr Zeichen ausgegeben werden als ohne den Aufruf, dann musst du vor jedem auslesen erstmal den Puffer leeren. Das geht z.B. mit
Code:
begin
  inline($FA);
  memw[$40 : $1A] := memw[$40 : $1C];
  inline($FB);
end;
 
Du hast Recht, es werden Whitespaces und anderer Plunder ausgegeben. Dein Code-Schnipsel sorgt jedoch dafür, dass die Kompilierung fehlschlägt.
 
Zuletzt bearbeitet:
Ich habs mir grade nochmal angeguckt. Das Problem liegt darin, daß FreePascal Programme für den sog. Protected Mode liefert. Es hat die Prozedur inline nicht und auch kein Array memw.

Die einzige Lösung, die ich gefunden habe ist folgende:
Es gibt von FreePascal die Version DOS/Go32v2. Die unterstützt das (außer der inline-Prozedur).

Wenn du die benutzt, sollte folgendes funktionieren:
Code:
asm
  cli
end;
memw[$40 : $1A] := memw[$40 : $1C];
asm
  sti
end;
 
Dieser Code funktioniert ebenfalls nicht. Die Kompilierung bricht mit der Fehlermeldung "Identifier not found memw" ab. Na ja, mache dir keine weitere Mühe mehr. Ich denke nicht, dass unser Lehrer das verlangen kann. Wir haben schließlich noch nie etwas von einem Tastaturpuffer gehört. Des Weiteren verstehe ich deinen Code noch nicht einmal ansatzweise. ;)
 

Ähnliche Themen

Zurück
Oben