Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Sortier Algorithmus Fehlfunktion


HenryHux - So 14.11.10 22:30
Titel: Sortier Algorithmus Fehlfunktion
Hi, habe einen Algorithmus, der Karten sortiert, und Paare "löscht".
Doch irgendwas stimmt nicht.

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:
procedure TMain.SpeedButton1Click(Sender: TObject);
var index, i, curlength, zahl1, zahl2, zahl3, zahl4, zahl5, zahl6 : integer;
result : boolean;
begin
  //einlesen
  zahl1:=strtoint(edit1.Text);
  zahl2:=strtoint(edit2.Text);
  zahl3:=strtoint(edit3.Text);
  zahl4:=strtoint(edit4.Text);
  zahl5:=strtoint(edit5.Text);
  zahl6:=strtoint(edit6.Text);
  //array füllen
  setlength(ownhandarray,6);
  ownhandarray[0]:=zahl1;
  ownhandarray[1]:=zahl2;
  ownhandarray[2]:=zahl3;
  ownhandarray[3]:=zahl4;
  ownhandarray[4]:=zahl5;
  ownhandarray[5]:=zahl6;
  bubblesort(ownhandarray); //ordnet zahlen (klappt wunderbar)
  // ab hier liegt der Fehler irgendwo
  i := Succ(Low(ownhandarray));
  if Length(ownhandarray) > 0 then
    CurLength := 1
  else
    CurLength := 0;
  while i <= High(ownhandarray) do
  begin
    if ownhandarray[Pred(i)] = ownhandarray[i] then
    begin
      inc(paare);
      ownhandarray[CurLength] := ownhandarray[i];
      Inc(CurLength);
    end;
    Inc(i);
  end;
end;


Hiernach kommt dann die zuweisung anhand von der variable curlength:

Dh, wenn curlength-1=0 ist, dann ist kein paar da, wenns gleich 1 ist, dann is eins da, usw.
Da habe ich dann einen neuen array, welchen ich dann mit den ungepaarten fülle.

Doch lässt er oft einfach Paare drin.
Hat jemand eine Idee wieso?
Kann den Fehler nicht finden.

Lg

Henry


jaenicke - So 14.11.10 22:43

Du schreibst als erstes am Index CurLength. Und der ist am Anfang 1, daher wird der Index Null ignoriert.
Und wenn du kein Paar hast, erhöhst du nur i und ignorierst den Wert völlig (ein bestehendes Paar wird also nicht überschrieben). Irgendwie seltsam, ich verstehe nicht was du vorhast? :gruebel:

Was du eigentlich willst ist doch (wenn ich das richtig verstanden habe), dass du das aktuelle Element speicherst, wenn es nicht gleich dem vorhergehenden gespeicherten ist (also kein Paar).


HenryHux - So 14.11.10 23:12

Ok, ich roll das mal ein bisschen auf, vlt hilft das ja auch mir =)

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
  
  i := Succ(Low(ownhandarray));  // i kriegt den wert 1
  if Length(ownhandarray) > 0 then  //da die länge immer über 0 ist kriegt curlength auch den wert 1
    CurLength := 1
  else
    CurLength := 0;
  while pred(i) <= High(ownhandarray) do  //hier liegt glaube ein fehler, ich will ja nicht erst ab dem zweiten wert anfangen, sondern ab dem ersten, also aus i pred(i) gemacht
  begin
    if ownhandarray[Pred(i)] = ownhandarray[i] then  //falls sich zwei naheliegende werte gleich sind dann... 
    begin
      ownhandarray[i] := ownhandarray[inc(i)];  //hier lasse ich curlength am besten weg, kann mit i auch rechnen, also aus curlength i gemacht und aus i inc(i)
    end;                                        // so jetzt hat das 2te paar den wert von dem folgenden wert und wir können zum nächsten wert gehen mit inc(i)
    Inc(i);
  end;


Stimmt das so, oder sind Logikfehler drin?

Lg

Henry


jaenicke - So 14.11.10 23:29

So lässt es sich gar nicht kompilieren (wegen dem inc). Ich bin mir nicht sicher was da genau passiert, aber jedenfalls ist es nicht gerade der einfachste Weg. Was du eigentlich willst, ist doch wie gesagt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
if Length(ownhandarray) > 0 then
begin
  i := Succ(Low(ownhandarray));
  CurElement := 0;
  while i <= High(ownhandarray) do
  begin
    if ownhandarray[i] <> ownhandarray[CurElement] then
    begin
      Inc(CurElement);
      ownhandarray[CurElement] := ownhandarray[i];
    end;
    Inc(i);
  end;
  SetLength(ownhandarray, Succ(CurElement));
end;


HenryHux - So 14.11.10 23:52

Cool, danke so klappts, wäre wahrscheinlich nie drauf gekommen...
Aber eine Frage hab ich noch, frag ich mich schon länger.
Wenn ich einen Array mit SetLenth auf ne Länge setze, wieso kann ich dann die Werte, die außerhalb von dem Bereich liegen noch ansteuern?
Zwar geben die dann falsche Werte, aber keine Zugriffsverletzungen. Geben auch immer nur Werte zurück, die der Array im gültigen Bereich sowieso enthält.

Vielen Dank nochmal, hast mir sehr geholfen =)

Lg

Henry


jaenicke - So 14.11.10 23:55

user profile iconHenryHux hat folgendes geschrieben Zum zitierten Posting springen:
Wenn ich einen Array mit SetLenth auf ne Länge setze, wieso kann ich dann die Werte, die außerhalb von dem Bereich liegen noch ansteuern?
Weil Delphi sonst bei jedem Zugriff prüfen müsste, ob der Index gültig ist. Das würde aber länger dauern. Und da so etwas normalerweise ja nicht vorkommt, wird es deshalb aus Geschwindigkeitsgründen nicht geprüft.

Für das Debuggen sollte man die Prüfung natürlich ggf. in den Projektoptionen einschalten, genauso wie die Optimierung aus.