Entwickler-Ecke

Sonstiges (Delphi) - Probleme mit Schleife..


DiamondDog - Fr 03.10.08 13:15
Titel: Probleme mit Schleife..
Hallo Leute,
ich hab da ein Problem mit Folgendem Code:

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:
procedure TForm1.btCheckRowClick(Sender: TObject);
var hProcess: THandle;
    i:integer;
    checkgame,gametext1:string;
    gametext2,gamefound:string;
begin
if z = 0 then
  begin
    for i:=0 to NGUinGrid.RowCount-1 do
      begin
        checkgame:=NGUinGrid.Cell[0,i].AsString;
        gametext1:=NGUinGrid.Cell[1,i].AsString;
        gametext2:=NGUinGrid.Cell[2,i].AsString;
        hProcess := GetProcessHandleFromID(GetProcessID(checkgame));
        if hProcess = 0 then z:=0;
        if hProcess = 0 then begin
          ShowMessage(checkgame + ' läuft nicht!');
        end
        else
          ShowMessage('Läuft: '+checkgame+' '+gametext1+' '+gametext2);
          z:=1;
          h:=i;
          h:=h-1;
      end;
  end;
{************************}
if z = 1 then
  begin
    gamefound:=NGUinGrid.Cell[0,h].AsString;
    gametext1:=NGUinGrid.Cell[1,h].AsString;
    gametext2:=NGUinGrid.Cell[2,h].AsString;
    hProcess := GetProcessHandleFromID(GetProcessID(gamefound));
    if hProcess = 0 then begin
      ShowMessage(gamefound + ' läuft nicht!2');
      z:=0
    end
    else
      ShowMessage('Läuft2: '+gamefound+' '+gametext1+' '+gametext2);
    end;
end;
mein Problem dabei ist das z troz das kein laufendes Spiel gefunden wurde trozdem auf 1 gesetzt wird
und ich weiß nicht ganz wieso.
Des weitern bekomme ich es irgend wie nicht hin das wenn ein Game gefunden wird,
die erste Schleife abgeprochen wird
und dann nur noch die 2te genutz wird,
biß das Spiel wieder geschlossen wird.
Kann mir da vll jemand Helfen die Fehler zu beheben?

Ps: Ich weiß der Code is hier und da noch nicht perfekt, aber das ist ja auch erstmal nur zum Testen.

Noch mal ne kurze Erklärung wie es sein sollte:
Also das alles soll später immer und immer wieder prüfen ob ein Spiel läuft.
Wenn halt keins läuft soll wieder alles durchlaufen werden.
Sollte ein Spiel gefunden werden, soll die erste Schleife abgebrochen werden
und die 2te durchlaufen werden.
Die 2te soll so lange dann prüfen ob das Spiel was an ist noch läuft bis das Spiel beendet wurde.
Wurde das Spiel beendet gehts wieder ab zu Schleife 1.

Danke schon mal fürs Helfen.

Mfg Dog


Delete - Fr 03.10.08 13:19

Da fehlt auch ein begin und ein end

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
if hProcess = 0 then begin
          ShowMessage(checkgame + ' läuft nicht!');
        end
        else begin //hier
          ShowMessage('Läuft: '+checkgame+' '+gametext1+' '+gametext2);
          z:=1;
          h:=i;
          h:=h-1
        end//und hier


DiamondDog - Fr 03.10.08 13:42

Ok hab ich geändert.
Und wie bekomme ich es hin das die 1te Schleife,
bei einem gefunden game auf hört zu suchen?

Hier nach müste die Schleife ja unterbrochen werden:

Delphi-Quelltext
1:
ShowMessage('Läuft: '+checkgame+' '+gametext1+' '+gametext2);                    
weil sonst das nächste game nicht läuft und dann z wieder auf 0 gesetzt wird.
Dann wird ja nicht die 2te Schleife aufgerufen sondern wieder die 1te.
Also muß wenn ein game gefunden wurde die 1te Schleife abgebrochen werden.


Delete - Fr 03.10.08 13:46

Welche zweite Schleife? Meinst Du, die for-Schleife soll bei Fund abbrechen? Dann gibt es 2 Möglichkeiten: break benutzen (was von manchen als unsauber angesehen wird) oder eine while-Schleife mit einer zweiten Bedingung daraus machen.


DiamondDog - Fr 03.10.08 13:55

Ahhh ok jetzt hab ich es:

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:
procedure TForm1.btCheckRowClick(Sender: TObject);
var hProcess: THandle;
    i:integer;
    checkgame,gametext1:string;
    gametext2,gamefound:string;
begin
if z = 0 then
  begin
    for i:=0 to NGUinGrid.RowCount-1 do
      begin
        checkgame:=NGUinGrid.Cell[0,i].AsString;
        gametext1:=NGUinGrid.Cell[1,i].AsString;
        gametext2:=NGUinGrid.Cell[2,i].AsString;
        hProcess := GetProcessHandleFromID(GetProcessID(checkgame));
        if hProcess = 0 then begin
          ShowMessage(checkgame + ' läuft nicht!');
          z:=0;
        end
        else begin
          ShowMessage('Läuft: '+checkgame+' '+gametext1+' '+gametext2);
          z:=1;
          h:=i;
          break;
        end;
      end;
  end;
{************************}
if z = 1 then
  begin
    gamefound:=NGUinGrid.Cell[0,h].AsString;
    gametext1:=NGUinGrid.Cell[1,h].AsString;
    gametext2:=NGUinGrid.Cell[2,h].AsString;
    hProcess := GetProcessHandleFromID(GetProcessID(gamefound));
    if hProcess = 0 then begin
      ShowMessage(gamefound + ' läuft nicht!2');
      z:=0;
    end
    else begin
      ShowMessage('Läuft2: '+gamefound+' '+gametext1+' '+gametext2);
    end;
    end;
