Ergebnis 1 bis 14 von 14

Thema: [Delphi] Records auf Gleichheit prüfen

  1. #1

    [Delphi] Records auf Gleichheit prüfen

    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?

  2. #2
    Solange die Records vom selben Typen sind, sollte if Record1 = Record2 funktionieren.

  3. #3
    anscheinend wohl nicht, da der Kompiler die Fehlermeldung:

    "E2015 Operator ist auf diesen Operandentyp nicht anwendbar"

    ausspuckt.

  4. #4
    Auch wenn ich Delphi nicht kenne. Kannst du das relevante Stueck, an dem es hapert zeigen?

  5. #5
    Es ist im Grunde nichts besonderes.
    Typendefinition:
    Code (Delphi):
     
      //Alle Werte eines Feldes
      PField = ^TField;
     
      TInfo = record
                  row, col : TRowCol; //Position im gesamten Spielfeld
                  player : TPlayer;
                  selected : boolean;
              end;
     
      TField = record
                  Info : TInfo;
                  p : array[TPointerDirection] of PField; //Zeiger auf die Nachbarfelder
                  pNext : PField; //lineare Verkettung
               end;
     

    Den Rest der Typendefinition hab ich mal weggelassen.

    Funktion:
    Code (Delphi):
     
    function list_isIn(I:TInfo; F:PField):boolean;
    begin
      if I = F^.Info then
        list_isIn := true
      else
        list_isIn := list_isIn(e, list_tail(l));
    end;
     

    list_tail() liefert nur den pNext-Zeiger

  6. #6
    Loesungsansatz 1:

    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;

    Loesungsansatz 2: Du verwendest statt Records Objekte und bietest obige Funktion als Methode an.

  7. #7
    Zitat Zitat von Ineluki Beitrag anzeigen
    Loesungsansatz 1:

    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).

  8. #8
    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.

  9. #9
    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.

    Geändert von Ineluki (14.02.2010 um 06:50 Uhr)

  10. #10
    Zitat Zitat von Brauni90 Beitrag anzeigen
    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 ^^

  11. #11
    Was hast du erwartet ?

    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.

    Geändert von Ineluki (14.02.2010 um 09:17 Uhr)

  12. #12
    Zitat Zitat von Ineluki Beitrag anzeigen
    Was hast du erwartet ?
    Hätte ja angehen können, dass es dafür eine spezielle Funktion in irgendeiner der Delphi Units gibt oder was weiß ich.

    Zitat Zitat von Ineluki Beitrag anzeigen
    PS: Ganz nebenbei, ein "Danke" haette dir auch nicht geschadet.
    Als ob darauf heutzutage noch großartig Wert draufgelegt wird ...

    Danke

    (warum auch immer diese aggressive Tonlage? ...)

  13. #13
    Zitat Zitat von Whiz-zarD Beitrag anzeigen
    Hätte ja angehen können, dass es dafür eine spezielle Funktion in irgendeiner der Delphi Units gibt oder was weiß ich.
    Und wie hätte diese bitte aussehen sollen, wenn sie keinen Speichervergleich macht? RTTI? Soviel aufwand, nur um zwei Records zu vergleichen?

  14. #14
    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.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •