Entwickler-Ecke

Sonstiges (Delphi) - Programm hängt sich auf wegen ner Schleife


F.Art - Mi 15.01.03 03:03
Titel: Programm hängt sich auf wegen ner Schleife

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
 for x:=1 to strtoint(Anzahl.text) do 
 For i := 0 To (AbsenderNamenListe.Items.Count-1) do

begin
    idMessage.Body.Add(NachrichtenListe.Items.Strings[i]);

   idSMTP.Connect;
   idSMTP.Send(idMessage);
   idSMTP.Disconnect;

Application.ProcessMessages;
Anzahl.text := inttostr(strtoint(Anzahl.Text) - 1);
if Anzahl.Text=('0') then goto Ende;
end;


sobalt ich die Zeile

Quelltext
1:
For i := 0 To (AbsenderNamenListe.Items.Count-1) do                    

weg lasse geht es ansonsten hängd sich das programm auf oder sendet nur langsam. hat einer ne lösung?


KeinePanik - Mi 15.01.03 03:31

Na da fehlt ja auch ein begin und ein end wenn ich das richtig sehe :


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
for x:=1 to strtoint(Anzahl.text) do 
[b]begin[/b]
For i := 0 To (AbsenderNamenListe.Items.Count-1) do 

begin 
    idMessage.Body.Add(NachrichtenListe.Items.Strings[i]); 

   idSMTP.Connect; 
   idSMTP.Send(idMessage); 
   idSMTP.Disconnect; 

Application.ProcessMessages; 
Anzahl.text := inttostr(strtoint(Anzahl.Text) - 1); 
if Anzahl.Text=('0') then goto Ende; 
end;
[b]end;[/b]


// edit:

(die "end;"'s musst du natürlich dorthin setzen, wo die jeweilige Schleife aufhören soll ... sind erstmal willkürlich gesetzt ...)


Anonymous - Mi 15.01.03 04:21

Da fehlen einige Zeilen Code. Außerdem


Quelltext
1:
... goto Ende;                    


beendet keine Schleife. Versuchs mal mit Break.


Quelltext
1:
if Anzahl.Text='0' then Break;                    


Dann mischt du zwei For-Schleifen durcheinander. Ein mal ist da


Quelltext
1:
for x:=1 to strtoint(Anzahl.text) do                    


dann


Quelltext
1:
For i := 0 To (AbsenderNamenListe.Items.Count-1) do                    


allerdings wird in der Schleife der Wert in Anzahl.Text dekrementiert.


Quelltext
1:
Anzahl.text := inttostr(strtoint(Anzahl.Text) - 1);                    


Wozu dann die erste Schleife?

Ich zum Beispiel blick da nicht durch. Glaubst du, daß der Compiler das kann?


KeinePanik - Mi 15.01.03 05:13

Popov hat folgendes geschrieben:

Quelltext
1:
... goto Ende;                    

beendet keine Schleife. Versuchs mal mit Break.


nur zu meiner Info ... da geht doch auch "exit" !? (oder wo liegt da der Unterschied !?) ...

Zitat:

Dann mischt du zwei For-Schleifen durcheinander. Ein mal ist da

Quelltext
1:
for x:=1 to strtoint(Anzahl.text) do                    

dann

Quelltext
1:
For i := 0 To (AbsenderNamenListe.Items.Count-1) do                    



das wollte ich mit meinem Posting sagen ... kam wohl nicht so rüber ...

Mal ne dumme Frage :D :
Zitat:

allerdings wird in der Schleife der Wert in Anzahl.Text dekrementiert.


was bedeutet "dekrementiert" !?!?

Zitat:

Ich zum Beispiel blick da nicht durch. Glaubst du, daß der Compiler das kann?


Also irgendwie fehlt mir bei dem Code auch der Durchblick ...

//edit :

Ich geb einen aus auf meinen 111-ten Beitrag .... trinkt das, was Ihr mögt !!! ... Auf Kosten von KP ;-)))


F.Art - Mi 15.01.03 05:14

Also die Anzahl ist dafür da das er von einer eingegeben zahl abzählt und die andere dazu das jede nachricht einen anderen text bekommt


KeinePanik - Mi 15.01.03 05:27

also wie gesagt, hast du zumindest erstmal mindestens jeweils ein "begin" und ein "end;" vergessen ...


UGrohne - Mi 15.01.03 09:46

@KeinePanik: Das mit Exit funktioniert net, Exit bricht die Prozedur ab, mit Break verlässt Du nur die jetzt laufende Schleife.


KeinePanik - Mi 15.01.03 10:03

