Moin.
Ich schreib mir grad eine kleine Bibliothek für eine einfachverkettete Liste.
Dafür hab ich ein Record, welches die Knoteninformationen (was ebenfalls ein Record ist) und den Zeiger auf den nächsten Knoten beinhaltet.
Nun möchte ich eine Funktion schreiben, die überprüft, ob ein bestimmter Knoten schon existiert. Da ich die Bibliothek nun unabhängig von den Records haben möchte, muss ich die Records, die die Knoteninformationen beinhalten, auf Gleichheit prüfen.
Nur leider kann man nicht mit if Record1= Record2 auf Gleichheit prüfen.
Jemand ne Idee, wie man sowas realisieren kann?
function is_equal(a,b:Record): Boolean;
begin
is_equal := true;
is_equal := is_equal or ( a.x = b.x );
is_equal := is_equal or ( a.y = b.y );
is_equal := is_equal or ( a.z = b.z );
..
end;
...
Genau das wollte ich eigentlich verhindern.
Ich wollte es ganz gerne unabhängig von der Struktur des Records lösen.
So muss ich ja jedes Mal, wenn sich die Struktur des Records ändert, auch die Funktion ändern.
Dass mit den Objekten muss ich mir mal genauer anschauen, da ich noch nie mit Objekten gearbeitet habe und die Records leider vorgegeben worden sind (ist eine Aufgabe für die Schule).
Wenn du es mit einer sich aendernden, nicht anpassbaren Struktur zu tun hast, dann wird es etwas schwierig. Andererseits koenntest du eine Variable fuer die Groesse in die Records aufnehmen. Zur Verarbeitung bieten sich Zeigerarithmetik und Schleifen an, falls ihr das schon angesprochen hattet.
Ok, es gibt noch eine fiese Quick n' Dirty Methode fuer Records.
Allerdings nur, wenn sie wirklich von absolut dem selben Typ sind und keinerlei dynamische Strukturen aufweisen.
Dann koenntest du direkt auf binaere Identitaet pruefen mittels
Unit Sysutils
function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
Du machst die Funktion
function is_equal(R1, R2: Record): Boolean;
begin
is_equal := CompareMem( @R1, @R2, SizeOf(Record) )
end;
Damit ueberpruefst du, ob der Speicherinhalt an den Speicherstellen @R1 und @R2 innerhalb einer Laenge von SizeOf(Record) Bytes identisch ist. SizeOf(Record) liefert gerade die Laenge deines Record-Typs in Byte.
Das ganze geht natuerlich massiv in die Hose, wenn der Record eine dynamische Laenge besitzt (wie es z.B. manche Datentypen der Windows-API haben) und pro Instanz demnach unterschiedlich lang sein kann.
Ausserdem gibts natuerlich Probleme, wenn dein Record selber Zeiger enthaellt. MemComp ueberprueft naemlich durch den byteweisen Vergleich, ob die Addressen, auf die die Zeiger zeigen, identisch sind, nicht, ob deren Inhalt identisch ist. Nehmen wir also an, du haettest einen Record R1 und einen Record R2, die beide einen typisierten Pointer P besitzen, (der auch auf alloziierten Speicher zeigt). Dann wuerde R2.P^ := R1.P^; eine Valide Zuweisung sein, indem der Inhalt von R2.P durch den Inhalt von R1.P ersetzt wird. Dennoch zeigen R1.P und R2.P auf unterschiedliche Speicherbereiche (Addressen), und MemComp schlaegt damit als binaerer Vergleich fehl, obwohl der Inhalt beider Zeiger (aber nicht beide Zeiger) identisch sind.
Wenn du es mit einer sich aendernden, nicht anpassbaren Struktur zu tun hast, dann wird es etwas schwierig. Andererseits koenntest du eine Variable fuer die Groesse in die Records aufnehmen. Zur Verarbeitung bieten sich Zeigerarithmetik und Schleifen an, falls ihr das schon angesprochen hattet.
...
Ich weiß, was Schleifen und Zeiger sind. Ist ja nicht so, dass ich schon seit Jahren programmiere und nun ins vierte Semester meiner Ausbildung komme
Ich hab mir ja so eine Bibliothek unter C geschrieben und wollte sie jetzt nach Delphi übertragen, da ich nun solche Funktionen für eine Seminaraufgabe brauche. Unter C geht es ja mit if (struct1 == struct2), nur leider wohl unter Delphi nicht.
Ok, da man wohl unter Delphi mit dreckigen und unsicheren Tricks arbeiten muss, dann lass ich wohl diese Funktionen raus, die von dieser Funktion abhängig sind. Je weniger murks da drinnen steht, desto weniger können sie danach fragen ^^
Du wusstest schon selber, dass es keinen Vergleichsoperator fuer Records gibt.
Ergo gibt es nur 2 Moeglichkeiten:
a) Du vergleichst alles per Hand.
Das wolltest du aber nicht, da du dann, wenn du den Record aenderst, die Vergleichsfunktion anpassen musst.
b) Du pruefst die Speicherbereiche auf identischen Inhalt.
Das ist dir aber auch nicht recht, da es dir zu "dreckig" ist.
Nur andere Moeglichkeiten gibt es nun einmal nicht. Selbst die eingebauten Identitaetsoperatoren in C arbeiten auf diesem Prinzip (idR nach b, wobei die natuerlich schon vom compiler her auf Typgleichheit testen koennen).
Das ganze ist also kein "Delphi"-Problem, wie du es darstellst, sondern einfach, dass du etwas selbst implementieren musst, weil dir der syntaktische Zucker fehlt.
PS: Ganz nebenbei, ein "Danke" haette dir auch nicht geschadet.
Es gibt in C keinen sprachunterstützten Vergleich von Strukturen, da die Möglichkeit besteht, dass Füllbytes eingesetzt werden. Insofern is der Speichervergleich Unsinn. In C++ gibt es die Möglichkeit den Vergleichsoperator zu überladen, das kommt allerdings einer eigenen Vergleichsfunktion gleich.