Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Definition von einem Mengentyps, was ist hier falsch?


greenhorn - Sa 28.10.06 09:38
Titel: Definition von einem Mengentyps, was ist hier falsch?
hallo Zusammen,

der compiler hat jetzt eindeutig etwas gegen mich, oder liegts an mir? versuch grad 'ne menge zu definieren bei der ich das eine oder andere element einfügen oder löschen kann und der compi meint, das zeug verträgt sich nicht? wisst ihr's wie's geht? ich bin am verzweifeln.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
type
 tDVKListSortOption  = (dvklsoAscending,    dvklsoDesending,
                        dvklsoSortOnInsert, dvklsoNotSortOnInsert);
 tDVKListSortOptions = set of tDVKListSortOption;

 tDVKList = class
 private
  ...
  fSortOptions                   : tDVKListSortOptions;
  function  readSortOptions: tDVKListSortOptions;
  procedure writeSortOptions(const Value: tDVKListSortOptions);
 public
  property  SortOptions: tDVKListSortOptions read readSortOptions write writeSortOptions;
 ....



Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
function tDVKList.readSortOptions: tDVKListSortOptions;
begin
 result := fSortOptions;
end;

procedure tDVKList.Sort(Compare: TDVKListSortCompare);
var
 tmp, v, x, tmpExchange: tDVKListItem;
 tmpResult: integer;
begin
 tmpExchange := tDVKListItem.create; //nur einmal anlegen und bis Ende verwenden.
 try
  if  (fLauf        <> NIL//pointer initialisiert
  and (fAnkerAnfang <> NIL)
  and (fAnkerEnde   <> NILthen
  begin
   x := fAnkerAnfang.next;  // auf erstes Element positionieren
   while x <> fAnkerEnde.Prior do //liste bis zum ende durchgehen
   begin
    flauf := x; //nächstes Item zuweisen
    x := x.Next; //nächstes Item merken
    tmp := fLauf; //Merker Initialisieren
    v := fLauf.Next; //auf folgeelement positionieren
    while v <> fAnkerEnde do   //liste bis zum ende durchgehen
    begin
     tmpResult := compare(tmp.Data, v.Data);

//-->  //und hier gibts den Fehler
     if ((tmpResult < 0and (SortOptions in [dvklsoAscending]))
     or ((tmpResult > 0and (SortOptions in [dvklsoDesending])) then tmp := v; //kleinstes element merken
     v := v.Next; //auf nächstes element setzen
    end;
    if tmp <> fLauf then ExChange(fLauf, tmp, tmpExchange); //fals verändert, beide elemente tauschen
    fLauf := fLauf.Next; //auf nächstes element setzen
   end;
  end;
 finally
  tmpExchange.Free;
 end;
end;

//und hier gibts nur noch fehler
procedure tDVKList.writeSortOptions(const Value: tDVKListSortOptions);
begin
 fSortOptions := value;
//Prüfen auf mind. 1 Eintrag
 if not fSortOptions in [dvklsoAscending, dvklsoDesending] then
  fSortOptions := [dvklsoAscending];
 if not fSortOptions in [dvklsoSortOnInsert, dvklsoNotSortOnInsert] then
  fSortOptions := [dvklsoNotSortOnInsert];

//Nicht eindeutige Optionen aussschliessen und ggf. Standard wieder herstellen
 if  (fSortOptions in [dvklsoAscending])
 and (fSortOptions in [dvklsoDesending]) then
  fSortOptions := fSortOptions - [dvklsoDesending];
 if  (fSortOptions in [dvklsoSortOnInsert])
 and (fSortOptions in [dvklsoNotSortOnInsert]) then
  fSortOptions := fSortOptions - [dvklsoSortOnInsert];
end;


ist sicher wieder so 'ne kleinigkeit aber ich werd einfach nicht schlau draus...

danke für euere mühe.


greenhorn - Sa 28.10.06 17:24

hab 'n neues beispiel, erstellt. weshalb lässt sich die mengenoperation nicht in der IF Abfrage einbinden? bei BORLAND funktionierts doch auch... :gruebel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
 ttxy = (a, b, c, d);
 txy = set of ttxy;

 a1 = class
  zz: txy;
  private
    function rtxy: txy;
    procedure wtxy(const Value: txy);
  published
 public
  property u: txy read rtxy write wtxy;
  procedure test;
 end;

var
 abc: txy;
{ a1 }

function a1.rtxy: txy;
begin
 result := zz;
end;

procedure a1.test;
begin
 u := [c];

 if u in [d] then //hier krachts .... weshalb?
  writeln('test');
end;

procedure a1.wtxy(const Value: txy);
begin
 zz := value;
end;

begin
 abc := [];
 abc := [a, b];

end.


oldmax - Sa 28.10.06 19:55

Hi
Zu deinem 1. Thread. Ist vielleicht nicht das Problem, aber versuch mal die Const "Value" anders zu benennen. Es ist möglich, dass du ein Schlüsselwort erwischt hast. Was anderes ist mir im Moment nicht aufgefallen.
Gruß oldmax


greenhorn - Sa 28.10.06 21:15

hallo max,

bei den beiden ist es das selbe problem. beim ersten hab ich den code aus einer grösseren objektclasse herausgenommen, beim anderen mal separat nachvollzogen. normal sollte es gehen...

in der hilfe zum mengentype wird auf alle fälle eine entsprechende deklaration noch ausdrücklich erwähnt. so, die deklaration und benützung passt ja... nur eben die vergleiche funktionieren nicht...

aber vielleicht täusche ich mich, und der IN operator ist in den mengentypen nicht zugelassen. habs übrigens auch schon probiert die beiden parameter zum IN zu tauschen, bringt aber die selbe fehlermeldung.

es muss daher an etwas anderes liegen, ich hab nur keinen plan an was....

ich wünsch dir noch einen schönen abend


personX - So 29.10.06 14:42

Hallo,
ich hab den Quelltext mal so übernommen. Bei mir kam auch der Fehler. Hab dann an der Stelle, an der der Fehler aufgetreten ist, u und d vertauscht und die Klammern von d entfernt. Ich weiß zwar nicht, ob es jetzt noch seinen Zweck erfüllt, aber es funktioniert!

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
program Project1;


{$APPTYPE CONSOLE}


uses
  SysUtils;


type
 ttxy = (a, b, c, d);
 txy = set of ttxy;


 a1 = class
  zz: txy;
  private
    function rtxy: txy;
    procedure wtxy(const Value: txy);
  published  
 public
  property u: txy read rtxy write wtxy;
  procedure test;
 end;


var
 abc: txy;  
{ a1 }


function a1.rtxy: txy;  
begin  
 result := zz;  
end;

 
procedure a1.test;  
begin  
 u := [c];

 
 if d in u then // hab u und d vertauscht und Klammern von d entfernt
  writeln('test');
end;

 
procedure a1.wtxy(const Value: txy);  
begin
 zz := value;
end;  

 
begin  
 abc := [];
 abc := [a, b];  

 readln;
end.


greenhorn - So 29.10.06 14:48

hallo kollege,

hier soll nur geprüft werden, ob ein Eintrag im "Set IN [Menge]" vorhanden ist.

also gehören nach meinen verständnis zwei mengen in die abfrage, so dass man fragen kann ist menge1 teilmenge von menge2.

oder hab ich da nur den falschen operator erwischt?

wäre dankbar, wenn mich jemand aufklären könnte..


Nachtrag: habs noch getestet


Delphi-Quelltext
1:
2:
3:
4:
 u := [c];

 if c in u then //hier krachts .... weshalb?
  writeln('test');


und er erkennt nicht die teilmenge. es muss also eine andere lösung geben.


jaenicke - So 29.10.06 14:55

Also ich bin mir da zwar nicht hundertprozentig sicher (weil ich das bisher nie ausprobiert oder benötigt habe ;-)), aber ich kenne in nur als:
"ist ein Element in einem Set enthalten"
Das heißt: AFAIK ist es so, dass man nicht prüfen kann ob eine Menge in der anderen enthalten ist sondern nur, ob ein Element in einer Menge enthalten ist.


greenhorn - So 29.10.06 15:04

hallo zusammen,

genau das möchte ich ja auch tun. ich möchte aus einem set herausfinden, ob in diesem ein parameter gesetzt ist. nur das set kann halt mehrere parameter enthalten (sonst könnt ich gleich 'ne boolsche variable nehmen).


Delphi-Quelltext
1:
if u in c then //hier krachts .... weshalb?                    

habs noch mal probiert, hier lässt er es mir auch gar nicht zu ...

von der BDE kenn ich halt solche abfragen


Delphi-Quelltext
1:
if state in [dsinsert, dsedit] then...                    


und so etwas möcht ich halt auch gern hinbekommen...

was mach ich nur falsch? :gruebel:


jaenicke - So 29.10.06 15:12

Du fragst immer "if u in", aber u ist doch die Menge! Und die kann nicht wo drin sein! Du musst fragen ob ein Element "in u" drin ist!

In deinem ursprüngliche Code:

Delphi-Quelltext
1:
     if ((tmpResult < 0and (SortOptions in [dvklsoAscending]))                    

Stattdessen musst du aber fragen, ob dvklsoAscending in der Menge ist!!!

Delphi-Quelltext
1:
     if ((tmpResult < 0and (dvklsoAscending in SortOptions))                    


Dein BDE-Beispiel bedeutet, ob state (ein bestimmtes Element) entweder dsinsert oder dsedit ist, also ob das Element state in der Menge der beiden Elemente dsinsert und dsedit ist!


personX - So 29.10.06 15:16

Ich glaub, ich hab's jetzt:
Zitat:
so dass man fragen kann ist menge1 teilmenge von menge2.

IN ist nur dazu da, abzufragen, ob ein Element in einer Menge ist.
Wenn du mit Teilmenge arbeiten willst, musst du <= verwenden.

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure a1.test;
begin
 u := [c];


 if u <= [d] then //hier krachts .... weshalb?
  writeln('test');
end;

Wenn u Teilmenge von [d] ist, dann schreibe "Test".


jaenicke - So 29.10.06 15:29

Er hat doch gerade geschrieben, dass er gar keine Teilmengen will, und als ich mir seinen ersten Source nochmal angesehen habe, habe ich auch gemerkt, was da falsch ist...
Wie ich eben auch geschrieben habe. Er hat nur statt "Element in Menge" geschrieben: "Menge in [Element]".


greenhorn - So 29.10.06 17:22

hallo zusammen,

ja, jetzt funktionierts...

@jaeneke: wusste gar nicht, dass man keine mengen/variablen für die IN abfrage braucht.

@personX: genau, das hab ich gesucht :-)

beide möglichkeiten funktionieren

dank und gruss :beer: :beer: