Wie auf unbekanntes Element eines Recorarrays zugreifen?
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Wie auf unbekanntes Element eines Recorarrays zugreifen?
Hallo,
gibt es eine Möglichkeit, bei einem Recordarray auf ein einzelnes Element eines bestimmten Records zuzugreifen, um dann dessen Typ (Byte, Word, String etc.) und dementsprechend auch sizeof() herauszufinden?
Ich bräuchte das, um dann die Records nach diesem Element sortieren zu können.
Der Compiler macht das ja auch. Aber gibt es dafür auch geeignete Prozeduren/Funktionen?
Herzlichen Dank.
gibt es eine Möglichkeit, bei einem Recordarray auf ein einzelnes Element eines bestimmten Records zuzugreifen, um dann dessen Typ (Byte, Word, String etc.) und dementsprechend auch sizeof() herauszufinden?
Ich bräuchte das, um dann die Records nach diesem Element sortieren zu können.
Der Compiler macht das ja auch. Aber gibt es dafür auch geeignete Prozeduren/Funktionen?
Herzlichen Dank.
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Bei Records musst du immer die Definition des Record-Typen haben. Ohne hast du keine Chance die in einem Record enthaltenen Daten richtig zu verarbeiten.br_klaus hat geschrieben:gibt es eine Möglichkeit, bei einem Recordarray auf ein einzelnes Element eines bestimmten Records zuzugreifen, um dann dessen Typ (Byte, Word, String etc.) und dementsprechend auch sizeof() herauszufinden?
An welcher Stelle?br_klaus hat geschrieben:Der Compiler macht das ja auch.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- willi4willi
- Lazarusforum e. V.
- Beiträge: 172
- Registriert: Sa 1. Nov 2008, 18:06
- OS, Lazarus, FPC: Lazarus 3.8 FPC 3.2.2 x86_64-win64-win32/win64 x86_64-linux-gtk2
- CPU-Target: i386, win64, arm
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Hallo br_klaus,
wenn Du den Namen des Elements kennst, kannst Du den Typ ermitteln, indem Du das Element einer Variant-Variable zuordnest und dann mit der Funktion VarTest den Typ herausfindest.
Du benötigst dazu die Unit variants.
Viele Grüße Willi4Willi
wenn Du den Namen des Elements kennst, kannst Du den Typ ermitteln, indem Du das Element einer Variant-Variable zuordnest und dann mit der Funktion VarTest den Typ herausfindest.
Du benötigst dazu die Unit variants.
Viele Grüße Willi4Willi
Viele Grüße
Willi4Willi
------------
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Hallo, Wili4Willi,willi4willi hat geschrieben:Hallo br_klaus,
wenn Du den Namen des Elements kennst, kannst Du den Typ ermitteln, indem Du das Element einer Variant-Variable zuordnest und dann mit der Funktion VarTest den Typ herausfindest.
Du benötigst dazu die Unit variants.
Viele Grüße Willi4Willi
herzlichen Dank für Deinen Hinweis. Aber in der Unit Varians finde ich zwar eine Menge von Funktionen, aber keine namens VarTest (die gibt es in ganz Lazarus nicht).
Wie macht man das denn konkret: das Element einer Variant-Variablen zuordnen und dann deren Typ herausfinden?
herzlichen Dank!
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Das ganze geht auch ohne Variants:br_klaus hat geschrieben:Wie macht man das denn konkret: das Element einer Variant-Variablen zuordnen und dann deren Typ herausfinden?
- Records unterstützen kein RTTI.
- Daher: Der Name eines Record-Elements muss beim Übersetzen des Programms bekannt sein.
- Daher: kann man die Compiler-Funktion typeinfo() (oder typinfo(), da bin ich mir nicht mehr ganz sicher) verwenden um an Typinformationen zu gelangen. Der Compiler ersetzt die Funktion zur Übersetzungszeit mit einem entsprechenden Funktionsaufruf.
Code: Alles auswählen
type TMyRecord = record
x: Integer;
end;
var
v: Variant;
r: TMyRecord;
begin
v := r.x;
writeln(varType(v)); // was du auch immer damit tun möchtest
end;
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
- willi4willi
- Lazarusforum e. V.
- Beiträge: 172
- Registriert: Sa 1. Nov 2008, 18:06
- OS, Lazarus, FPC: Lazarus 3.8 FPC 3.2.2 x86_64-win64-win32/win64 x86_64-linux-gtk2
- CPU-Target: i386, win64, arm
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Oh, verzeih. Die Funktion heißt natürlich VarType().
Mit folgender Funktion kann man mal testen. Du machst das dann sicherlich auf die Art und Weise, wie socke sie beschrieben hat.
Viele Grüße!
Willi4Willi
Mit folgender Funktion kann man mal testen. Du machst das dann sicherlich auf die Art und Weise, wie socke sie beschrieben hat.
Code: Alles auswählen
Procedure VarTest(v:variant);
begin
case VarType(v) of
varEmpty : showmessage('$0000 Die Variante hat den Status Unassigned.');
VarNull : showmessage('$0001 Die Variante hat den Wert Null.');
VarSmallint : showmessage('$0002 16-Bit-Integer mit Vorzeichen (Typ Smallint).');
VarInteger : showmessage('$0003 32-Bit-Integer mit Vorzeichen (Typ Integer).');
VarSingle : showmessage('$0004 Gleitkommawert mit einfacher Genauigkeit (Typ Single).');
VarDouble : showmessage('$0005 Gleitkommawert mit doppelter Genauigkeit (Typ Double).');
VarCurrency : showmessage('$0006 Gleitkommawert für Währungsbeträge (Typ Currency).');
VarDate : showmessage('$0007 Datums-/Zeitwert (Typ TDateTime).');
VarOleStr : showmessage('$0008 Referenz auf einen OLE-String (dynamisch verwalteter Unicode-String).');
VarDispatch : showmessage('$0009 Referenz auf ein OLE-Automatisierungsobjekt (Zeiger auf IDispatch-Schnittstelle). ');
VarError : showmessage('$000A Betriebssystem-Fehlercode.');
VarBoolean : showmessage('$000B Boolescher 16-Bit-Wert (Typ WordBool).');
VarVariant : showmessage('$000C Variante (nur in Verbindung mit varianten Arrays).');
VarUnknown : showmessage('$000D Referenz auf ein unbekanntes OLE-Objekt (Zeiger auf IUnknown-Schnittstelle).');
VarByte : showmessage('$0011 8-Bit-Integer ohne Vorzeichen (Typ Byte).');
VarString : showmessage('$0100 Referenz auf einen dynamisch verwalteten langen String (Typ AnsiString).');
VarTypeMask : showmessage('$0FFF Bitmaske zur Ermittlung des Typencodes.');
VarArray : showmessage('$2000 Bit zur Kennzeichnung eines varianten Arrays.');
else
showmessage('was anderes');
end;
end;
Willi4Willi
Viele Grüße
Willi4Willi
------------
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Herzlichen dank für diesen Hinweis. Es heißt jedoch, variants seien extrem langsam.willi4willi hat geschrieben:Oh, verzeih. Die Funktion heißt natürlich VarType().
Mit folgender Funktion kann man mal testen. Du machst das dann sicherlich auf die Art und Weise, wie socke sie beschrieben hat.
....
Viele Grüße!
Willi4Willi
Wie macht das denn der Compiler selber, wenn er den Typ einer Variablen ermiteln will?
Ich nehme an, daß er intern eine (oder mehrere) varlist erstellt mit jeweils Name, Klassenname, Speicherplatz, Wert, ob Teil einer anderen Variablen (zB Record oder userdefinierte Klasse), Ort der Definition (Datei, Zeile, Spalte), sonst könnte er ja nicht bei Fehlermeldungen (zB Doppeldeklaration) angeben, wo eine Variable desselben Namens schon erstellt wurde. Und bei Arrays muß er ja auch unterscheiden können zwischen fixen arrays[x..y] of ... und dynamischen arrays of ...
Gibt es eine Möglichkeit, auf diese Liste zugreifen zu können, bzw kann mir jemand sagen, wo (in welcher Unit) diese Liste erstellt bzw. ausgelesen wird (mit welchen Prozeduren)?
Herzlichen Dank!
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Kannst Du nicht 'mal Deine Record- / Array- (oder was auch immer) Definition posten ?
-Michael
-Michael
Zuletzt geändert von mschnell am Mi 28. Nov 2012, 10:45, insgesamt 1-mal geändert.
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Variants sind auch (im Vergleich zu nativen Datentypen wie Integer oder Char) sehr langsam, da einiges an Verwaltung zu den Daten hinzu kommt.br_klaus hat geschrieben:Herzlichen dank für diesen Hinweis. Es heißt jedoch, variants seien extrem langsam.
Wie macht das denn der Compiler selber, wenn er den Typ einer Variablen ermiteln will?
Der Compiler erstellt selbstverständlich ebenfalls Typinformationen. Diese werden aber nur Teilweise für Klassen (mit dem Compilerschalter {$M+}) in das fertige Programm übernommen (RTTI). Für alle primitiven Datentypen gibt es den oben von mir beschriebenen Weg um an Daten zu kommen.
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Re: Wie auf unbekanntes Element eines Recordarrays zugreifen
Wenn ich zB folgendes habe:mschnell hat geschrieben:Kannst Du nicht 'mal Deine Record- / Array- (oder was auch immer) Definition posten ?
-Michael
Code: Alles auswählen
Type TRec = record a:integer; b:boolean; c:string; d:pointer; end;
var recs: array of TRec;
Code: Alles auswählen
procedure SortRecs(sortstr);
Der Compiler macht das sicher eleganter mit internen arrays. Nur hat der als Ausgangspunkt i.a. die Cursorposition bzw die zu kompilierende Datei. Ich habe schon einige Units gefunden, die damit zu tun haben: bei den CodeTools (finddeclaration u.ä.) und auch bei den packages\fcl-passrc die Unit Pastree.
Es wird wohl keine Möglichkeit geben, die Variablen automatisch in einem array zu speichern mit dem jeweiligen Variablentyp (und dann natürlich auch den Offset im Record und die Speichergröße), oder?
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Wie auf unbekanntes Element eines Recordarrays zugreifen
Mir ist völlig schleierhaft, was Du damit meinst und was das mit irgendwelchen Typen zu tun hat.br_klaus hat geschrieben:dann würde ich die gerne sortieren nach einzelnen Elementen, und zwar, indem ich nur einen String Sortstr anzugeben brauche, der die Sortierreihenfolge enthält, zB '2 1 0 3'.
Auch hier ist mir völlig schleierhaft, was Du da vor hast.br_klaus hat geschrieben:Es wird wohl keine Möglichkeit geben, die Variablen automatisch in einem array zu speichern mit dem jeweiligen Variablentyp (und dann natürlich auch den Offset im Record und die Speichergröße), oder?
Aber jedenfalls ist der Record Typ ja programmatisch vorgegeben, deshalb sind die Typen der Elemente zur Compile-Zeit bekannt und brauchen nicht irgendwie zur Laufzeit dynamisch bestimmt werden.
-Michael
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Re: Wie auf unbekanntes Element eines Recordarrays zugreifen
Die procedure SortRecs('0 2 1 3') soll folgendes machen: Sortieren der Recs mit folgender Vergleichsfunktion:mschnell hat geschrieben:Mir ist völlig schleierhaft, was Du damit meinst und was das mit irgendwelchen Typen zu tun hat.br_klaus hat geschrieben:dann würde ich die gerne sortieren nach einzelnen Elementen, und zwar, indem ich nur einen String Sortstr anzugeben brauche, der die Sortierreihenfolge enthält, zB '2 1 0 3'.
br_klaus hat geschrieben:Es wird wohl keine Möglichkeit geben, die Variablen automatisch in einem array zu speichern mit dem jeweiligen Variablentyp (und dann natürlich auch den Offset im Record und die Speichergröße), oder?
Auch hier ist mir völlig schleierhaft, was Du da vor hast.
Aber jedenfalls ist der Record Typ ja programmatisch vorgegeben, deshalb sind die Typen der Elemente zur Compile-Zeit bekannt und brauchen nicht irgendwie zur Laufzeit dynamisch bestimmt werden.
-Michael
Code: Alles auswählen
function CompareRecs(p,q:pointer):integer;
var off,j:integer;
begin j:=0; result:=0;
repeat
off := offs[seq[j]]; func:=sorts[typ[seq[j]]];
result:=func((P+off)^, (q+off)^);
if result<>0 then exit;
inc(j);
until j>= length(seq);
end;
offs ist ein IntegerArray mit den Offsets (zum Recordbeginn) der einzelnen Record-Komponenten
off daher der Offset der jeweiligen zu sortierenden Variablen
sorts ist ein array of TListSortCompare, je nach Typ der zu vergleichenden Variable (und hier benötige ich den Typ), zB wenn Integer, dann IntegerVergleich, etc.
zB.
Code: Alles auswählen
Function SortCompareInt(p,q:pointer):integer;
begin result:=CompareInt(Pinteger(p)^, PInteger(q)^) end;
//mit
function CompareInt(x,y:integer):integer;
begin result:=0; if x=y then exit; if x>y then inc(result) else dec(result); end;
Sortrecs('0 2 1 3')
ausführen, wenn er nicht weiß, von welchem Typ das erste,zweite,dritte,.. Element des Records ist?
-
- Beiträge: 3444
- Registriert: Mo 11. Sep 2006, 10:24
- OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
- CPU-Target: X32 / X64 / ARMv5
- Wohnort: Krefeld
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
"Normal" wäre, eine an die Liste zu übergebende Vergleichsfunktion etwa wie:
-Michael
Code: Alles auswählen
Type TpRec = ^Trec;
function CompareRecs(p,q:pointer):integer;
var
rp, rq TpRec;
begin
rp := TpRec(p);
rq := TpRec(q);
Result := rq.a - rp.a;
end;
Zuletzt geändert von mschnell am Sa 1. Dez 2012, 02:01, insgesamt 1-mal geändert.
-
- Beiträge: 244
- Registriert: Do 21. Jan 2010, 22:33
- OS, Lazarus, FPC: Windows Vista (L 0.9.31 FPC 2.5.1)
- CPU-Target: 32Bit
- Wohnort: z.z. Brasilien, sonst 82335 Berg-Leoni (südlich von München)
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
[quote="mschnell"]"Normal" wäre eine an die Liste zu übergebende Vergleichsfunktion etwa wie:
An so etwas hatte ich gar icht gedacht. Herzlichen Dank.
Aber das geht wohl nur bei Zahlen. Bei Strings muß ich sicher byteweise vergleichen. Und bei booleans?
Code: Alles auswählen
Type TpRec = ^Trec;
function CompareRecs(p,q:pointer):integer;
var
rp, rq TpRec;
begin
rp := TpRec(p);
rq := TpRec(q);
Result := rq.a - rp.a;
end;
Aber das geht wohl nur bei Zahlen. Bei Strings muß ich sicher byteweise vergleichen. Und bei booleans?
-
- Lazarusforum e. V.
- Beiträge: 3178
- Registriert: Di 22. Jul 2008, 19:27
- OS, Lazarus, FPC: Lazarus: SVN; FPC: svn; Win 10/Linux/Raspbian/openSUSE
- CPU-Target: 32bit x86 armhf
- Wohnort: Köln
- Kontaktdaten:
Re: Wie auf unbekanntes Element eines Recorarrays zugreifen?
Der Datentyp Boolean lässt sich nicht ordinal vergleichen. Du kannst zwischen den Werten True und False nur eine Gleichheit bzw. Ungleichheit feststellen. Welches davon in einer Liste zuerst stehen soll, ist anwendungsabhängig und muss daher von dir festgelegt werden.br_klaus hat geschrieben:Und bei booleans?
MfG Socke
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein
Ein Gedicht braucht keinen Reim//Ich pack’ hier trotzdem einen rein