@UGrohne :

Aha ... danke für die Info !!! ... bis jetzt habe ich das so nicht gebraucht ... sollte man (vor allem ich :D ) aber wissen :wink:


Keldorn - Mi 15.01.03 10:08

Hallo

die for Schleifen m,üssen nicht unbedingt in begin/end stehen

Quelltext
1:
2:
3:
4:
5:
6:
for x:=1 to 10 do
 for y:=1 to 10 do
  begin
    machwas (x,y);
    machnochwas 
  end;

ist möglich
anders wäre das hier, hier ist begin7end bei der 1. for schleife notwendig:

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
for x:=1 to 10 do
 begin
  for y:=1 to 10 do
   begin
     machwas (x,y)
     machnochwas 
   end;
  machwasandersmitx(x);
 end;


Mfg Frank


KeinePanik - Mi 15.01.03 10:17

Keldorn hat folgendes geschrieben:

die for Schleifen m,üssen nicht unbedingt in begin/end stehen

Quelltext
1:
2:
3:
4:
5:
6:
for x:=1 to 10 do
 for y:=1 to 10 do
  begin
    machwas (x,y);
    machnochwas 
  end;

ist möglich


Wieder was gelernt .... .... .... (muss ich aber erstmal selbst ausprobieren, bevor ich das glaub, denn irgendwie versteh ich den Sinn nicht so ganz, warum das so gehen sollte ...) .... .... ....

so wie ich den Code von "F.Art" aber verstanden habe, sind das zwei "unabhängige" Schleifen ... deshalb "fehlen" da auch das "begin" und das "end" ((!?)) ....


Keldorn - Mi 15.01.03 10:47

Doch das geht.
for i:=0 to 10 do machwas

und das machwas ist dann halt wieder selbst ne Schleife.

weiß aber auch nicht,was bei Fart die erste Forschleife soll, da der Wert x überhaupt keine Verwendung findet.

die Sache von Fart hat noch den Fehler: da bin ich auch schon mal drüber gestolpert.
Anfang und Ende der Schleife werden vorm Eintritt der Schleife festgelegt, ein nachträgliches Ändern der Start und endwerte innerhalb der schleife hat keine auswirkung.

Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
Var i,ende:integer;
begin
  ende:=10;
  for i:=1 to ende do
    begin
      ende:=5;
      listbox1.items.add(inttostr(i));
    end;
end;

dann stehen in der listbox trotzdem 10 einträge statt 5.
wenn sich in der Schleife der Endwert ändern soll, kann man das in einer while schleife realisieren.

Mfg Frank


UGrohne - Mi 15.01.03 10:52

for x:=0 to ... do machwas

wird eben als eine Anweisung verstanden, deswegen wird beim vorherigen Block kein begin end; gebraucht. Erst, wenn eine Schleife mehrere Anweisungen ausführen muss, wird der Block gebraucht.

for kann man sozusagen als rekursive Funktion auffassen, denk ich mal so.

BTW: Zum Glück programmieren wir nicht C, da bräuchte man ja immer ein {}-Block *g*


KeinePanik - Mi 15.01.03 12:13

aha ... also


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
var xcount, ycount : integer;

for X := 1 to 10 do

{DAS WÄRE DANN DIE "ZUSAMMENHÄNGENDE" ANWEISUNG !? ... ich dachte hier wäre noch ein "begin" erforderlich ...}
for Y := 1 to 10 do
begin
ycount := ycount +1;
{...}
end;

{BIS HIER ... Y := 0 to 10 ... (und hier eben ein "end;" erforderlich) ...
 ab hier wieder X := 1 to ... ...}
xcount := xcount + 1;
{...}


Zum schluss sollte ycount 100 sein und xcount 10 ... muss ich echt mal ausprobieren ... ist mir neu, dass das so geht ...


Anonymous - Mi 15.01.03 12:36

KeinePanik hat folgendes geschrieben:
was bedeutet "dekrementiert" !?!?


Dekrement - laut Wörterbuch: Abnahme, Verminderung, Verfall.

Guck dir auch die Delphiprozedur "Dec". Es gibt auch den Inkrement. Guck dir auch die Delphiprozedur "Inc". Das sind zwei der elementaren Befehle einer jeden Programmiersprache und zu finden auch in einfachsten Sprachen, wie z.B. Assembler. Es gibt Sprachen die überhaupt keine For-Schleifen kennen. Dank Dec und Inc kann man mit ihnen denoch programmieren. Deshalb dachte ich, daß der Begriff bekannt ist.

Zu Begin und End in den For-Schleifen. Wie schon bereits kurz bemerkt: Begin und End braucht man nur dann, wenn der Block aus mehr als einer Anweisung besteht. Dabei ist es aber egal, ob die Anweisung ihrerseits einen Block von mehreren Zeilen hat. Falsch ist es nicht, aber nicht zwingend erforderlich. Allerdings hat diese Weisheit auch Hacken:

if a = b then if c = d then a := b else a := c;

Hier ist alles richtig. Allerdings wird der Compiler garantiert einen Fehler machen, denn er wird nicht durchblicken zu welcher If die Else gehört. Na?

if a = b then begin if c = d then a := b end else a := c;


KeinePanik - Mi 15.01.03 13:00

"dec" und "inc" (decrease und increase) ist schon klar ... mir war nur nicht bewusst, dass dieses Wort eingedeutscht wurde (bzw. bereits als "deutsches" Wort existiert ...) ... und das mit dem "else" und dass der Compiler nicht weiss, zu welcher Schleife das nun gehört, auch ....

Aber das ist ja (glaub ich) gerade die Frage von F.ART ... Der Compiler kommt m.E. eben nicht in seinem Code mit den zwei Schleifen zurecht !!! Also sollte er die beiden Schleifen "genauer" definieren ... eben mir einem zusätzlichen "begin" und "end;" ...


Anonymous - Mi 15.01.03 14:11

Ja, aber diese obere Ausnahme gilt nur für if-then Abfragen. Alle anderen Schleifen und Anfragen haben kein Else. Deshalb dürfte es sonst nicht zu Problemen kommen.


Raphael O. - Mi 15.01.03 14:14

Zitat:
Zum schluss sollte ycount 100 sein und xcount 10 ... muss ich echt mal ausprobieren ... ist mir neu, dass das so geht ...

geht auch nicht...
du kannst das begin..end; nur weglassen, wenn dur nur eine Anweisung ausführen willst--> es wird nur die Anweisung, die direkt hinter dem for i:=1 to 10 do ausgeführt...
in deinem Fall würde das xcount also nicht erhöht werden...

Fiji-Fighter


KeinePanik - Mi 15.01.03 14:31

Fiji-Fighter hat folgendes geschrieben:
geht auch nicht...
es wird nur die Anweisung, die direkt hinter dem for i:=1 to 10 do ausgeführt...


Darum gehts ja (siehe CODE im Themenstart) ... mir will nicht einleuchten, warum nach dem ersten for ... do nicht noch ein "begin" kommen soll um die zweite Schleife zu umfassen, die eben mehrere Anweisungen hat, wie (offensichtlich) die erste FOR-Schleife auch !!!

wenn der Code nach folgendem Schema aufgebautn wäre:

Quelltext
1:
2:
3:
4:
5:
{erste schleife}for x:=1 to 10 do showmessage(inttostr(x)); // erste Schleife ist hier eben abgeschlossen ...
{erste schleife}for y:=1 to 10 do
begin
{... mehrere Anweisungen ...}
end;


wär ja alles klar ... ist er aber nicht ... Ich glaub Ihr missversteht mich (oder drück ich mich unglücklich aus !?) ...

Zitat:

Alle anderen Schleifen und Anfragen haben kein Else.


ja klar !!! ... aber die schleifen müssen eben dann anderweitig "abgeschlossen" werden, was im Themenstart ja nicht der Fall ist, da die 2. Schleife eben mehrere Anweisungen beinhaltet und dort eben noch ein "begin" und ein "end;" hinkommen muss,sollte, was auch immer ...


Raphael O. - Mi 15.01.03 14:38


Quelltext
1:
2:
3:
4:
5:
6:
7:
for i:=1 to 10 do
for y:=1 to 10 do
 begin
  doanything;
  doanything2;
 end;
doanything3;//hierstartet der zwite befehl!!

Also!
er geht die erste for-Schleife durch und behandelt wegen fehlendem begin nur den nächsten Eintrag: also die zweite for-Schleife...
und zu der for schleife gehört auch noch doanything1+2 während doanything3 schon der zweite befehl ist und deshalb nur einmal ausgeführt wird!

Fiji-Fighter


F.Art - Mi 15.01.03 14:43

jetzt habt ihr mich estwas verwirrt. ich werde mir inruhe mal die texte durch den kopf gehen lassen. so jetzt versuche ich mal zu erklären was ich genau vorhabe.

also jenach smtp server den ich nehmen geht das sogar so schon aber ich suche ne möglichkeit um eine schleife (die Anzahl) solange wieder holen zu lassen bis es bei 0 angekommen ist. zusätzlich soll bei jedem mal zwei verschiedene listbox um einen text weiter springen.

-So gehts aber nicht gut -


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
for x:=1 to strtoint(Anzahl.text) do 
For i := 0 To (AbsenderNamenListe.Items.Count-1) do 
begin 
    idMessage.Body.Add(NachrichtenListe.Items.Strings[i]);
    idMessage.Subject.Add(BetreffListe.Items.Strings[i]);
Application.ProcessMessages; 
Anzahl.text := inttostr(strtoint(Anzahl.Text) - 1); 
if Anzahl.Text=('0') then Break;
end;


- so irgendwie ? -


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
for x:=1 to strtoint(Anzahl.text) do 
begin 
    i := -1;// das diese Zeile nicht geht weis ich aber wie dann?
    idMessage.Body.Add(NachrichtenListe.Items.Strings[i]);
    idMessage.Subject.Add(BetreffListe.Items.Strings[i]);
Application.ProcessMessages; 
Anzahl.text := inttostr(strtoint(Anzahl.Text) - 1); 
if Anzahl.Text=('0') then Break;
end;


KeinePanik - Mi 15.01.03 14:51

hmm fiji ...

so würde ich das (der Übersicht wegen) nie machen ... man sieht ja an diesem Thema, zu welchen Missverständnissen das führt (meinerseits) ...

egal ... Thema (für mich) abgehakt ...


Anonymous - Mi 15.01.03 14:52

@KeinePanik

Doch


Quelltext
1:
2:
3:
4:
5:
6:
for x := 0 to 10 do 
  for y := 0 to 10 do begin
    Anweisung1
    Anweisung2
    ...
  end;


Die Regel ist: Wenn du eine Anweisung ausführen willst, dann brauchst du kein begin..end. Erst wenn du mehrere Anweisung zusammenfassen willst, erst dann brauchst du begin..end. for y := 0 to 10 do ist für for x := 0 to 10 do nur eine Anweisung. Deshalb kein begin..end. for y := 0 to 10 do muß dagegen zwei Anweisungen ausführen, deshalb ein Anweisungsblock.


Raphael O. - Mi 15.01.03 14:56

du musst vor der schleife i initialisieren!

Quelltext
1:
i:=AbsenderNamenListe.Items.Count-1;                    


außerdem:

Quelltext
1:
i:=-1;                    

so geht das nicht, denn dann ist i immer "-1"--> also so:

Quelltext
1:
i:=i-1;                    


am Ende musst du überprüfen ob
x=0 ist und nicht ob Anzahl.text=0 ist!!!

weitere Fragen???

Fiji-Fighter


KeinePanik - Mi 15.01.03 14:59

ja es funktioniert so ...

ich schreib mir aber bei jeder Schleife nen Kommentar dahinter, so dass es für MICH mit einem zusätzlichen "begin" und "end;" übersichtlicher ist ... selbst wenn die erste Schleife nur "EINE" Anweisung hat ...


Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
for x := 0 to 10 do 
begin //Schleife1
  for y := 0 to 10 do 
   begin //Schleife2
     Anweisung1 
     Anweisung2 
    ... 
  end;//Schleife2
end; //Schleife1


So ist eben MEIN Stil, deshalb bin ich zunächst nicht mit euren Aussagen klar gekommen ... (jetzt ist es klar ... und auch logisch ... nur ungewohnt) ...


Anonymous - Mi 15.01.03 15:03

@F.Art

Wieso immer noch zwei mal


Quelltext
1:
2:
3:
4:
5:
6:
for x:=1 to strtoint(Anzahl.text) do 
begin 
   ...
  Anzahl.text := inttostr(strtoint(Anzahl.Text) - 1); 
  if Anzahl.Text=('0') then Break;
end;


Einmal als for x:=1 to strtoint(Anzahl.text) do Schleife, dann aber auch noch als Anzahl.text := inttostr(strtoint(Anzahl.Text) - 1).

Mit der x Schleife wird doch schon bis Anzahl.text gezählt. Wieso dekrementierst du noch mal Anzahl.text am ende des Blocks?

ist das gleiche wie :


Quelltext
1:
2:
3:
4:
5:
for x:=1 to strtoint(Anzahl.text) do 
  for x2:=(strtoint(Anzahl.text) - 1) downto 0 do 
  begin 
     ...
  end;


Ist unlogisch. Das hab ich dir aber schon am anfang geschrieben.

Irgendwie hab ich das gefühl, daß du meine Antworten ignorierts. Ist das so? Wenn ja, dann schreib mir ein KM warum und ob ich es lassen soll.