Autor |
Beitrag |
Gonozal_IX
Hält's aus hier
Beiträge: 5
|
Verfasst: 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:
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 Tino: Code- durch Delphi-Tags ersetzt
|
|
F4n4T!C
      
Beiträge: 25
|
Verfasst: 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 
Hält's aus hier
Beiträge: 5
|
Verfasst: Mo 03.12.07 12:35
F4n4T!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
|
Verfasst: Mo 03.12.07 12:45
Sollte eigentlich so funktionieren.
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 ) ); i := 0; while i<2 do i := i+1; end; end; |
|
|
jackle32
      
Beiträge: 183
Erhaltene Danke: 7
Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
|
Verfasst: 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 Neurologic 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
|
Verfasst: Mo 03.12.07 12:53
jackle32 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
      
Beiträge: 183
Erhaltene Danke: 7
Win7
Delphi XE5 Starter, RAD Studio XE7 Pro
|
Verfasst: 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
      
Beiträge: 66
WinXP Prof., Vista
Delphi6, Delphi 2009, Java(Eclipse), C++, Basic
|
Verfasst: 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
|
Verfasst: Mo 03.12.07 13:03
Magic 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
Gonozal_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 
Hält's aus hier
Beiträge: 5
|
Verfasst: 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:
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:
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 Tino: Code- durch Delphi-Tags ersetzt
|
|
Christian R.
Ehemaliges Mitglied
Erhaltene Danke: 1
|
Verfasst: Mo 03.12.07 13:53
Gonozal_IX hat folgendes geschrieben: | 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.
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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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 
Hält's aus hier
Beiträge: 5
|
Verfasst: Mo 03.12.07 14:19
jaenicke 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:
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..3] of 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
Quelltext
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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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  ): 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
Unit11.pas.34: j := 0; 0045AC93 33DB xor ebx,ebx
Unit11.pas.35: for i := 0 to 2 do 0045AC95 BA03000000 mov edx,$00000003 0045AC9A 8D45F4 lea eax,[ebp-$0c]
Unit11.pas.36: j := j + test[i]; 0045AC9D 0318 add ebx,[eax] 0045AC9F 83C004 add eax,$04
Unit11.pas.35: for i := 0 to 2 do 0045ACA2 4A dec edx 0045ACA3 75F8 jnz $0045ac9d | 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: 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..2] of 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 
Hält's aus hier
Beiträge: 5
|
Verfasst: 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
|
Verfasst: 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
      
Beiträge: 19315
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: 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
|
Verfasst: Mo 03.12.07 15:52
Beim Debuggen sollte man sowieso die Optimierung abschalten.
|
|
|