![]() |
Rückgabewert der Funktion undefiniert
Hallo Delphianer(innen)!
Ich weiß, ich habe schon öfter im Forum Themen zu folgender bekannter Fehlermeldung gehört: "Rückgabewert der Funktion FormX.Funktion könnte undefiniert sein". Aber ich komme echt nicht weiter - ich zerbreche mir über den paar Zeilen Code schon Wochen den Kopf:
Delphi-Quellcode:
Schonda soll prüfen, ob ein Element s:string (hier: eine Datei) in einer Listbox schon vorhanden ist.
//Dateien des gleichen Pfads schon vorhanden?
function TForm1.schonda(s:string):boolean; var i,a:integer; begin a:=listbox1.items.count; for i:=1 to a do if (s=listbox1.items[i-1]) then begin result:=true; break; end else result:=false; end; Ich ziehe Dateien per Drag'n'Drop hinein und es wäre ja sichtbar dumm, wenn zweimal der gleiche Dateiname in der Listbox vorhanden ist. Schonda prüft also bevor eine Datei der Listbox hinzugefügt wird ... Hoffe, ihr könnt mir helfen - RObert |
Re: Rückgabewert der Funktion undefiniert
Wenn die Schleife nicht durchlaufen wird, wird kein Result gesetzt. Denk mal darüber nach, was passiert, wenn 0 Elemente in der Listbox sind. :-)
Außerdem gab es doch bei Listbox die Funktion .IndexOf[]. Edit: Dann würde ich lieber eine while- oder repeat-Schleife nehmen, anstatt mit einem break zu arbeiten. Und das false kannst du ja schon ganz am Anfang setzen und nur noch bei einem Fund den Rückgabewert auf true ändern. |
Re: Rückgabewert der Funktion undefiniert
Zitat:
|
Re: Rückgabewert der Funktion undefiniert
Heißt doch nicht, das hier jedes mal auf .Count zugegriffen werden muss.
|
Re: Rückgabewert der Funktion undefiniert
Zitat:
Wobei man sich für sehr große Dateilisten eh nen besseren Such-Algo (ggf. auch nicht mit TStringList) überlegen könnte :) |
Re: Rückgabewert der Funktion undefiniert
wenn man es sich ganz einfach (und übersichtlich) machen will, könnte man die dateien
auch in ner eigenen StringList "mitspeichern" und dann halt über
Delphi-Quellcode:
duplikate ignorieren. bei sehr großen dateilisten ist das aber vll nicht unbedingt die optimalste variante
MyStringList.Duplicates := dupIgnore;
(wegen dem ständigen hin und her kopieren ums in der listbox anzuzeigen) bei ner handvoll einträgen aber sicher recht kompfortabel und ausreichend! |
Re: Rückgabewert der Funktion undefiniert
Hi!
@quendolineDD: << 1.) Wenn die Schleife nicht durchlaufen wird, wird kein Result gesetzt. 2.) Denk mal darüber nach, was passiert, wenn 0 Elemente in der Listbox sind. Smile 3.) Außerdem gab es doch bei Listbox die Funktion .IndexOf[]. Edit: 4.) Dann würde ich lieber eine while- oder repeat-Schleife nehmen, anstatt mit einem break zu arbeiten. 5.) Und das false kannst du ja schon ganz am Anfang setzen und nur noch bei einem Fund den Rückgabewert auf true ändern. >> Tut mir Leid, dass ich deinen Beitrag so zerpflücken und abändern muss, aber ich habe ansonsten keine Chance, darauf geregelt zu antworten ...: 1.) Warum sollte die Schleife nicht durchlaufen werden? Sie wir immer durchlaufen. (Die Funktion wird nicht nur einmal bei Drag'n'Drop ausgeführt, sondern für jede einzelne Datei).
Delphi-Quellcode:
2.) Was ist daran so schlimm, wenn 0 Elemente vorhanden sind? Dann durchläuft er die Schleife nicht. Und das ist ja nicht schlimm. Sind ja eh keine Elemente da ...
//Fügt Datei aus Listbox4 hinzu, wenn Schonda=false also Datei noch nicht da; prüft jede einzelne Datei mit jedem einzelnen Element
for r:=1 to (listbox1.items.count) do if schonda(listbox4.items[r-1])=false then listbox1.items.add(listbox4.items[r-1]); 3.) Ob ich nun
Delphi-Quellcode:
oder
(s=listbox1.items[i-1])
Delphi-Quellcode:
ist doch egal ...
(listbox1.items.indexof[...]=listbox1.items[i-1])
4.) Ist doch egal ob ich breake oder ob ich mit einer geregelten Bedingung eine andere Wiederholungsstruktur verlasse ... 5.) Das false brauche ich nicht zu setzen, da boolesche Variablen etc. nicht initialisert werden müssen; sie haben als Startwert immer false ... Mir geht es auch weniger darum, möglichst wenig Rechenaufwand oder so einzubringen oder Die Funktion mitb anderen Befehlen schöner aussehen zu lassen ... Ich sehe das "Loch" in meiner Funktion nicht. Wenn mein Result=undefiniert sein kann, dann muss es also einen Programmierpfad geben, indem Result nicht klar definiert wird, sich also der Startwert nicht ändert. Und das verstehe ich nicht. Durch mein If-Else sage ich doch genau, entweder so oder so. Ich sage doch in einer bestimmten Bedingung nicht nichts ... Versteht ihr mich?! Gruß - RObert |
Re: Rückgabewert der Funktion undefiniert
Wenn die obere Grenze der Schleife kleiner ist als die untere Grenze wird die Schleife nicht durchlaufen. Falls also keine Elemente in der Listbox sind (was theoretisch ja passieren könnte) wird die Schleife nicht durchlaufen und damit das if-Statement ebensowenig.
Also eher so:
Delphi-Quellcode:
function TForm1.schonda(s:string):boolean;
var i,a:integer; begin result:=false; a:=listbox1.items.count; for i:=1 to a do if (s=listbox1.items[i-1]) then begin result:=true; break; end end; |
Re: Rückgabewert der Funktion undefiniert
Wenn die Liste leer ist, dann ist a = 0. Bei a = 0 wird die Schleife nicht durchlaufen und somit auch Result nie ein Wert von Deinem Code zugewiesen. In dem Fall gibt Result den Wert zurück, mit dem Delphi die Variable initialisiert hat.
Das hier ein Wert zurückgegeben wird, den Delphi entschieden hat und nicht Dein Code, davor wirst Du gewarnt. Wie gesagt, Delphi weis nicht, ob die Liste nie leer sein kann. Delphi weis auch nicht, ob es OK ist, das Result = False bei leerer Liste. PS: Ist es überhaupt garantiert, das Boolean immer mit False initialisiert werden? |
Re: Rückgabewert der Funktion undefiniert
zu 3) ich glaub quendolineDD meinte, dass du dir die ganze funktion durch einen aufruf von indexof sparen könntest
Delphi-Quellcode:
vorhanden := Listbox1.Items.IndexOf(Filename) >= 0;
|
Re: Rückgabewert der Funktion undefiniert
@Satty: Es ist gar nicht sicher, dass Result überhaupt Speicherplatz zugewiesen wird. Es kann sein, dass am Ende einfach der Wert zurückgegeben wird, der zufällig in AL stand.
|
Re: Rückgabewert der Funktion undefiniert
Hey!
Habe das erstmal umgesetzt, was jfheins sagte ... Und auch das von Satty67 verstanden ... Das heißt, Delphi rechnet damit, dass die Liste leer sein kann? Narrja, es ist ja gut und auch logisch, dass bei leerer Liste keine Schleife durchlaufen wird, denn ich brauche ja nichts abgleichen oder nicht hinzufügen, wenn sie eh leer ist ... Ob Boolean immer auf false initialisiert wird - festlegen möchte ich mich nicht. Aber ich habe es überprüft bei meiner Funktion und er initialiserte mit false ... Außerdem ist es ja logisch: Eine Variable wird immer mit dem kleinsten Wert belegt (Integer=0) und false ist nun mal kleiner als true (denn 0<1). Daher bestimmt eben ... Aber obwohl ich nun meinen Quellcode geändert habe, geht es immer noch nicht. Die Fehlermeldung ist zwar weg, aber er fügt dennoch Dateien mehrmals hinzu, wenn ich z.B. Datei 1-15 im ersten Durchlauf Drage und Drope und dann eben Datei 8-11 wieder hineinmache, dann fügt er sie gnadenlos hinzu ohne zu merken, dass sie ja schon im ersten Durchlauf hinzugefügt wurden ... PS: Ich verstehe nats Beitrag nicht ... Besser gesagt den Quellcode??? In einer Wertzuweisung ein Vergleich - hä? Und meint er mit 'vorhanden' etwa 'schonda'? |
Re: Rückgabewert der Funktion undefiniert
Um meine Aussage zu verdeutlichen: Ich meine, das zum einen das von Satty67 festgestellte. Es gibt Fälle, in denen die Schleife nicht durchlaufen wird und der Rückgabewert der Funktion gänzlich ungesetzt ist und wie von Apollonius beschrieben ein undefinierter Wert aus dem Arbeitsspeicher gelesen wird.
Es wird nur False mit 0 definiert. True ist alles <> 0. Daher gibt es auch Unterschiede im BOOLEAN und dem von der WinAPI verwendeten BOOL (welches glaub ich LONGBOOL ist). |
Re: Rückgabewert der Funktion undefiniert
Habe ja schon geschrieben, egal wie boolean initialisiert wird, in meiner Funktion - habe ich getestet - wird False ausgegeben, wenn nichts definiert wird ...
Bitte nochmal auf meinen vorigen Beitrag eingehen ... |
Re: Rückgabewert der Funktion undefiniert
ja, das was ich oben geschrieben habe kannst du als ersatz für deine schonda funktion nehmen.
wenn du jetzt sowas wie
Delphi-Quellcode:
hast, dann
vorhanden := schonda(dateiname);
kannste das durch
Delphi-Quellcode:
ersetzen.
vorhanden := Listbox1.Items.IndexOf(dateiname) >= 0;
guck dir in der hilfe ma an, was indexof macht. und das mit den vergleichen in einer zuweisung: ein vergleich ergibt doch einen boolschen wert. diesen kannste natürlich auch einer boolschen variable zuweisen! |
Re: Rückgabewert der Funktion undefiniert
IndexOf in der hilfe bei was gucken ...?
TListItems oder wo oder was ....??? |
Re: Rückgabewert der Funktion undefiniert
Hi
TListbox.Items ist vom Typ TStrings. und TStrings hat eine Methode IndexOf..... Gruss |
Re: Rückgabewert der Funktion undefiniert
man wär auch hingekommen wenn man die hilfe zu TListbox aufgerufen hätte, da auf items geklickt hätte und dann halt auf indexof.
irgendwie logisch, oder? :lol: |
Re: Rückgabewert der Funktion undefiniert
Ich habs jetzt begriffen
Delphi-Quellcode:
aber es funktioniert immer noch nicht; keine Fehlermeldung aber er fügt gnadenlos hinzu ...
//Neue Dateien in Listbox1
for r:=1 to a do if listbox1.items.indexof(listbox4.items[r-1])=-1 then listbox1.items.add(listbox4.items[r-1]); Ich habe übrigens mal mit ner anderen Listbox geprüft; es ist immer -1 ... D.h. da geht wohl was nicht so, wie es soll ......... |
Re: Rückgabewert der Funktion undefiniert
poste ma n bisserl mehr quelltext!
|
Re: Rückgabewert der Funktion undefiniert
Sind die Einträge komplett identisch oder unterscheiden die sich durch Leerzeichen oder Groß-/Kleinschreibung?
|
Re: Rückgabewert der Funktion undefiniert
ie Einträge sind komplett identisch, wie aus meinen vorigen Beiträgen hervor gehen müsste: Ich sagte ja bereits, dass ich einmal Dateien per Drag'n'Drop hineinziehe und dass sie beim zweiten Reinziehen (sprich gleiche Dateien) nicht nochmal hinzugefügt werden ...
Die Dateien werden weiterverarbeitet, und da wäre es dämlich, sie mehrmals zu bearbeiten, weil sie inner Listbox mehrmals stehen ... Hier die komplette Drag'n'Drop-Routine ... Sicherlich auch von irgendwo hier geklaut ;-)
Delphi-Quellcode:
const DF_NUMBEROFFILES=$FFFFFFFF;
procedure TForm1.WMDROPFILES(var Msg: TMessage); var i,j,l,a,r,anzahl,size:Integer; Dateiname:PChar; Pfad,Pfadneu,s:string; begin inherited; Dateiname:=PChar(''); Pfad:=edit1.text; //Ermitteln des Pfades der neuen Dateien durch Einlesen der neuen Dateien //in Listbox4 anzahl:=DragQueryFile(Msg.WParam, DF_NUMBEROFFILES, Dateiname, 255); for i:=0 to (anzahl-1) do begin size:=DragQueryFile(Msg.WParam,i,nil,0)+1; Dateiname:=StrAlloc(size); DragQueryFile(Msg.WParam,i,Dateiname,size); Listbox4.Items.Add(StrPas(Dateiname)); StrDispose(Dateiname); end; DragFinish(Msg.WParam); //Herausfiltern des Pfades s:=listbox4.items[0]; l:=length(s); for j:=l downto 1 do begin if s[j]='\' then begin Pfadneu:=copy(s,1,j); Break; end; end; a:=listbox4.items.count; //Messagebox, wenn Listbox nicht leer und Pfade der neuen/alten Dateien ungleich if ((listbox1.items.count<>0) and (Pfad<>Pfadneu) and (Pfad<>'')) then if Application.MessageBox ('Sie können nur Dateien des gleichen Ordners nummerieren!'#13'Wenn Sie Dateien eines anderen Ordners in die Liste ziehen, werden die anderen Elemente entfernt.','Hinweis',MB_OKCANCEL +MB_ICONINFORMATION +MB_SETFOREGROUND)=mrok then listbox1.items.clear else a:=0; //Neue Dateien in Listbox1 for r:=1 to a do //if schonda(listbox4.items[r-1])=false then if listbox1.items.indexof(listbox4.items[r-1])=-1 then begin edit2.text:=inttostr(listbox1.items.indexof(listbox4.items[r-1])); listbox1.items.add(listbox4.items[r-1]); end; listbox4.items.clear; Dateinamenkurz(); Form1.ActiveControl:=listbox1; BitBtn1.enabled:=false; BitBtn2.enabled:=true; Button2.enabled:=true; BitBtn3.enabled:=false; BitBtn5.enabled:=true; Button6.enabled:=true; listbox2.items.clear; listbox3.items.clear; listbox1.itemindex:=0; SetLBHScrollbar(Listbox1); end; PS: Was macht inherited ... Ich verstehs immer noch nicht ... |
Re: Rückgabewert der Funktion undefiniert
Nun wurde ich aufgefordert, Quelltext zu geben und es antwortet keiner mehr ...
Keiner einen Rat? |
Re: Rückgabewert der Funktion undefiniert
Da ich nicht weiß worum es geht, da auch die Überschrift nicht zur geposteten Prozedur paßt ...
Zitat:
Also wenn z.B. mit "WMDROPFILES" eine gleichnamige Funktion in einer der Elternklasse überschrieben wurde, dann wird die alte Funktion aufgerufen. |
Re: Rückgabewert der Funktion undefiniert
Zitat:
also dein source macht bei mir genau das was er soll. es werden nur neue dateien hinzugefügt. was macht denn die funktion "Dateinamenkurz();", die hast du ja nicht mit gepostet. |
Re: Rückgabewert der Funktion undefiniert
Zitat:
___________________________________________ Für nat (und alle anderen natürlich auch):
Delphi-Quellcode:
procedure TForm1.dateinamenkurz();
var a,i,j,l:integer; Pfad,s:string; begin a:=listbox1.items.count; s:=listbox1.items[a-1]; l:=length(s); //Pfadlänge ermitteln mittels letztem Backslash for j:=l downto 1 do begin if s[j]='\' then begin Pfad:=copy(s,1,j); Break; end; end; //Pfad aus jeder Datei löschen, sodass nur noch Dateiname übrig bleibt for i:=1 to a do begin s:=listbox1.items[i-1]; if (pos(Pfad,s)<>0) then delete(s,1,j); listbox1.items[i-1]:=s; end; if (Pfad<>'') then edit1.text:=Pfad; end; |
Re: Rückgabewert der Funktion undefiniert
Zitat:
|
Re: Rückgabewert der Funktion undefiniert
Und man könnte auch ExtractFilePath und ExtractFileName verwenden, das ist nicht so umständlich :mrgreen:
|
Re: Rückgabewert der Funktion undefiniert
Delphi-Quellcode:
for i:=0 to (anzahl-1) do
begin size:=DragQueryFile(Msg.WParam,i,nil,0)+1; Dateiname:=StrAlloc(size); DragQueryFile(Msg.WParam,i,Dateiname,size); Listbox4.Items.Add(StrPas(Dateiname)); //hier fügst du mit pfad ein StrDispose(Dateiname); end;
Delphi-Quellcode:
dein problem ist, dass du die dateinamen ohne pfad speicherst,
//Neue Dateien in Listbox1
for r:=1 to a do //if schonda(listbox4.items[r-1])=false then if listbox1.items.indexof(listbox4.items[r-1])=-1 then //hier wird "datei mit pfad" mit "datei ohne pfad" verglichen begin edit2.text:=inttostr(listbox1.items.indexof(listbox4.items[r-1])); listbox1.items.add(listbox4.items[r-1]); vergleichst die (neuen) gedroppten dateien aber mit pfad mit den alten (vorher gedroppten) dateien von denen du den pfad abgeschnitten hast mit deiner procedure TForm1.dateinamenkurz(); methode. |
Re: Rückgabewert der Funktion undefiniert
Gut, Danke nat!
Jetzt funktioniert es. Ich habe die Dateinamen in Listbox4 schon gekürzt, sodass sie ganz ohne Pfad in die Listbox1 kommen. Es geht jetzt! Danke! -- Somit ist das Problem gelöst und kann daher beendet werden. -- |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:40 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 by Thomas Breitkreuz