Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - 2-dimensionales Array befüllen


Sunsurfer79 - Di 18.05.10 14:16
Titel: 2-dimensionales Array befüllen
Hallo Zusammen.

Ich komme bei einer Aufgabe zu 2-dimensionalen Arrays nicht weiter.
Hier mal die Aufgabenstellung:

Schreiben Sie eine Funktion Format der als Parameter eine Variable M vom Typ
TMatrix übergeben wird. Der Funktionswert soll vom Typ TIntListe sein und die
Länge der einzelnen "Zeilen" von M enthalten.

Vorgaben:
TListe=array of Double,
TMatrix=array of TListe;
TIntListe=array of Integer;

Die Function "Format" zum Auslesen der Längen der Zeilen von M sollte soweit stimmen.
Ich schaffe es jedoch nicht das Array im Hauptprogramm zu befüllen, um es zu probieren.
Er schreibt mir die Zahlen alle untereinander
Es ist ja im Endeffekt ein Array of Array of double, oder?
Es soll eine Tabelle mit 10 Zeilen enstehen, die jedoch zufallsgesteuert verschieden lang sein sollen,
um dann die länge der einzelnen Zeilen als Funktionswerte zu erhalten.

Bsp:
xxxxx (5)
xxxxxxxxx (9)
xxxxxxx (7)
xxxxxxxxxxx (11)
(usw.)

Vielen Dank im Voraus.

MFG Sören

Hier der Quellcode:


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:
program Aufgabe3;

{$APPTYPE CONSOLE}

uses SysUtils;

Type TListe=array of double;
     TMatrix=array of TListe;
     TIntListe=array of integer;

var M:TMatrix;
    i,j:integer;
function format(M:TMatrix):TIntListe;
var k:integer;
begin
  for k:=0 to high(M) do
  begin
    result[k]:=length(M[k]);
    write(result[k]);
    readln;
  end;
end;

begin
  randomize;
  setlength(M,10,random(10)+2);
  for i:=0 to high(M) do
  for j:=0 to high(M) do
  begin
    M[i,j]:=random(20);
    writeln(M[i,j]:2:0);
  end;
  readln;
  //format(M);
end.


BenBE - Di 18.05.10 14:27

Durch dein ReadLn; werden Zeilenumbrüche in der Ausgabe erzeugt. Nehm das ml raus und schreib das am Ende deiner Hauptprozedur einmalig.

Ansonsten: SetLength mit 3 Argumenten setzt für jede der Zeilen die gleiche (im 3. Parameter gegebene) Länge. Wenn Du für jede Zeile was anderes haben willst, müsstest Du SetLength(M, 10); einmalig aufrufen gefolgt von SetLength(M[k], Random(10)); für jede einzelne Zeile k.

HTH.


bummi - Di 18.05.10 14:34


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:
program Aufgabe3;

{$APPTYPE CONSOLE}

uses SysUtils;

Type TListe=array of double;
     TMatrix=array of TListe;
     TIntListe=array of integer;

var M:TMatrix;
    i,j:integer;
function format(M:TMatrix):TIntListe;
var k:integer;
begin
  SetLength(result,high(M));
  for k:=0 to high(M) do
  begin
    result[k]:=High((M[k])) + 1;
    writeln(IntToStr(k) + ':' + IntToStr(result[k]));

  end;
end;

begin
  randomize;
  setlength(M,random(10)+2);
  for i:=0 to high(M) do
  begin
  setlength(M[i],random(10)+2);

  for j:=0 to high(M[i]) do
  begin
    M[i,j]:=random(20);
    writeln(M[i,j]:2:0);
  end;
  end;
  writeln('Kommt');
  format(M);
  readln;



end.


Sunsurfer79 - Di 18.05.10 16:02

Danke für die Hilfestellungen.

ist es generell besser mit high statt length zu arbeiten? (Bsp: for i:=0 to high(M))
ist doch eigentlich das gleiche, oder?

Ich habe das Programm jetzt korrigiert und abgeändert. Leider stürzt es bei ca. jedem 3. Durchlauf mit "ungültige Zeigeroperation" ab. Ich weiß leider nicht, woran das liegen könnte.

Ich kriege auch die Ausgabe des 2-Dimensionalen Arrays in Tabellenform noch nicht hin. Er schreibt alles fleißig untereinander. Wenn die beiden Sachen noch behoben werden könnten, wäre es perfekt. :-)


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:
program Aufgabe3;

