Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Sortierroutine stürtzt ab, wenn eine 0 enthalten ist


Sunsurfer79 - Mi 19.05.10 15:33
Titel: Sortierroutine stürtzt ab, wenn eine 0 enthalten ist
Hallo Zusammen,

Folgende Aufgabenstellung:

Vorgaben:

Delphi-Quelltext
1:
2:
3:
4:
Type TPaar=Record
     x,y:double;
     end;
TTabelle=array of Tpaar;
Schreiben Sie eine Prozedur Sortieren, der als Parameter ein Dateiname übergeben wird. Dateiname steht für typisierte Datei mit Komponententyp TPaar. Die Funktion soll die Wertepaare lesen und nach wachsenden y-Werten sortieren. Die sortierten Wertepaare sollen in die gleiche Datei zurück geschrieben werden. Die Dateigröße wird sich also nicht ändern. Bei weniger als 2 Wertepaaren braucht und soll nicht sortiert werden. Tipp: Verwenden Sie Variablen der obigen Typen.

Folgendes Problem: Solange im Record TPaar keine Nullen enthalten sind funktioniert es wie es soll. Wenn eine 0 enthalten ist, wird auch ordentlich sortiert, aber dann gibts eine Exception "ungültige Zeigeroperation". Ich weiß leider nicht woran das liegt.

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:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
program Aufgabe4;

{$APPTYPE CONSOLE}

uses
  SysUtils;
Type TPaar=Record
           x,y:double;
           end;
TTabelle=array of Tpaar;

var Hilfsvar,Tabelle:TTabelle;
    i:integer;
    f:file of TPaar;


procedure Sortieren(Dateiname:String);

var tauschen:boolean;
    i:integer;
    //t:textfile;
begin
  assignfile(f,Dateiname);
  //assignfile(t,'Kontrolle.txt');
  reset(f);
  //rewrite(t);
  if filesize(f)<=1 then
  begin
    writeln('nur 1 Zahlenpaar - es wird nicht sortiert');
    readln;
    exit;
  end
  else
  setlength(Tabelle,filesize(f));
  setlength(Hilfsvar,filesize(f));
  for i:=0 to filesize(f)-1 do
  begin
    read(f,Tabelle[i]);
  end;
  repeat
  tauschen:=false;
  for i:=0 to high(Tabelle) do
  begin
    if Tabelle[i].y<Tabelle[i+1].y then
    begin
      tauschen:=true;
      Hilfsvar[i]:=Tabelle[i];
      Tabelle[i]:=Tabelle[i+1];
      Tabelle[i+1]:=Hilfsvar[i];
    end;
  end;
  until tauschen=false;
  writeln('    Y-Werte:   X-Werte:');
  for i:=0 to high(Tabelle) do
  begin
    writeln(i+1:2,':',Tabelle[i].y:6:0,Tabelle[i].x:12:0);
    write(f,Tabelle[i]);
    //writeln(t,Tabelle[i].y:2:0,Tabelle[i].x:4:0);
  end;
  readln;
  closefile(f);
  //closefile(t);
end;


begin
  assignfile(f,'Datei.dat');
  {$I-}
  rewrite(f);
  randomize;
  setlength(Tabelle,random(10)+5);
  writeln('    X-Werte:   Y-Werte:');
  for i:=0 to high(Tabelle) do
  begin
    Tabelle[i].x:=random(100);
    Tabelle[i].y:=random(60);
    writeln(i+1:2,':',Tabelle[i].x:6:0,Tabelle[i].y:12:0);
    write(f,Tabelle[i]);
  end;
  closefile(f);
  readln;
 {$I+}
  Sortieren('Datei.dat');

end.


Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt
Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.


MaPsTaR - Mi 19.05.10 15:49

Hallo,
ich kann mich zwar auch irren, aber kann es sein, dass diese Zeilen deine Exception auslösen?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
  for i:=0 to high(Tabelle) do
  begin
    if Tabelle[i].y<Tabelle[i+1].y then
    begin
      tauschen:=true;
      Hilfsvar[i]:=Tabelle[i];
      Tabelle[i]:=Tabelle[i+1];
      Tabelle[i+1]:=Hilfsvar[i];
    end;


Du zählst in der Schleife bis zum letzten Eintrag in Tabelle...
Wenn i = High(Tabelle) erzeugt i+1 also eine Fehlermeldung, oder??


bummi - Mi 19.05.10 15:49

beim drüberfliegen fällt mir auf daß Du in ungültige Speicherbereiche fasst:

Delphi-Quelltext
1:
2:
3:
 for i:=0 to high(Tabelle) do
  begin
    if Tabelle[i].y<Tabelle[i+1].y then


high(Tabelle) vs Tabelle[i+1].y


Sunsurfer79 - Mi 19.05.10 15:57

Deswegen: for i:=0 to filesize(f)-1



Delphi-Quelltext
1:
2:
3:
setlength(Tabelle,filesize(f));
setlength(Hilfsvar,filesize(f));
for i:=0 to filesize(f)-1 do


Er schaut dann aber trotzdem bei Tabelle[i+1] noch mal nach ob da noch einer größer ist.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
    if Tabelle[i].y<Tabelle[i+1].y then
    begin
      tauschen:=true;
      Hilfsvar[i]:=Tabelle[i];
      Tabelle[i]:=Tabelle[i+1];
      Tabelle[i+1]:=Hilfsvar[i];
    end;


Es funktioniert ja, jedoch nicht wenn eine 0 bei Tabelle[i].y auftaucht.


MaPsTaR - Mi 19.05.10 16:05

Aber das ist doch eine neue Schleife...

Ich glaube ehrlich gesagt nicht, dass das an der 0 liegt.

Versuch mal das.


Delphi-Quelltext
1:
for i:=0 to high(Tabelle)-1 do                    


Sunsurfer79 - Mi 19.05.10 16:17

Super, danke.

Das war es...nur komisch, daß es vorher auch funktioniert hat, wenn keine 0 als Y-Wert generiert wurde.
Kann ich mir nicht erklären.