Autor Beitrag
Gonozal_IX
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mo 03.12.07 12:20 
Hallo,

ich habe ein Problem mit einer for-Schleife, wo ich selbst nichtmehr weiterkomme. Wahrscheinlich ist es nur nen trivialer Fehler und ich seh den Wald vor lauter Bäumen nicht.

Also erstmal der Code:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function TForm8.holeForschungen : Tintegerarray;
var i,k : integer;
begin

for k := 0 to 2 do
  begin
  i := 0;
    while i<2 do
      i := i+1;
  end;
end;


Der Code selbst ist erstmal recht sinnfrei, allerdings ist er ausreichend für das Problem.
Beim Debuggen ist mir aufgefallen, dass die for-Schleife einmal durchlaufen wird und zwar mit dem Wert k=3....
und ich frage mich die ganze Zeit warum, wo sie doch eigentlich 3mal durchlaufen müsste mit k=0, k=1, k=2.

Vielleicht kann mir ja jemand einen Tip geben, so dass ich meinen Denkfehler verstehe.

Lieben Gruß,
Gono.

Moderiert von user profile iconTino: Code- durch Delphi-Tags ersetzt
F4n4T!C
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 25



BeitragVerfasst: Mo 03.12.07 12:30 
mohoin^^ ... also erstmal^^ bei der for to schleife benutzt man glaube ich for k=0 to k=2

glaube so war das

dann würde ich dir raten...dass du im Formblatt (da wo du die ganzen buttons hinziehst) mal doppelt drauf klickst, und dem sagst "K:=0" damit er weiß, dass die variable ja null sein soll

versuch dass mal...lt hilft es ja^^
Gonozal_IX Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mo 03.12.07 12:35 
user profile iconF4n4T!C hat folgendes geschrieben:
mohoin^^ ... also erstmal^^ bei der for to schleife benutzt man glaube ich for k=0 to k=2


Nein ;)


Zitat:
dann würde ich dir raten...dass du im Formblatt (da wo du die ganzen buttons hinziehst) mal doppelt drauf klickst, und dem sagst "K:=0" damit er weiß, dass die variable ja null sein soll

versuch dass mal...lt hilft es ja^^


Naja, dafür instanziiert man die Variable ja in der for-Schleife direkt. Aber selbst eine Instanziierung direkt vor der Schleife hilft nicht.
Im Formblatt direkt instanziieren mag ich sie nicht, weil ich sie dann global speichern müsste *pfui*
Die Variable wird auch nur lokal in der function benötigt, also gehört sie da auch nur hin.

Lieben Gruß
Gono.
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 03.12.07 12:45 
Sollte eigentlich so funktionieren.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function TForm8.holeForschungen : Tintegerarray;
var i,k : integer;
begin
  for k := 0 to 2 do
  begin
    ShowMessage( IntToStr( k ) );   // Mach das mal dazu.
    i := 0;
    while i<2 do
      i := i+1;
  end;
end;
jackle32
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: Mo 03.12.07 12:49 
Hi,

ersmal die Syntax deiner Scheife stimmt, so wie du sie geschrieben hast. Hab sie mir auch grad 1:1 rauskopiert und getestet.

Es ist folgendes:

Wenn du k in der for Schleif nicht verwendest zählt Delphi k runter. Also in deinem Fall sind es ja drei Schritte also ist der Startwert 3 und die Schleif bricht ab wenn k Null ist. D.h. also er durchläuft die Schleif nicht nur einmal sondern schon dreimal wie gewünscht.

Wenn k jetzt benutzt wird, wenn auch nur zur Ausgabe (wie user profile iconNeurologic Scientist) vorschlägt zählt k wieder hoch.

Aber frag jetzt bitte nicht warum, könnte mir aber Vorstellen, das es was mit der Geschwindigkeit der Schleif zu tun hat, da man da auf das Nullflak im Prozessor reagieren kann und muss nicht die Abbruchbedingung jedes mal noch zusätzlcih abfragen. (Ist jetzt aber eine reine Vermutung).

Gruß Jack

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.


Zuletzt bearbeitet von jackle32 am Mo 03.12.07 12:54, insgesamt 1-mal bearbeitet
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 03.12.07 12:53 
user profile iconjackle32 hat folgendes geschrieben:
in der for Schleif nicht verwendest zählt Delphi k runter. [..] Warum das so ist hab ich keien Ahnung.

Weil der Compiler optimiert: for-Schleife läuft rückwärts.
jackle32
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 183
Erhaltene Danke: 7

Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
BeitragVerfasst: Mo 03.12.07 12:56 
Na ja nach dem Bericht hab ich doch dann mit meiner Erklärung gar nicht so falsch gelegen *stolz guck*

Gruß Jack

_________________
Es gibt keine dummen Fragen, nur dumme Antworten.
Magic J
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 66

WinXP Prof., Vista
Delphi6, Delphi 2009, Java(Eclipse), C++, Basic
BeitragVerfasst: Mo 03.12.07 13:00 
Hi

ist die auch schon aufgefallen, dass in deiner Function das RESULT fehlt?!

Sowas führt im Normalfall doch zum Fehler...

