Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Rückgabewert der Funktion undefiniert (https://www.delphipraxis.net/135200-rueckgabewert-der-funktion-undefiniert.html)

trebor90 6. Jun 2009 14:18


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:
//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;
Schonda soll prüfen, ob ein Element s:string (hier: eine Datei) in einer Listbox schon vorhanden ist.
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

quendolineDD 6. Jun 2009 14:21

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.

mirage228 6. Jun 2009 14:26

Re: Rückgabewert der Funktion undefiniert
 
Zitat:

Zitat von quendolineDD
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.

Bei einer for-Schleife wird auf Items.Count aber nur einmal zugegriffen und nicht bei jeder Iteration (falls das Wichtig sein sollte...).

quendolineDD 6. Jun 2009 14:29

Re: Rückgabewert der Funktion undefiniert
 
Heißt doch nicht, das hier jedes mal auf .Count zugegriffen werden muss.

mirage228 6. Jun 2009 14:33

Re: Rückgabewert der Funktion undefiniert
 
Zitat:

Zitat von quendolineDD
Heißt doch nicht, das hier jedes mal auf .Count zugegriffen werden muss.

Hm, dasn Argument :mrgreen:
Wobei man sich für sehr große Dateilisten eh nen besseren Such-Algo (ggf. auch nicht mit TStringList) überlegen könnte :)

nat 6. Jun 2009 14:54

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:
MyStringList.Duplicates := dupIgnore;
duplikate ignorieren. bei sehr großen dateilisten ist das aber vll nicht unbedingt die optimalste variante
(wegen dem ständigen hin und her kopieren ums in der listbox anzuzeigen) bei ner handvoll einträgen aber sicher
recht kompfortabel und ausreichend!

trebor90 6. Jun 2009 15:50

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:
//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]);
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 ...
3.) Ob ich nun
Delphi-Quellcode:
(s=listbox1.items[i-1])
oder
Delphi-Quellcode:
(listbox1.items.indexof[...]=listbox1.items[i-1])
ist doch egal ...
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

jfheins 6. Jun 2009 15:55

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;

Satty67 6. Jun 2009 16:05

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?

nat 6. Jun 2009 16:12

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;

Apollonius 6. Jun 2009 16:16

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.

trebor90 6. Jun 2009 16:20

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'?

quendolineDD 6. Jun 2009 16:25

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).

trebor90 6. Jun 2009 16:32

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 ...

nat 6. Jun 2009 16:38

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:
vorhanden := schonda(dateiname);
hast, dann
kannste das durch
Delphi-Quellcode:
vorhanden := Listbox1.Items.IndexOf(dateiname) >= 0;
ersetzen.
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!

trebor90 6. Jun 2009 16:48

Re: Rückgabewert der Funktion undefiniert
 
IndexOf in der hilfe bei was gucken ...?
TListItems oder wo oder was ....???

thkerkmann 6. Jun 2009 17:34

Re: Rückgabewert der Funktion undefiniert
 
Hi

TListbox.Items ist vom Typ TStrings.

und TStrings hat eine Methode IndexOf.....

Gruss

nat 6. Jun 2009 18:02

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:

trebor90 6. Jun 2009 22:10

Re: Rückgabewert der Funktion undefiniert
 
Ich habs jetzt begriffen

Delphi-Quellcode:
//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]);
aber es funktioniert immer noch nicht; keine Fehlermeldung aber er fügt gnadenlos hinzu ...

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 .........

nat 6. Jun 2009 23:17

Re: Rückgabewert der Funktion undefiniert
 
poste ma n bisserl mehr quelltext!

mkinzler 6. Jun 2009 23:18

Re: Rückgabewert der Funktion undefiniert
 
Sind die Einträge komplett identisch oder unterscheiden die sich durch Leerzeichen oder Groß-/Kleinschreibung?

trebor90 7. Jun 2009 00:10

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 ...

trebor90 11. Jun 2009 10:09

Re: Rückgabewert der Funktion undefiniert
 
Nun wurde ich aufgefordert, Quelltext zu geben und es antwortet keiner mehr ...
Keiner einen Rat?

himitsu 11. Jun 2009 10:18

Re: Rückgabewert der Funktion undefiniert
 
Da ich nicht weiß worum es geht, da auch die Überschrift nicht zur geposteten Prozedur paßt ...



Zitat:

Zitat von trebor90
PS: Was macht inherited ... Ich verstehs immer noch nicht ...

dieses ruft die gleiche Funktion in einer übergeordneten Klasse auf

Also wenn z.B. mit "WMDROPFILES" eine gleichnamige Funktion in einer der Elternklasse überschrieben wurde, dann wird die alte Funktion aufgerufen.

nat 11. Jun 2009 12:15

Re: Rückgabewert der Funktion undefiniert
 
Zitat:

Zitat von trebor90
Nun wurde ich aufgefordert, Quelltext zu geben und es antwortet keiner mehr ...
Keiner einen Rat?

sorry, hatte den thread hier total vergessen :oops:

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.

trebor90 12. Jun 2009 23:14

Re: Rückgabewert der Funktion undefiniert
 
Zitat:

Zitat von himitsu
Da ich nicht weiß worum es geht, da auch die Überschrift nicht zur geposteten Prozedur paßt ...

Dann müsstest du einfach mal den gesamten Gesprächsfaden von vorn beginnend lesen, denn da (auf Seite 1) ging es anfangs um einen undefinierten Rückgabewert ...
___________________________________________

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;

quendolineDD 13. Jun 2009 00:05

Re: Rückgabewert der Funktion undefiniert
 
Zitat:

Dann müsstest du einfach mal den gesamten Gesprächsfaden von vorn beginnend lesen, denn da (auf Seite 1) ging es anfangs um einen undefinierten Rückgabewert ...
Um die Funktion der Suche weiterhin zu gewährleisten und andere schnell an passende Ergebnisse kommen wäre es doch passend ein neues Thema zu starten, mit der neuen Frage/Thematik.

DeddyH 13. Jun 2009 00:43

Re: Rückgabewert der Funktion undefiniert
 
Und man könnte auch ExtractFilePath und ExtractFileName verwenden, das ist nicht so umständlich :mrgreen:

nat 13. Jun 2009 15:45

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:
//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]);
dein problem ist, dass du die dateinamen ohne pfad speicherst,
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.

trebor90 16. Jun 2009 13:01

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