Ärger mit der Sichtbarkeit(?) in Turbo-Pascal Objekten

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
alfware17
Beiträge: 214
Registriert: Di 14. Dez 2010, 23:27

Ärger mit der Sichtbarkeit(?) in Turbo-Pascal Objekten

Beitrag von alfware17 »

Hallo zusammen,
ich bin ein wenig ratlos wegen eines Fehlers in einem Programm, den ich ehrlich gesagt so nicht verstehe. Ich gebe zu, ich habe zwar ein wenig mit Objekten in Lazarus und anderen Programmiersprachen gearbeitet, aber nicht in Turbo-Pascal. Dummerweise soll mein Programm da aber laufen - ich habe jetzt wochenlang geübt in Python und in Java, die Ursprungsquelle war weder oo noch schick strukturiert sondern einfach dBaseIV.

Jetzt habe ich schicke Lösungen in Python und auch in Java und auch mein Lazarus-Programm läuft an sich, wenn es mir auch vergleichsweise umständlich formuliert vorkommt, aber egal es läuft. Mein Clone in Turbo-Pascal ($DEFINE DOS} tut es aber nicht wegen einem Syntaxfehler bei der Benutzung meiner (Array-)Liste Unit. Speziell wird ein nicht sichtbares Feld "Head" angemeckert, was ein Pointer der Liste sein sollte. Allerdings habe ich es soweit ich beurteilen kann, schon public und auch ein Getter oder First und Next Methoden haben alles nicht geholfen, letztere will ich auch gar nicht weil die ArrayList im generischen Fall so schon gut ist. Lazararus-Collections könnte ich nehmen, aber der Fehler tritt ja im DOS-Pfad auf.

Könnte bitte jemand so lieb sein und mal meine Quelle(n) anschauen, was ich da verbockt habe? Wie gesagt das Programm wäre mir gerade für den DOS-Fall wichtig, in den anderen (Python, Java, Lazarus) geht es ja schon.
Dateianhänge
freiburg.zip
(75.93 KiB) 93-mal heruntergeladen

Mathias
Beiträge: 6919
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Ärger mit der Sichtbarkeit(?) in Turbo-Pascal Objekten

Beitrag von Mathias »

Kannst du uns zeigen, wo der Syntaxfehler ist, Datei / Zeile.
Oder noch besser, das was der Compiler ausspuckt.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

alfware17
Beiträge: 214
Registriert: Di 14. Dez 2010, 23:27

Re: Ärger mit der Sichtbarkeit(?) in Turbo-Pascal Objekten

Beitrag von alfware17 »

Also Turbo-Pascal bemängelt in FREIBURG.PAS, Zeile 61, Spalte 21 das .Head aus der Anweisung
zeiger := gesamt.head;

Fehler 44, Feldbezeichner erwartet. Ich nehme an, die weiteren Stellen zB Zeilen 76, 89, 96 und 106 wo ich in ähnlicher Weise den Kopf meiner Liste haben will, wird nach dem 1.Compilerfehler abgebrochen. Lazarus hat keinen Fehler, da ist ja auch $ELSE vom $IFDEF DOS also zieht er eine andere Definition aus der

LISTE.PAS wo ich eigentlich gehofft hatte daß mein "Head" in Zeile 20 zu sehen ist. Habe schon alles probiert, public, getter, first/next-Methoden, anscheinend ist nichts sichtbar :-(

Oder ich habe Tomaten auf den Augen

Vielleicht habe ich den TMListe oder TMEintrag für DOS falsch definiert, aber dann sollte eine andere Fehlermeldung kommen und nicht "Feldbezeichner erwartet"?

Benutzeravatar
kupferstecher
Beiträge: 434
Registriert: Do 17. Nov 2016, 11:52

Re: Ärger mit der Sichtbarkeit(?) in Turbo-Pascal Objekten

Beitrag von kupferstecher »

Habs mir kurz angeschaut, .Head zeigt doch auf einen anderen Typ, nämlich auf

Code: Alles auswählen

  TListeElement = RECORD
    Data: Pointer;
    Next: PListeElement;
  END;
Zeiger zeigt auf TEintrag

Code: Alles auswählen

   TEintrag = RECORD
      M1, M2, M3, N1, N2, L1: INTEGER;
      PROG, BEZEICHNER, CODE: STRING[50];
   END;
Edit: WIe ist das in Turbopascal, werden da Pointer auf Feder automatisch dereferenziert? Dann könnten sich die Kompilerentwickler gedacht haben dass der Standardfall ist, dass man nur das Feld vergessen hat, das dann den passenden Typen hat.

alfware17
Beiträge: 214
Registriert: Di 14. Dez 2010, 23:27

Re: Ärger mit der Sichtbarkeit(?) in Turbo-Pascal Objekten

Beitrag von alfware17 »

kupferstecher hat geschrieben: Mo 4. Nov 2024, 20:59 Habs mir kurz angeschaut, .Head zeigt doch auf einen anderen Typ, nämlich auf

Code: Alles auswählen

  TListeElement = RECORD
    Data: Pointer;
    Next: PListeElement;
  END;
Zeiger zeigt auf TEintrag

Code: Alles auswählen

   TEintrag = RECORD
      M1, M2, M3, N1, N2, L1: INTEGER;
      PROG, BEZEICHNER, CODE: STRING[50];
   END;
Edit: WIe ist das in Turbopascal, werden da Pointer auf Feder automatisch dereferenziert? Dann könnten sich die Kompilerentwickler gedacht haben dass der Standardfall ist, dass man nur das Feld vergessen hat, das dann den passenden Typen hat.
Ja du hast recht, meine Sammeldeklaration TMEintrag ist für den $DEFINE DOS Fall falsch und muß auf PListeElement lauten. Das habe ich gestern noch korrigiert (ich hatte die ganze Zeit vorher in Lazarus entwickelt und da fiel es nicht auf), mir dann aber neue Probleme geholt. Mittlerweile löuft der Quelltext in Turbo wieder, nachdem ich eine Zwischenvariable eingeführt habe. Das muß ich aber noch verifizieren (anscheinend eine "Grenze" des Turbo Compilers) und leider haut es mir auch meine bedingte Compilierung durcheinander bzw das wird unansehnlich. Ich versuche es noch mal und zeige dann das Ergebnis.

alfware17
Beiträge: 214
Registriert: Di 14. Dez 2010, 23:27

Re: Ärger mit der Sichtbarkeit(?) in Turbo-Pascal Objekten

Beitrag von alfware17 »

Also das Rätsel ist gelöst. Ich hatte einen Denkfehler in einer (zusätzlichen) Typvereinbarung, die ich eingeführt hatte um mir das oftmalige bedingte Compilieren zu sparen.
Als ich das für den (bisher ungetesteten) MSDOS/Turbo-Pascal Fall korrigiert habe, stand ich zwar vor einem neuen Problem, denn meine Stack/ArrayList-Units arbeiten für DOS mit Pointer und für Lazarus mit Generics

Code: Alles auswählen

UNIT Liste;

{$I OsWahl.inc}

{$IFNDEF DOS} {$MODE OBJFPC} {$H+} {$ENDIF}

INTERFACE

TYPE

  {$IFDEF DOS}

  PListeElement = ^TListeElement;
  TListeElement = RECORD
    Data: Pointer;
    Next: PListeElement;
  END;

  TListe = OBJECT
    Public
      Head, Tail: PListeElement;
      DataSize: Integer;
      Count: Integer;

  {$ELSE}

  GENERIC TListe<T> = OBJECT
    Private
      TYPE
        PListeElement = ^TListeElement;
        TListeElement = RECORD
          Data: T;
          Next: PListeElement;
        END;
      VAR
        Head, Tail: PListeElement;
        Count: Integer;

  {$ENDIF}

  Public
    PROCEDURE Init {$IFDEF DOS} (SizeOfData: Integer) {$ENDIF} ;
    PROCEDURE Add(Data: {$IFDEF DOS} Pointer {$ELSE} T {$ENDIF});
    FUNCTION Get(Index: Integer; {$IFDEF DOS} Data: Pointer {$ELSE} VAR Data: T {$ENDIF}): BOOLEAN;
    FUNCTION Remove(Index: Integer): BOOLEAN;
    FUNCTION IsEmpty: BOOLEAN;
    PROCEDURE Clear;
    FUNCTION Anzahl: Integer;
    FUNCTION Start: PListeElement;
  END;

Daran mußte mich der Compiler erst schmerzhaft erinnern (ich kann nicht einfach den Ergebnis-Record so abfragen sondern muß erst den Pointer auflösen im DOS-Fall), schade nun habe ich das so oft gemacht mit der $IFDEF DOS Unterscheidung und wenn es darauf ankommt denkt man nicht daran. Leider mag der Turbo Pascal auch keine doppelten ^ also was ich meine habe ich hier mal im Testcode:

Code: Alles auswählen

FUNCTION TMenueManager.Aktuelle_Menuepunkte_Test(VAR Ergebnis: TMListe): BOOLEAN;
VAR Zeiger: PMEintrag; (* Pointer *)
    RecTemp: TEintrag; (* Record *)
    PointTemp: PEintrag; (* Pointer *)
BEGIN
   Ergebnis.Clear;
   Zeiger := Gesamt.Head;
   WHILE Zeiger <> NIL DO BEGIN

      PointTemp := Zeiger^.Data;

      IF (PointTemp^.M1 = aktuell.M1) AND (PointTemp^.M2 = aktuell.M2) THEN
         Ergebnis.Add(PointTemp);

      RecTemp := PointTemp^;

      IF (RecTemp.M1 = aktuell.M1) AND (RecTemp.M2 = aktuell.M2) THEN
         Ergebnis.Add(Zeiger^.Data);

      (* direkt ohne Zwischenvariable, 2x ^ geht nicht *)
      (*RecTemp := Zeiger^.Data^; *)

      (* direkt ohne Zwischenvariable, mit Klammern, geht auch nicht *)
      (* RecTemp := (Zeiger^).Data^; *)

      (* direkt ohne Zwischenvariable, mit Klammern, geht auch nicht *)
      (* RecTemp := (Zeiger^.Data)^; *)

      IF (PointTemp^.M1 = aktuell.M1) AND (PointTemp^.M2 = aktuell.M2) THEN
         Ergebnis.Add(Zeiger^.Data);

      (* direkt wie in Lazarus geht nicht weil in Turbo Nutzdaten Pointer
         und in Lazarus Data = TEintrag *)
      (* IF (Zeiger^.Data.M1 = aktuell.M1) AND (Zeiger^.Data.M2 = aktuell.M2) THEN
         Ergebnis.Add(Zeiger^.Data);
      *)

      Zeiger := Zeiger^.Next;

   END;
Man sieht im Murphy-Fall kommt wirklich alles zusammen.

Die richtige, und jetzt in Lazarus wie in Turbo-Pascal laufende Methode sieht nun so aus:

Code: Alles auswählen

PROCEDURE TMenueManager.Inhalt(Zeiger: PMEintrag; VAR Eintrag: TEintrag);
{$IFDEF DOS} VAR Temp: PEintrag; {$ENDIF}
BEGIN
   {$IFDEF DOS} Temp := Zeiger^.Data; Eintrag := Temp^; {$ELSE} Eintrag := Zeiger^.Data; {$ENDIF}
END;

FUNCTION TMenueManager.Aktuelle_Menuepunkte(VAR Ergebnis: TMListe): BOOLEAN;
VAR Zeiger: PMEintrag;
    Eintrag: TEintrag;
BEGIN
   Ergebnis.Clear;
   Zeiger := Gesamt.Head;
   WHILE Zeiger <> NIL DO BEGIN
      Inhalt(Zeiger, Eintrag);     
      IF (Eintrag.M1 = aktuell.M1) AND (Eintrag.M2 = aktuell.M2)
         THEN Ergebnis.Add({$IFDEF DOS}@{$ENDIF}Eintrag);
      Zeiger := Zeiger^.Next;
   END;
   Aktuelle_Menuepunkte := Ergebnis.Anzahl <> 0;
END;


Es war also nur scheinbar die "Sichtbarkeit" sondern ein anderes kleines Problemchen, welches mir der Turbo-Pascal Compiler nicht abgenommen hat, weil ich nicht exakt genug war.
HIer kommt noch meine Bitte. Ich hänge noch einmal das komplette richtige Programm in den Thread (nehme dafür oben raus mit dem Fehler?) und frage um Feedback und vernichtende Kritik zum Quelltext des Hauptprogramms freiburg.pas und den beiden Units Stack und Liste. Ich weiß schon - es ist vermutlich umständlicher als mit den schicken Lazarus-Bibliotheken ausgedrückt und noch viel viel umständlicher als in Java oder gar Python. Auch mußte ich Rücksicht nehmen auf Turbo-Pascal und generell habe ich mal auf VAR Ergebnisparameter gesetzt, weil komplexere Funktionsergebnisse nicht so meins und Turbos Ding sind.

Aber habt ihr generell Verbesserungsvorschläge? Im Java und im Python Programm habe ich nachträglich Programmkonstrukte eingebaut, auf die ich nie im Leben selber gekommen wäre, die einem das Leben aber leichter machen können
Dateianhänge
freiburg.zip
(76.37 KiB) 78-mal heruntergeladen

Antworten