andere Fehler kann ich nun wirklich nicht endecken!

Gruß Jonas
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 03.12.07 13:03 
user profile iconMagic J hat folgendes geschrieben:
ist die auch schon aufgefallen, dass in deiner Function das RESULT fehlt?!

Sowas führt im Normalfall doch zum Fehler...

Nein. Die Funktion bleibt einfach ohne definiertes Ergebnis. Ob Du einen Wert via Result zuweist oder nicht, ist in disem Fall wurscht ... denn

user profile iconGonozal_IX hat folgendes geschrieben:
Der Code selbst ist erstmal recht sinnfrei, allerdings ist er ausreichend für das Problem.


Aber rein algorhythmisch ist es ein Fehler.
Gonozal_IX Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mo 03.12.07 13:46 
Hiho,

es gibt schon nen Result, ich hab den Code nur aufs Grundproblem gekürzt :)
Die Sache mit dem Runterzählen habe ich verstanden, das Problem ist nur, dass genauso verfahren wird, wenn ich k in der for-Schleife verwende!

.
.
.

Ok, ich hab das Problem gefunden. Es liegt dadran, dass Delphi anscheinend nicht erkennt, dass k in der Schleife verwendet wird.

Bisher hatte ich folgende Codezeile drin:

ausblenden Delphi-Quelltext
1:
i := pos(suche[k],quellcode) + Length(suche[k]);					


wobei suche ein array of string und quellcode ein string ist.
Nur mit dieser Codezeile zählt Delphi wirklich von 3 runter (obwohl suche[3] nicht definiert ist, darum auch der Fehler).

Ändert man dies ab in:
ausblenden Delphi-Quelltext
1:
2:
i := k;
i := pos(suche[k],quellcode) + Length(suche[k]);


läuft alles prima.

Auf sowas muss man erstmal kommen. Danke für die Hilfe :)

Moderiert von user profile iconTino: Code- durch Delphi-Tags ersetzt
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 03.12.07 13:53 
user profile iconGonozal_IX hat folgendes geschrieben:
ausblenden Delphi-Quelltext
1:
2:
i := k;
i := pos(suche[k],quellcode) + Length(suche[k]);


läuft alles prima.


Das find ich zu irre. So sollte es nicht sein! In dem Moment, wo Du k als Index für den String und für das Array verwendest, MUSS er eigentlich hoch- anstatt runterzählen. Sont würdest Du zum Beispiel die Items einer ComboBox trotz vorwärtslaufender Schleife rückwärts auslesen. :gruebel:

Da stimmt doch was nicht. Hast Du mit ShowMessage( ) gearbeitet? Sollte rein als Überprüfung dienen.

//Edit: Liegt es vielleicht an einem Fehler im Komplett-Code? Eigentlich unwahrscheinlich, aber man weiß ja nie. Manchmal ...

//Edit2: Und denk daran, dass Du wahrscheinlich immer noch die While-Schleife im Code hast, die ebenfalls I verwendet und I auch einen neuen Wert zuweist. Ich kenne Deinen code nicht, daher nur Spekulation, dass Du da was verhaust.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 03.12.07 14:05 
Ich habe es gerade mit Delphi 2007 und einem Stringarray ausprobiert. k benutze ich ausschließlich als Index einmal. Es funktioniert wie es soll.
Könntest du vielleicht ein komplettes Beispielprojekt anhängen und schreiben welche Delphiversion du benutzt?

Bei dir funktioniert es ja zwar jetzt, aber zumindest ich fände es interessant, herauszufinden, warum das bei dir so ist. ;-)
Gonozal_IX Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mo 03.12.07 14:19 
user profile iconjaenicke hat folgendes geschrieben:
Ich habe es gerade mit Delphi 2007 und einem Stringarray ausprobiert. k benutze ich ausschließlich als Index einmal. Es funktioniert wie es soll.
Könntest du vielleicht ein komplettes Beispielprojekt anhängen und schreiben welche Delphiversion du benutzt?


Hiho,

ich hab den Neurologic Scientist gerade ne PN geschrieben, aber da anscheinend mehr interesse besteht, hier auchnochmal der komplette Code:

ausblenden 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:
function TForm8.holeForschungen : Tintegerarray;
var quellcode : string;
    suche : array[0..3of string;
    i,k : integer;
begin
quellcode := 'Teststring Eins(1), Zwei(2), Drei(3), Vier(4)';
suche[0] := 'Eins(';
suche[1] := 'Zwei(';
suche[2] := 'Drei(';
suche[3] := 'Vier(';

for k := 0 to 2 do
  begin
      i := pos(suche[k],quellcode) + Length(suche[k]);
      suche[k] := '';
      while quellcode[i] <> ')' do
        begin
         suche[k] := suche[k] + quellcode[i];
         i := i+1;
        end;

end;
result[0] := strtoint(suche[0]);
result[1] := strtoint(suche[1]);
result[2] := strtoint(suche[2]);
end;


Und jetzt das kuriose dazu: Er geht mit k = 3 in die Schleife (laut Debugger), der Debugger zeigt mir auch an suche[k] = 'Vier('

Wenn er dann aber zur Zeile

ausblenden Quelltext
1:
suche[k] := '';					

kommt, setzt er suche[0] auf '' (was ja im ersten durchlauf sein sollte).
Ich biete auch gerne ne Bilddoku dazu^^
Ich würds selber net glauben, wenn ichs net gesehen hätte oO

Zitat:

Bei dir funktioniert es ja zwar jetzt, aber zumindest ich fände es interessant, herauszufinden, warum das bei dir so ist. ;-)


Jaaa, ich auch! *g*

Gruß,
Gono.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 03.12.07 14:57 
Ich habe mir mal den generierten Assemblercode angesehen (einfaches Integerarray). Und jetzt ist mir klar, was passiert (sowas hatte ich mir auch schon fast gedacht ;-)):
ausblenden volle Höhe 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:
Unit11.pas.31: test[0] := 1;
0045AC7E C745F401000000   mov [ebp-$0c],$00000001

Unit11.pas.32: test[1] := 2;
0045AC85 C745F802000000   mov [ebp-$08],$00000002

Unit11.pas.33: test[2] := 3;
0045AC8C C745FC03000000   mov [ebp-$04],$00000003

// Bis hierhin wird lediglich an die Speicherstellen
// der Arrayeinträge der entsprechende Wert geschrieben.

Unit11.pas.34: j := 0;
0045AC93 33DB             xor ebx,ebx
// j wird in ebx berechnet, also wird ebx auf 0 gesetzt

Unit11.pas.35for i := 0 to 2 do
0045AC95 BA03000000       mov edx,$00000003
0045AC9A 8D45F4           lea eax,[ebp-$0c]
// in edx wird die Anzahl der Durchläufe geschrieben,
// in eax kommt die Adresse des ersten Eintrags des Arrays

Unit11.pas.36: j := j + test[i];
0045AC9D 0318             add ebx,[eax]
0045AC9F 83C004           add eax,$04
// zu ebx (j) wird der Wert an der Speicherstelle eax (des aktuellen Arrayeintrags) hinzugezählt
// die Speicheradresse in eax (der aktuelle Arrayeintrag) wird um 4 (die Größe eines Integerwerts) erhöht
// --> eax zeigt jetzt auf den nächsten Arrayeintrag

Unit11.pas.35for i := 0 to 2 do
0045ACA2 4A               dec edx
0045ACA3 75F8             jnz $0045ac9d
// Schleifenzähler verringern, zurück zum Anfang der Schleife
// springen, wenn edx noch nicht 0 ist
Was passiert ist also, dass der Zugriff auf das Array über die Adresse des aktuellen Eintrags geschieht, und dieser erhöht wird bei jedem Schleifendurchlauf. Damit ist der Wert des Schleifenzählers dafür unerheblich und dieser kann rückwärts laufen.
Der Delphicode komplett:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TForm11.Button1Click(Sender: TObject);
var
  i, j: Integer;
  test: array[0..2of Integer;
begin
  test[0] := 1;
  test[1] := 2;
  test[2] := 3;
  j := 0;
  for i := 0 to 2 do
    j := j + test[i];
  ShowMessage(IntToStr(j));
end;
Gonozal_IX Threadstarter
Hält's aus hier
Beiträge: 5



BeitragVerfasst: Mo 03.12.07 15:03 
Gut,

er lässt also das Array einfach anders laufen und darum läuft die Schleife rückwert, da optimiert.
Nur warum in Herrgottsnamen kriegt das der Debugger net gebacken, mir dass dann richtig anzuzeigen *gna*

Nagut, ich danke jedenfalls vielmals für die Hilfe :)

Gono.
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 03.12.07 15:11 
Das hätte ich Dir via PN niemals so beantworten können. ;) Warum das so ist, kannst Du bei Borland nachfragen.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19315
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Mo 03.12.07 15:19 
Der Grund ist vermutlich relativ einfach. Um das korrekt anzuzeigen, müsste der Debugger an der Stelle die Information haben, dass optimiert wurde (um die Werte aus den Registern korrekt umzurechnen). Ob optimiert werden kann oder nicht, ist aber sicher nicht ganz so einfach zu entscheiden. Im erstellten Binärcode steht davon auch nix mehr drin.
Also müsste der Debugger diese Informationen durch erneute Analyse des Quelltextes erneut gewinnen. Dadurch würde das Debuggen aber langsamer werden. Deshalb ist es wohl schon eine akzeptable Lösung, dass man davon ausgeht, dass ohne Optimierung kompiliert wurde. Denn wenn etwas schief geht, würde man ja als Entwickler normalerweise sowieso Debugausgaben einbauen (was dann eine Optimierung evtl. auch unmöglich macht), und die werden ja dann korrekt angezeigt.

Dass man wissen muss, dass Schleifen intern rückwärts laufen können, macht das anfangs etwas undurchsichtig, aber wenn man das weiß (zum Beispiel durch solch einen Thread hier ;-)), dann kann man an der Stelle auch damit umgehen.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 03.12.07 15:52 
Beim Debuggen sollte man sowieso die Optimierung abschalten.