Dynamische Arrays - ins negative Erweiterbar?

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

Aha. Das ist ja interessant. Habe ich das richtig verstanden:
Dadurch wird es möglich, unter ein uns denselben Variablennamen verschiedene Variablentypen zu unterscheiden?

Werde ich mir mal Gedanken drüber machen. Bin bei meiner Sache im Moment noch in der Planungsphase: Möchte den Quelltext nur einmal schreiben - und nicht irgendwann feststellen, dass die von mir verwendete Struktur ungeeignet für spezielle Aufgaben ist.


Euklid

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@Euklid

Das Problem dabei ist, das im case-Konstrukt des Records die Variablen unterschiedliche Namen haben müssen. Du kannst also nicht sowas machen:

Code: Alles auswählen

TMyTypset = %u28myinteger, mycaedinal, myreal, mydouble%u29;
 
TMyTypes  = myinteger..mydouble;
 
TMyRecord = record
  ThisType%u3a TMyTypes;
  case ThisType of
    myinteger%u3a %u28content %u7b!!!%u7d%u3a integer%u29;
    mydouble%u3a %u28content %u7b!!!%u7d%u3a double%u29;
  end; // of case
end; // of TMyRecord
So aber ginge es:

Code: Alles auswählen

TMyRecord = record
  ThisType%u3a TMyTypes;
  case ThisType of
    myinteger%u3a %u28integercontent %u7b!!!%u7d%u3a integer%u29;
    mydouble%u3a %u28doublecontent %u7b!!!%u7d%u3a double%u29;
  end; // of case
end; // of TMyRecord
Und du kannst in diesem Fall natürlich noch einen Schritt weitergehen:

Code: Alles auswählen

TIntContenRec = record
  Potenz%u3a integer;
  Zahl   %u3a integer;
end;
 
TDoubleContenRec = record
  Potenz%u3a integer;
  Zahl   %u3a double;
end;
 
 
TIntContentArray = array of TIntContenRec;
TDoubleContenArray = array of TDoubleContenRec;
 
%u28* hier kommt der Punkt wo der Floh das Wasser läßt *%u29
 
TMyRecord = record
  ThisType%u3a TMyTypes;
  case ThisType of
    myinteger%u3a %u28intcont%u3a TIntContentArray%u29;       %u28* !!!! *%u29
    mydouble%u3a %u28doubcont%u3a TDoubleContenArray%u29;  %u28* !!! *%u29
  end; // of case
end; // of TMyRecord
Aber nun darfst Du folgendes deklarieren:

var MyComputedVar: TMyRecord;

und hast damit alle Möglichkeiten die deine Struktur abbilden kann in einer Variablen. Der Trick:

procedure TuWas(var Buf);

bezieht sich auf keinen keinerlei Typ für Buf und kann deswegen alles annehmen, also auch deine Struktur. Erst innerhalb der Prozedur mußt du den richtigen Typ herausfinden und dann bestimmen wie es weiter geht.

War jetzt etwas ausführlicher damit Du siehst was damit so alles möglich ist. Auf ähnliche Art hab ich mal ein Lottoprogramm spaßeshalber geproggt. Da waren die Lottoscheine in dieser Form aufgebaut. Das schränkt dann die nötigen Prozeduren und Funktionen zum verarbeiten ein.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Euklid
Lazarusforum e. V.
Beiträge: 2808
Registriert: Fr 22. Sep 2006, 10:38
OS, Lazarus, FPC: Lazarus v2.0.10, FPC 3.2.0
Wohnort: Hessen
Kontaktdaten:

Beitrag von Euklid »

schnullerbacke hat geschrieben: War jetzt etwas ausführlicher damit Du siehst was damit so alles möglich ist.
Danke! Hatte mich schon immer über manche Standard-Routinen gewundert, die ganz unterschiedliche Variablentypen akzeptieren. Dachte nicht, dass man solche Routinen auch selbst programmieren kann.
Naja, einen fortgeschrittenen Anfängerstatus haben meine Pascal-Kenntnisse leider nie überschritten....

Aber man lernt ja immer dazu. Deswegen gleich noch eine Frage:
Lässt sich ähnlich einfach realisieren, dass eine Funktion einen beliebigen Variablentyp zurückgibt? Quasi, dass man den Rückgabewert dann mit case-Anweisungen ausdifferenziert behandelt?

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

@schnullerbacke
und wie greife ich auf so ein record zu ? und für was währe es Einsetzbar ?
ich meine jetzt dein letztes Beispiel.
MFG
Michael Springwald

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@Euklid

Die Rückgabe kann entweder direkt in Buf erfolgen. Durch die Deklaration als var ist das zweigleisig. Man könnte aber auch eine zweite variable als Rückgabe deklarieren wenn man Buf nicht mit anderen Daten überschreiben will. Also etwa so:

procedure TuWas(var InBuf;var OutBuf);

Als function ist sowas nur mit Zeigern möglich und deshalb eher nicht zu empfehlen.

@pluto

Zugriff ist recht einfach, da der Typ an der ersten Position steht. D.h.:

Code: Alles auswählen

procedure TuWas(var InBuf; var OutBuf);
var
  VarType: TMyTypeSet;
begin
   // entweder
  move(InBuf[0], VarType, SizeOf(VarType));
  case VarType of
    myinteger:{};
  end
  else Exit;
 
  // oder
  case TMyRecord(InBuf).VarType of
     myinteger:{};
  end;
end;
Der Typecast bietet sich an wenn man sicher sein kann, das in InBuf etwas vom Typ TMyRecord ankommt. Ansonsten könnte zum absichern das es sowas ist die erste Variante besser geeignet sein. Ansonsten wird bei anderen Records üblich ebenfalls mit dem Punkt refenziert. Also

Code: Alles auswählen

var
  MyVar: TMyRecord;
  Indize: integer;
begin
  case TMyRecord(InBuf).MyType of
     myinteger: Indize:= High(TMyRecord(InBuf).IntArray);
     myDouble: Indize:= High(TMyRecord(InBuf).DoubArray);
  end;
end;
Also eigentlich ganz easy. :P
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Da läßt sich also ne Menge damit spielen. Man könnte sich auch zur Gewohnheit machen in jedem Record an der ersten Stelle einen Recordmagic zu deklarieren anhand dessen man den Record-Typ erkennt.

Dann kann je nach magic den entsprechenden Typecast anwenden und könnte so eine zentrale Prozedur für eine Datenbank verwenden. Hat dann aber den Nachteil, das man die Daten von einer SQL-Tabelle zunächst in den Record übertragen muß. Kann aber im Zweifel durchaus eine elegante Lösung sein.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

naja ich würde den ganzen Aufwand erst gar nicht machen. Weil ich auch noch gar nicht so verstehe wo hier der sin liegt.

Ich würde einfach verschiedene Variablen definieren und je nach dem welche ich davon brauche benutzen. Könnte deine Variante evlt. den Speicher Verbrauch reduzieren ?
MFG
Michael Springwald

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

Der Sinn liegt darin, das man in einer einzigen Struktur unterschiedliche Dinge speichern kann. Beim Datenbank-Beispiel könnte das z.B. zum einen ein Personendatensatz sein zum anderen aber auch ein Warendatensatz. Erst in der Zentralen Prozedur wird das effektiv zerlegt und dann entschieden wie weiter verfahren wird.

So könnte man z.B. in Abhängigkeit vom Typ ein bestimmtes Formular auf rufen und mit einer Transfer-Prozedur die Daten in die Eingabefelder bringen:

Code: Alles auswählen

prozedur TThisForm.FillForm(var InBuf);
begin
  edNachname.Text:= TMyDataBaseRec(InBuf).Nachname;
  edVorname.Text:= TMyDataBaseRec(InBuf).Vorname;
  // usw
end;

Bei Euklids Plan kann er halt verschieden Variablentypen behandeln und diese sogar als offene Arrays behandeln. Der eigentlich Witz ist, das man nicht mehrere verschiedene Records braucht und deshalb auch nicht verschiedene Prozeduren für die Bearbeitung braucht. Erst wenn eindeutig klar ist welche Struktur vorliegt wird die spezielle Verarbeitung durchgeführt.

Führt halt zu eleganten und sehr übersichtlichen Programmen.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

noch verstehe ich das nicht: weil ich kann doch ein record defnieren:
TPerson = record
Vorname, Nachname:String;
end;
ist doch viel einfacher. Für alles andere nehme ich eine klasse.
MFG
Michael Springwald

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Also das mit dem personen und Warendatensatz ist gnadenlos übertrieben das geht auch nicht und macht auch keinen Sinn.
Man kann lediglich einzelne Variablen austauschen und sone art Variant Ersatz haben.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

schnullerbacke
Beiträge: 1187
Registriert: Mi 13. Dez 2006, 10:58
OS, Lazarus, FPC: Winux (L 1.2.xy FPC 2.6.z)
CPU-Target: AMD A4-6400 APU
Wohnort: Hamburg

Beitrag von schnullerbacke »

@Christian

Gehen tut es, wieviel Sinn das macht sei mal dahingestellt. Für Euklids Aufgabe ist es aber eine elegante Lösung.

@pluto

Du vergißt da wohl die enge Typprüfung von PASCAL. Du müßtest dann unter Umständen für ein Formular mehrere solcher Prozeduren bereitstellen. So braucht man halt nur eine und kann dann mit lokalen Prozeduren die speziellen Teile bearbeiten. Das macht sowas Pflegeleichter.
Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.

(Ringelnatz)

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Wie soll das denn gehen ? Du hast doch ganz andere Felder in den Datensätzen was bitte soll z.b. die Adresse bei nem Wahrendatensatz darstellen ? Quark.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Ich verstehe den sin nicht. wozu gibt es OOP ?

ich verstehe das so, das es eine art OOP ersatzt ist.
So sieht das für mich bis jetzt aus.
MFG
Michael Springwald

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Nein pluto wie soll das denn ne art OOP Ersatz sein ?
Es ist einfach ne gute Möglichkeit wenn eine Variable mehrere Typen annehmen kann. Beispiel Postfach und Adresse könnte man so in eine Variable packen wenn sie word ist ists ein Postfach und String ists Adresse.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Für mich ergibt das noch kein sinn....
MFG
Michael Springwald

Antworten