end;
Jetzt funktioniert es 1000 Dank.


Delete - Fr 03.10.08 14:02


Delphi-Quelltext
1:
2:
3:
4:
5:
if z = 0 then
  begin
    ...
    z := 0//wozu?
  end;


Delete - Fr 03.10.08 14:51

Also ich nutze für soetwas lieber while-Schleifen, anstatt mit einem harte break aus der Schleife zu springen.


DiamondDog - Fr 03.10.08 16:23

user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
2:
3:
4:
5:
if z = 0 then
  begin
    ...
    z := 0//wozu?
  end;
Ohh hab ich wohl übersehn, das raus zu nehmen.
Aber schlimm ist es ja eigendlich auch nicht, wenn es da steht.

user profile iconLuckie hat folgendes geschrieben Zum zitierten Posting springen:
Also ich nutze für soetwas lieber while-Schleifen, anstatt mit einem harte break aus der Schleife zu springen.

Naja wie oben schon jemand sagte über break kann man sich Streiten.


jaenicke - Fr 03.10.08 17:28

Nun ja, for-Schleifen sind ja dafür da, wenn man die normale Anzahl der Durchläufe kennt, while-Schleifen, wenn man das nicht weiß. Hier kennt man die Anzahl der Durchläufe und nur, wenn ein Eintrag gefunden wird, dann springt man raus. Deshalb finde ich, dass hier die for-Schleife genau passend ist.


Delete - Fr 03.10.08 17:32

jaenicke hat folgendes geschrieben:
Hier kennt man die Anzahl der Durchläufe und nur, wenn ein Eintrag gefunden wird, dann springt man raus.
Kann das sein, dass Du Dir gerade selbst widersprichst?


jaenicke - Fr 03.10.08 18:00

Ja, ich habe das "normale" aus dem ersten Satz vergessen. Was ich meine ist, dass ein Fund und das folgende break wohl eher eine Ausnahme denn die Regel darstellt.


Delete - Fr 03.10.08 18:09

Was Luckie und ich eigentlich meinten: ist die Anzahl der tatsächlichen Durchläufe bekannt, bietet sich die for-Schleife an. Ist das nicht der Fall, ist die while-Schleife (ggf. mit einer weiteren Bedingung) die "sauberere" Alternative.


jaenicke - Fr 03.10.08 18:33

Das Problem dabei ist nur, dass dies natürlich erheblich langsamer ist. Schließlich kann eine for-Schleife optimiert werden, eine beliebige zweite Bedingung aber nicht.


Delete - Fr 03.10.08 18:51

Ob ich nun eine zweite Schleifenbedingung habe oder in der Schleife eine Abfrage, dürfte sich nicht viel tun.


jaenicke - Fr 03.10.08 19:31

Da hast du Recht, viel nicht, bei 10000 Durchläufen statt 1200 Millisekunden 2800 ist ja nicht schlimm :roll: . Naja, bei meinen Projekten ist mir das schon wichtig, wenn Schleifen teilweise millionenfach durchlaufen werden.

Beispielprojekt, ein wenig konstruiert natürlich:

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:
procedure TfrmMain.btnTestClick(Sender: TObject);

  function Variante1: Integer;
  var
    i: Integer;
  begin
    Result := 0;
    for i := 0 to memTest.Lines.Count - 1 do
      if memTest.Lines[i] <> 'a' then
        Inc(Result)
      else
        Break;
  end;

  function Variante2: Integer;
  var
    i: Integer;
  begin
    i := 0;
    Result := 0;
    while (i < memTest.Lines.Count) and (memTest.Lines[i] <> 'a'do
    begin
      Inc(i);
      Inc(Result);
    end;
  end;

var
  i: Integer;
  a, b, Start: Cardinal;
begin
  Start := GetTickCount;
  for i := 0 to 10000 do
    Variante1;
  a := GetTickCount;
  for i := 0 to 10000 do
    Variante2;
  b := GetTickCount;
  ShowMessage('Mit for: ' + IntToStr(a - Start) + ', mit while: ' + IntToStr(b - a)); // b - a, nicht b - Start
end;
// EDIT: Programm korrigiert


Delete - Sa 04.10.08 20:03

Bei dieser Art der Zeitmessung wundert mich das Ergebnis nicht. :mrgreen: Schau mal, wann Du die Startzeit nimmst und was Du danach machst.


jaenicke - Sa 04.10.08 21:17

:oops:
Das muss natürlich b - a sein, ändert aber nix am Ergebnis insgesamt, die Zahlen hätten mich allerdings stutzig machen sollen, so ist es rein vom erzeugten Assemblercode her ein logischer Zeitunterschied.
Richtig ist: 920ms mit for und 1300ms mit while, das korrigierte Testprogramm ist im letzten Beitrag aktualisiert.