![]() |
Wieder ein Variablen Problem - komme nicht weiter.
Hallo, muss erst mal sagen, dass bis Gestern nie Probleme oder Fehler mit Variablen hatte, aber seit Gestern schon das zweite und zwar:
Habe bis jetzt diesen Code gehabt:
Delphi-Quellcode:
und hab diesen etwas auf diese Version geändert, aber der spinnt jetzt auf ein mal und ich bekomme eine Warnung "[Warnung] MAIN.pas(134): Variable 'cache' ist möglicherweise nicht initialisiert worden" Weiß nicht wo der Fehler liegt.
function RundeAufStelle(zahl: double; stellen: integer): double;
var multi: double; begin multi:=IntPower(10, stellen); zahl:=round(zahl*multi); result:=zahl/multi; end; procedure TForm1.Note; var note: Real; begin if (FiCountCorrect=0) and (jkeins=1) and (jkzwei=1) then begin note:=7; end else if (FiCountCorrect=0) and (jkeins=1) then begin note:=65/10; end else if (FiCountCorrect=0) and (jkzwei=1) then begin note:=65/10; end else if (FiCountCorrect=0) then begin note:=6; end else if (jkeins=1) then begin note:=StrToFloat(Label3.Caption); note:=note+1/2; end else if (jkzwei=1) then begin note:=StrToFloat(Label3.Caption); note:=note+1/2; end else begin note:=StrToFloat(Label3.Caption); note:=note-5/15; end; Label3.Caption:=FloatToStr(note); Label7.Caption:=FloatToStr(RundeAufStelle(StrToFloat(Label3.Caption), 1)); end;
Delphi-Quellcode:
function RundeAufStelle(zahl: double; stellen: integer): double;
var multi: double; begin multi:=IntPower(10, stellen); zahl:=round(zahl*multi); result:=zahl/multi; end; procedure TForm1.Note; var note, cache: Real; begin if (FiCountCorrect=0) and (jkeins=1) and (jkzwei=1) then begin note:=7; end else if (FiCountCorrect=0) and (jkeins=1) then begin note:=65/10; end else if (FiCountCorrect=0) and (jkzwei=1) then begin note:=65/10; end else if (FiCountCorrect=0) then begin note:=6; end else if (jkeins=1) then begin note:=cache; note:=note+1/2; end else if (jkzwei=1) then begin note:=cache; note:=note+1/2; end else begin note:=cache; note:=note-5/15; end; cache:=note; Label7.Caption:=FloatToStr(RundeAufStelle(cache, 1)); end; |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Sagt doch die Fehlermeldung, sie kann einen nicht definierten Wert annehmen.
Du gibst sie am Ende aus
Delphi-Quellcode:
Aber welchen Wert hat sie, wenn schon die erste if-Bedingung nicht zutrifft?
Label7.Caption:=FloatToStr(RundeAufStelle(cache, 1));
Und du solltest dringend dein Einrückungsstil überdenken und zumindest bei Postings hier im Forum dich ungefähr an den Borlandstil halten. |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Aber wenn ich die Variable cache durch Labe3.Caption ersetzte funktionier alles bestens. Ich verstehe die Logik nicht, hab ja nix verändert, nur label durch Variable ersetzt.
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Die Caption deines Labels hat einen definierten Anfangswert.
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Luckie kannst du mir vielleicht wenigstens nen Tipp geben wie ich den Code richtig schreiben soll. :gruebel:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Und wie kannst du da erkennen, welches end zu welchem begin gehört?
Was ist besser lesbar? Deins:
Delphi-Quellcode:
Oder meins:
procedure TForm1.Note;
var note, cache: Real; begin if (FiCountCorrect=0) and (jkeins=1) and (jkzwei=1) then begin note:=7; end else if (FiCountCorrect=0) and (jkeins=1) then begin note:=65/10; end else if (FiCountCorrect=0) and (jkzwei=1) then begin note:=65/10; end else if (FiCountCorrect=0) then begin note:=6; end else if (jkeins=1) then begin note:=cache; note:=note+1/2; end else if (jkzwei=1) then begin note:=cache; note:=note+1/2; end else begin note:=cache; note:=note-5/15; end; cache:=note; Label7.Caption:=FloatToStr(RundeAufStelle(cache, 1)); end;
Delphi-Quellcode:
Und dann sieht man auf den ersten Blick den Grund der Warnung.
procedure TForm1.Note;
var note, cache : Real; begin if (FiCountCorrect = 0) and (jkeins = 1) and (jkzwei = 1) then begin note := 7; end else if (FiCountCorrect = 0) and (jkeins = 1) then begin note := 65 / 10; end else if (FiCountCorrect = 0) and (jkzwei = 1) then begin note := 65 / 10; end else if (FiCountCorrect = 0) then begin note := 6; end else if (jkeins = 1) then begin note := cache; note := note + 1 / 2; end else if (jkzwei = 1) then begin note := cache; note := note + 1 / 2; end else begin note := cache; note := note - 5 / 15; end; cache := note; Label7.Caption := FloatToStr(RundeAufStelle(cache, 1)); end; |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Ich würde "cache" als Übergabeparameter definieren, dann kann m.E. nicht viel schiefgehen.
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Ich hab mich schon an meine bzw. staatliche (ist wirklich so, zu mindest in meiner Schule) Schreibweise gewöhnt, aber danke für die Muster. :thumb:
Ich komme mir schon dumm vor, aber sehe nix. Also die vierte Bedingung wird am Anfang immer erfüllt - note:=6; danach wird nach unten gesprungen und
Delphi-Quellcode:
ausgeführt, somit ist die Variable cache gefüllt. Als nächste wird die letzte Anweisung immer ausgeführt, dabei sind doch alle zwei Variablen schon gefühlt. :wall:
cache:=note;
Label7.Caption:=FloatToStr(RundeAufStelle(cache, 1)); |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Aber das weiß ja der Compiler nicht, denn woher soll er wissen, dass FiCountCorrect immer null ist. Da stellt sich mir die Frage, warum nimmst du es als Bedingung auf, wenn es doch sowieso immer null?
Und was das else angeht:
Delphi-Quellcode:
cache ist undefiniert und es wird auch nicht definierter, wenn du es hin und her schiebst. Denn dann machst du:
else
begin note := cache; note := note - 5 / 15; end;
Delphi-Quellcode:
cache := note;
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
FiCountCorrect ist eine globale Variable und ist beim öffnen des Programms gleich Null. Somit wird die vierte Bedienung erfüllt, note auf 6 gesetzt und in der vorletzten Zeile wird cache auf 6 gesetzt. Wenn die Procedur das nächste mal ausgeführt wird ist FiCountCorrect=1 und die allerletzte Anweisung ist dran, und sie muss eigentlich funken, da beide Variablen schon gefüllt sind.
Oder spinne ich schon? :wall: |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Delphi-Quellcode:
procedure TForm1.Note(cache: real); //so muss etwas übergeben wreden, cache ist also initialisiert
var note: Real; |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Warum ist cache dann initialisiert? Davon mal abgesehen, würde das Alex wohl komplett aus der bahn werfen, wenn er seine ganzen Code jetzt noch umbauen sollte.
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
Woher sind die denn bitte gefüllt? Vom vorherigen Aufruf? (siehe auch #10 von Luckie ...) |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Hallo,
Zitat:
Der Compiler weist ja auch "nur" darauf hin, dass cache eventuell nicht initialisiert ist, er weist darauf hin, dass es Situationen geben kann, in denen cache nicht initialisiert ist. Bei den von Dir verwendeten (vermuteten) Werten ist cache halt initialisiert (Zufall?). Bau doch am Anfang einfach direkt hinter dem ersten begin
Delphi-Quellcode:
ein.
cache := StrToFloat(Label3.Caption);
Zitat:
Stephan |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
Zitat:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Hallo,
Zitat:
Er betrachtet die Prozudur losgelöst vom "Rest der Welt". Für ihn ist innerhalb der Prozedur nicht erkennbar, das cache immer und zu jedem Zeitpunkt einen Wert hat und er verlässt sich nicht darauf, dass eine Prozedur immer nur so aufgerufen wird, dass jede Variabel immer einen Wert hat. Wenn er immer und überall überprüfen müsste, dass jede Variabel zu jeder Zeit, zu jeder Bedingung immer über gültige Werte verfügt, so müsste er zur Compilezeit das Programm mit sämtlichen möglichen Kombinationen von Werten... durchrechnen. Der Compiler, der das kann, der weiß auch, das die Antwort auf alle Fragen 42 ist :wink: Zitat:
Stephan |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Aber als Übergabeparameter ist sie laut Luckie ja auch nicht initialisiert :zwinker:. Ich frag mich nur, wozu es die Dinger dann überhaupt gibt.
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Zitat:
Stephan |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Ok danke dir. Muss mir mal heute alles über Proceduren durchlesen. :roll:
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Delphi-Quellcode:
Wo ist sie jetzt initialisiert?
procedure foo(c: Real);
begin // tu was end; // ...; procedure bar; var cache: Real; begin foo(cache); end; |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Davon war ja nicht die Rede. Das Spiel kannst Du natürlich endlos treiben.
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Hi!
Zuerst mal haben wir hier wohl das Mißverständnis, daß eine lokale Variable beim nächsten Prozeduraufruf noch ihren alten Wert habe - das mag bei anderen Programmiersprachen so sein, bei Delphi ist das nicht der Fall. Aufgrund des unter Windows ereignisgesteuerten Programmablaufs kann man ja auch nicht vorhersagen, in welcher Reihenfolge was aufgerufen wird - Tastatur- Maus- und Fensterereignisse passieren nun mal unvorhersehbar und rufen (sofern vom Programmierer da etwas geschrieben wurde) ihre Ereignisverarbeitungen auf. Wenn dann lokale Variablen als Zwischenspeicher verwendet werden könnten, kämen die merkwürdigsten Ergebnisse heraus. Bei Verwendung globaler Variablen kann das auch unter Delphi passieren. Leider hat der Fragesteller nicht die Zeile genannt, in der der Fehler gemeldet wird - die letzte Zeile dürfte es nicht sein. Hier mal Luckies Umformung des Codes mit meinen Anmerkungen, wo der Compiler warnen sollte:
Delphi-Quellcode:
Entweder cache als globale Variable im Formular haben oder als VAR-Parameter übergeben - dann natürlich vor dem ersten Aufruf der Prozedur das Initialisieren nicht vergessen.
procedure TForm1.Note;
var note, cache : Real; begin if (FiCountCorrect = 0) and (jkeins = 1) and (jkzwei = 1) then begin note := 7; end else if (FiCountCorrect = 0) and (jkeins = 1) then begin note := 65 / 10; end else if (FiCountCorrect = 0) and (jkzwei = 1) then begin note := 65 / 10; end else if (FiCountCorrect = 0) then begin note := 6; end else if (jkeins = 1) then begin note := cache; //==> cache möglicherweise nicht initialisiert note := note + 1 / 2; end else if (jkzwei = 1) then begin note := cache; //==> cache möglicherweise nicht initialisiert note := note + 1 / 2; end else begin note := cache; //==> cache möglicherweise nicht initialisiert note := note - 5 / 15; end; cache := note; Label7.Caption := FloatToStr(RundeAufStelle(cache, 1)); end; Dabei könnte man dann auch gleich die übrigen globalen Werte per Parameter übergeben:
Delphi-Quellcode:
Gruß
procedure TForm1.Note (const FiCountCorrect, jkeins, jkzwei: integer; var cache: real);
var note: Real; begin if (FiCountCorrect = 0) and (jkeins = 1) and (jkzwei = 1) then begin note := 7; end else if (FiCountCorrect = 0) and (jkeins = 1) then begin note := 65 / 10; end else if (FiCountCorrect = 0) and (jkzwei = 1) then begin note := 65 / 10; end else if (FiCountCorrect = 0) then begin note := 6; end else if (jkeins = 1) then begin note := cache; note := note + 1 / 2; end else if (jkzwei = 1) then begin note := cache; note := note + 1 / 2; end else begin note := cache; note := note - 5 / 15; end; cache := note; Label7.Caption := FloatToStr(RundeAufStelle(cache, 1)); end; Eos-PVU |
Re: Wieder ein Variablen Problem - komme nicht weiter.
Delphi-Quellcode:
Aber FiCountCorrect, jkeins, jkzwei sind doch nicht constant oder wie meinst du das?
procedure TForm1.Note (const FiCountCorrect, jkeins, jkzwei: integer; var cache: real);
|
Re: Wieder ein Variablen Problem - komme nicht weiter.
Hi!
Zitat:
Bei
Delphi-Quellcode:
wird die komplette Variable "bar" auf den Stack gepackt. Änderungen an "bar" sind innerhalb der Prozedur möglich, wirken aber nur auf die lokale Kopie. Beim Aufruf von "foo" können auch Konstanten (const-Deklarierte Werte) und Literale (Werte im Quelltext wie 1 oder 'foobar') übergeben werden.
procedure foo (bar: tbar);
Braucht bei komplexen Typen, z.B. Records, viel Stackspeicher. Bei
Delphi-Quellcode:
wird eine Referenz (Pointer) auf die Variable übergeben. Änderungen von "bar" innerhalb der Prozedur verändern die beim Aufruf angegebene Variable. Die Übergabe von Konstanten und Literalen ist natürlich nicht möglich.
procedure foo (var bar: tbar);
Braucht nur einen Pointer auf dem Stack. Bei
Delphi-Quellcode:
wird ebenfalls eine Referenz (Pointer) auf die Variable übergeben. Änderungen von "bar" innerhalb der Prozedur werden vom Compiler verhindert. Die Übergabe von Konstanten und Literalen ist möglich.
procedure foo (const bar: tbar);
Braucht nur einen Pointer auf dem Stack und spart deshalb bei komplexen Typen gegenüber der ersten Variante viel Speicherplatz. Bei Integer besteht kein Unterschied. Werte, die in einer Prozedur/Funktion nicht geändert werden (das ist bei Deinen Werten FiCountCorrect, jkeins, jkzwei der Fall) übergebe ich immer als const - eine versehentliche Zuweisung läßt sich dann gar nicht compilieren. das "const" könnte hier auch weggelassen werden. Gruß Eos-PVU |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:45 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz