Dynamische Arrays - ins negative Erweiterbar?
-
- 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:
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
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
-
- 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
@Euklid
Das Problem dabei ist, das im case-Konstrukt des Records die Variablen unterschiedliche Namen haben müssen. Du kannst also nicht sowas machen:
So aber ginge es:
Und du kannst in diesem Fall natürlich noch einen Schritt weitergehen:
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.
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
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
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
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)
(Ringelnatz)
-
- 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:
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.schnullerbacke hat geschrieben: War jetzt etwas ausführlicher damit Du siehst was damit so alles möglich ist.
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?
-
- 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
@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.:
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
Also eigentlich ganz easy. 
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;
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;

Humor ist der Knopf, der verhindert, daß uns der Kragen platzt.
(Ringelnatz)
(Ringelnatz)
-
- 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
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.
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)
(Ringelnatz)
-
- 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)
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 ?
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
Michael Springwald
-
- 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
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:
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.
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)
(Ringelnatz)
-
- 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
@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.
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)
(Ringelnatz)
-
- 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:
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.
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/