Entwickler-Ecke

Grafische Benutzeroberflächen (VCL & FireMonkey) - Variable geht über for-Schleife hinaus


maxet - So 20.01.13 17:34
Titel: Variable geht über for-Schleife hinaus
Hallo Leute,

ich habe mit einer ganz simplen for-Schleife ein Problem, das mich verwirrt.

Quelltext:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure allesnachruecken;
var i,j,anzahl_nichtaktiv:integer;
begin
  for i:=0 to 8 do
  begin
    anzahl_nichtaktiv:=0;
    for j:=1 to 30 do  //hier liegt das Problem!
    begin
      if not stockwerkwartende[i,j].aktiv then inc(anzahl_nichtaktiv);
    end;
    while anzahl_nichtaktiv>0 do
    begin
      if not (stockwerkwartende[i,j].aktiv) and (j<30then stockwerkwartende[i,j]:=stockwerkwartende[i,j+1];
      dec(anzahl_nichtaktiv);
    end;
  end;
end;


Das Problem habe ich bereits mit einem Haltepunkt und Strg+F7 (Ausdruck auswerten) gefunden: die for-Schleife lässt j über 30 hinaus gehen und beim Zugriff auf den Array stockwerkwartende:

Delphi-Quelltext
1:
stockwerkwartende:array[0..8,1..30of leute                    

schmiert das Programm natürlich mit einem ERangeError ab.
Bis jetzt habe ich den Fehler nicht gefunden und ich bin ratlos :?!?:
Habt ihr eine Idee?

Vielen Dank im Voraus
maxet


Mathematiker - So 20.01.13 18:07

Hallo,
die Zählschleife wird verlassen, wenn die Zählvariable die Grenze überschreitet. D.h. j wird erhöht und wenn es größer als 30, d.h. also 31, ist, wird die Schleife verlassen.
Zitat:
Hence the for...to statement is almost, but not quite, equivalent to this while construction:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
begin
  counter := initialValue;
  while counter <= finalValue do
  begin
    statement;
    counter := Succ(counter);
  end;
end

Vorsicht aber! Bei eingeschalteter Optimierung kann j auch nach der Schleife unbestimmt sein.
Zitat:
After the for statement terminates, the value of counter is undefined.

Die Zitate sind aus der Delphi-Hilfe.

Aus diesem Grund würde ich die Zählschleife durch eine repeat-until oder while-do-Schleife ersetzen.

Beste Grüße
Mathematiker


jaenicke - So 20.01.13 18:29

Eigentlich sollte auch eine entsprechende Compilerwarnung kommen. :gruebel:
Zitat:
[DCC Warnung] UnitXXX.pas(xx): W1037 FOR-Schleifenvariable 'j' kann nach Durchlauf undefiniert sein


Tranx - So 20.01.13 20:38

user profile iconmaxet hat folgendes geschrieben Zum zitierten Posting springen:
Hallo Leute,

ich habe mit einer ganz simplen for-Schleife ein Problem, das mich verwirrt.

Quelltext:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure allesnachruecken;
var i,j,anzahl_nichtaktiv:integer;
begin
  for i:=0 to 8 do
  begin
    anzahl_nichtaktiv:=0;
    for j:=1 to 30 do  //hier liegt das Problem!
    begin
      if not stockwerkwartende[i,j].aktiv then inc(anzahl_nichtaktiv);
    end;
    while anzahl_nichtaktiv>0 do
    begin
      if not (stockwerkwartende[i,j].aktiv) and (j<30then stockwerkwartende[i,j]:=stockwerkwartende[i,j+1];
      dec(anzahl_nichtaktiv);
    end;
  end;
end;


Das Problem habe ich bereits mit einem Haltepunkt und Strg+F7 (Ausdruck auswerten) gefunden: die for-Schleife lässt j über 30 hinaus gehen und beim Zugriff auf den Array stockwerkwartende:

Delphi-Quelltext
1:
stockwerkwartende:array[0..8,1..30of leute                    

schmiert das Programm natürlich mit einem ERangeError ab.
Bis jetzt habe ich den Fehler nicht gefunden und ich bin ratlos :?!?:
Habt ihr eine Idee?

Vielen Dank im Voraus
maxet


Nach dem Verlassen ist die Schleifenvariable j nicht definiert. Das meckert eigentlich der Compiler an. Er kann auch 31 sein. Und damit würdest Du in der unterlegten Zeile schon den Grenzwert überschreiten

vieleicht schreibst Du besser:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
    if (j>=1and (j<30then
    begin
       while anzahl_nichtaktiv>0 do
       begin
         if not (stockwerkwartende[i,j].aktiv) then stockwerkwartende[i,j]:=stockwerkwartende[i,j+1];
         dec(anzahl_nichtaktiv);
       end;
    end;


Dann kann die Schleife nie über j/j+1 > 30 gehen!


maxet - Mo 21.01.13 18:21

Danke!

So dumme Fehler übersehe ich also, wenn ich stundenlang vorm Bildschirm hocke ... :autsch:
Aber komisch, der Compiler beachtet das gar nicht!? Naja.

Jetzt funktioniert es wieder :party:


jaenicke - Mo 21.01.13 21:51

user profile iconmaxet hat folgendes geschrieben Zum zitierten Posting springen:
Aber komisch, der Compiler beachtet das gar nicht!? Naja.
Wie schon geschrieben, bei mir kommt da die Warnung. ;-)