{$APPTYPE CONSOLE}

uses SysUtils;

Type TListe=array of double;
     TMatrix=array of TListe;
     TIntListe=array of integer;

var M:TMatrix;
    i,j:integer;

function format(M:TMatrix):TIntListe;
var k:integer;
begin
  SetLength(result,high(M));
  for k:=0 to high(M) do
  begin
    result[k]:=high(M[k]);
    writeln(k+1:2,':',result[k]:3);
  end;
end;

begin
  randomize;
  setlength(M,10);
  for i:=0 to high(M) do
  begin
    setlength(M[i],random(10)+5);
    for j:=0 to high(M[i]) do
    begin
      M[i,j]:=random(20);
      writeln(M[i,j]:2:0);
    end;
  end;
  writeln;
  format(M);
  readln;
end.


bummi - Di 18.05.10 16:20

sorry :

Delphi-Quelltext
1:
SetLength(result,high(M) + 1);                    


Moderiert von user profile iconNarses: Delphi-Tags hinzugefügt


Tilo - Di 18.05.10 18:31

user profile iconSunsurfer79 hat folgendes geschrieben Zum zitierten Posting springen:

ist es generell besser mit high statt length zu arbeiten? (Bsp: for i:=0 to high(M))
ist doch eigentlich das gleiche, oder?

Nicht immer. In Verbindung mit Low() kannst Du bei Schleifen über Arrays ungekannter Größe sicher gehen das es zu keinen IndexOutOfRange kommt.
Ich hatte zum Beispiel mal ein Array von 1 bis 4 definiert.
In einer subfuntion schrieb ich folgendes:

Delphi-Quelltext
1:
2:
for i:=1 to 4 do
 dosomethingwith(array[a]);

Da die Funktion aber in einem anderem Kontext als die Arraydefinition lief und das Array als Parameter übergeben wurde (@all: bitte nicht hauhen) kam es zu einem IndexOutOfBounce.
Lösung war folgender Code:

Delphi-Quelltext
1:
2:
for i:=low(arrayto high(arraydo
 dosomethingwith(array[a]);

Grund: Durch die Übergabe als Parameter wurde der Indexraum des Arrays zu 0..3.
Low() und High() geben für arrays den kleinsten bzw größten Index zurück (klappt auch bei mehrdimensionalen Arrays).
High() entspricht Length()-1 bei Arrays solange du von 0 anfängst zu zählen.

Kleiner Spruch am Rande:
Es gibt folgende Leute, 1. die mit 1 anfangen zu zählen und 1. die mit 0 anfangen zu zählen.


Sunsurfer79 - Di 18.05.10 18:56

OK, danke,

Und warum funktioniert das Programm nicht ohne das +1?

SetLength(result,high(M)+1) = Das Array soll die Länge von M+1 annehmen also Index [0..10]

setlength(M,10) = Der Indexraum von M ist [0..9]

Warum braucht das Ergebnis-Array den einen Index mehr?


Tilo - Mi 19.05.10 08:58

Das ist einfach zu Erklären.

Du hast ein Array A, z.B. definiert von 1 bis 7 in der ersten Dimension und ein Array B definiert von 0 bis 7.
Low(A)=1, High(A)=7, Length(A)=7, Low(B)=0, High(B)=7, Length(B)=8
Der mathematische Zusammenhang zwischen Low(), High() und Length() ist: Length(x)=High(x)-Low(x)+1.

Im 2. Array möchteset Du nun den jeweiliges größten der 2. Dimension des ersten Arrays speichern. Bei einem Index von [0..6] wird ein 7-Elemente Arary benötigt.
Das sicherste vorgehen dürfte hier folgender Code sein:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
Setlength(ArrayB,length(ArrayA));//=> Array B hat nun die gleiche Länge wie A. Vermutlich Definiert von 0 bis length-1
i2:=low(ArrayB); //initialisierung für den Durchlauf von ArrayB
for i1:=low(ArrayA) to high(ArrayA) do //=> vom kleinsten bis größten Index des ersten Arrays durchlaufen
begin
  ArrayB[i2]:=high(ArrayA[i1]);
  //weitere Aktionen
  inc(i2);
end;

Dieser Code hat den Vorteil, dass es egal ist wie die einzelnen Arrays vom Compiler definiert werden.