Entwickler-Ecke

Sonstiges (Delphi) - arrayprobleme


dude - Sa 05.04.03 14:00
Titel: arrayprobleme
Hi,

bei mir schliesst sich folgendes Problem mit folgendem Quelltext.

Ich habe ein 2Dimensionales Array erstellt, dann per zufall zahlen eingeordenet, und dann die Zahlen in einem Stringgrid veröffentlicht.

Problem: Nachdem ich meine Form schliesse kommt ein Delphi Komplier Fehler:

Zitat:

Im Projekt blabla.exe ist eine Exception der Klasse EAccesViolation aufgetreten. Meldung:' Zugriffsverletzung bei Adresse00401E2B im Modul 'blabla.exe'. Schreiben von Adresse 018251F0. Prozess wurde angehalten. Mit Einzelne Anweisungen oder Start fortsetzen.


Hier der Quellcode:

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:
unit arraytut;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids;

type
  TForm1 = class(TForm)
    Button1: TButton;
    StringGrid1: TStringGrid;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  arrvar : ARRAY of ARRAY of Integer;
  i : Integer=-1;
  j : Integer=0;
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var q : integer;
begin
randomize;
SetLength(arrvar,6,6);
repeat
  Inc(i,1);
  if i = 6 then begin
    Inc(j,1);
    i := 0;
  end;
  q := random(90);
  arrvar[i,j] := q;
  StringGrid1.Cells[i,j] := IntToStr(arrvar[i,j]);
until j = 6;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
j := 0;
end;

end.


An was liegt das ?

Mfg, dude


Keldorn - Sa 05.04.03 15:04

Hallo

Zitat:

An was liegt das ?


Quelltext
1:
SetLength(arrvar,6,6);                    

daran sollte das liegen, denke ich.
Du reservierst nur Speicher in der "6.Zeile für 6 Spalten" nicht für alle 6 Zeilen und 6 Spalten. Du mußt das für jede "Zeile" einzelen tun.
Schau mal in die FAQ/Tutorials, da hat sich Peter Lustig viel Mühe gemacht, lies dirs mal durch.
wenn nicht, dann vielleicht daran: dynam.array beginnen bei 0, nicht bei 1
wenn du für 6 Elelmente den Speihcer reservierst, also für [0,1,2,3,4,5] bist du mit blablablaarray[6] im niemandsland.

Warum du die ButtonClick.-Proc nicht mit 2 verschachtelten for-Schleifen erledigst, ist mir Schleierhaft.
Und die Geschichte mit i schreit förmlich nach späteren Problemen. auch das j nur bei Formcreate gesetzt wird - warum? was passiert, wenn der User ein 2. mal auf den button klickt.?? überleg mal.

Ps: randomize ist in FormCreate besser aufgehoben (siehe OH)

Mfg Frank


dude - So 06.04.03 17:14

Also erstmal,

Das Programm ist nur gebaut, damit ich lerne, wie Arrays funktionieren.
Und das habe ich ja bereits von Peter Lustigs Tut gelernt.

Also soweit ich das noch von seinem Tut in errinnerung habe, fkntioniert das auch so. Außerdem kam der Fehler ja am Ende - und nicht während der Arrayerstellung. Erst beim Form schliessen. Und es funktioniert jas auch so, bis auf die Fehlermeldung am Ende!

Und das mit dem RAndomize weiss ich schon, aber mir war das bei dem probier-Programm egal, hauptsächlich verschiedene Zahlen !


Keldorn - Mo 07.04.03 09:04

dude hat folgendes geschrieben:
Also erstmal,

Das Programm ist nur gebaut, damit ich lerne, wie Arrays funktionieren.
Und das habe ich ja bereits von Peter Lustigs Tut gelernt.

ok, das mit setlength stimmt, hab ich was dazugelernt.

Zitat:
Außerdem kam der Fehler ja am Ende - und nicht während der Arrayerstellung. Erst beim Form schliessen. Und es funktioniert jas auch so, bis auf die Fehlermeldung am Ende!

also ich habe deinen Code mal probiert, die Fehlermeldung kommt nicht immer. Reproduzierbar ist sie, wenn du nochmal auf den Button klickst. Gründe stehen oben.


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
procedure TForm1.Button1Click(Sender: TObject);
var x,y : integer;
  begin
    for x:=0 to 5 do
     for y:=0 to 5 do
      begin
        arrvar[x,y] := random(90);
        StringGrid1.Cells[x,y] := IntToStr(arrvar[x,y]);
      end;
  end;

procedure TForm1.FormCreate(Sender: TObject);
  begin
    randomize;
    SetLength(arrvar,6,6);
  end;

siehst du den unterschied?


dude - Mo 07.04.03 15:22

ja, danke erstmal, es klappt mit deiner Methode - nur peil ich die for schleife nicht... :shock:
er tut ja alles in dem for - end; inhalt 5mal wiederholen.
Dann in dem For inhalt ist ja nochmal eine schleife, die wird dann jedesmal auf 5 gezählt, obwohl eigentlich die erste schleife zuerst auf 5 zählen sollte.... und dann die 2te schleife erst ab x=1 auf y= 2 schalten sollte ...

oder funktioniert das alles nur andersrum ????? :?:


AndyB - Mo 07.04.03 18:54

Na dann vertausche die Schleifen doch einfach. Laufvariablen (i, j) sollten immer lokal (als in der Funktion) deklariert werden und nie global, denn das führt sonst zu schwer reproduzierbaren Fehlern an denen man sich Tagelang herumquält.


Keldorn - Mo 07.04.03 19:25

dude hat folgendes geschrieben:
ja, danke erstmal, es klappt mit deiner Methode - nur peil ich die for schleife nicht... :shock:
er tut ja alles in dem for - end; inhalt 5mal wiederholen.
Dann in dem For inhalt ist ja nochmal eine schleife, die wird dann jedesmal auf 5 gezählt, obwohl eigentlich die erste schleife zuerst auf 5 zählen sollte.... und dann die 2te schleife erst ab x=1 auf y= 2 schalten sollte ...

oder funktioniert das alles nur andersrum ????? :?:


warum? in deinem Code ist es doch völlig egal, wierum das ganze läuft. ansonsten tausch die Schleifen, wie andyb es dir gesagt hat.

Du mußt aber immer noch aufpassen. Für mich hat es den Eindruck, daß du noch nicht verstanden hast das dein Array von [0,0] beginnt und nicht von [1,1].
eine for-Schleife

Quelltext
1:
for i:=0 to 5 do blabla                    

wird 6-mal durchlaufen (0,1,2,3,4,5)

vielleicht hilft es dir zum Verständnis der For-Schleife auch, noch ein begin end in der 1. Schleife zu setzen

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
    for x:=0 to 5 do
      begin
        for y:=0 to 5 do
          begin
            arrvar[x,y] := random(90);
            StringGrid1.Cells[x,y] := IntToStr(arrvar[x,y]);
          end; 
      end;


Mfg Frank


dude - Di 08.04.03 13:00

nein, nein, wusst ich schon dass es erst ab 0 anfängt, und das mitem vertauschen,
habnur nicht kapiert wie die for schleifen funktionieren, weil es dort so kompliziert und unübersichtlich (für einen for-schleifen-laien) dastand!
Hab aber ein bisschen ausprobiert und kapier sie jetzt !

danke für alles!