Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Komplexe Datentypen als Rückgabewert einer Funktion (https://www.delphipraxis.net/58890-komplexe-datentypen-als-rueckgabewert-einer-funktion.html)

inriz 14. Dez 2005 10:40


Komplexe Datentypen als Rückgabewert einer Funktion
 
Hallo,

folgendes Sachverhalt wurde mir zugetragen um meinen Code zu verbessern.
Ich habe eine Funktion namens GetTokenList. Diese Funktion nimmt einen String entgegen (separiert durch ':'), splittet diesen
anhand des Separators auf und schreibt alles in ein Objekt vom Typ TStringList.
Diese TStringList wird in der Funktion allokiert und die Referenz dieses Objektes wird zurückgegeben.
Delphi-Quellcode:
function TfmAppPanel.GetTokenList(sCommand, sSeparator : string) : TStringList;
var
  sTmp : string;
  sCurrentToken : string;
  iPos : Integer;
  iRest : Integer;
  TokenList : TStringList;
begin
  Result := nil;
  sTmp := sCommand;
  TokenList := TStringList.Create;

  iPos := Pos(sSeparator, sTmp);
  if iPos > 0 then
  begin
    repeat
      iRest := Length(sTmp) - iPos;
      sCurrentToken := LeftStr(sTmp, iPos - 1); // hier können laufzeitfehler entstehen ...
      TokenList.Add(sCurrentToken);
      sTmp := RightStr(sTmp, iRest);
      iPos := Pos(sSeparator, sTmp);
    until not (iPos > 0);

    if Length(sTmp) > 0 then
    begin
      TokenList.Add(sTmp);
    end;
    Result := TokenList;
  end;
end;
Nun wurde mir gesagt, gib anstatt der Referenz, TokenList.Text zurück. Der String, der sich in TokenList.Text befindet kann einer anderen Liste zugewiesen werden(AList.Text := GetTokenList(...)) und man kann normal mit der Liste (Alist) wie gewohnt weiterarbeiten. Meine Frage ist, macht diese Änderung Sinn, wenn ja? Warum?
Mein Kenntnisstand sagt, Allokation ist mit viel Rechenleistung behaftet und bei der mir zugetragenen Lösung muss ich noch eine weitere TStringList allokieren, was für mich keinen Sinn ergibt, da es ja Pointer gibt. Wie sieht ihr das? Ist die Lösung berechtigt? Gibt es andere Lösungen?

Gruß inriz

shmia 14. Dez 2005 11:01

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Sinnvoll ist es, die Liste vom Aufrufer deiner Funktion bereitstellen zu lassen:
Delphi-Quellcode:
procedure FillTokenList(const sCommand, sSeparator : string; liste:TStrings);
begin
   Assert(Assigned(liste)); // zur Sicherheit
   liste.clear;
   ...
end;
Damit wird die Funktion zu einer Procedure. Du kannst auch TStrings-Objekte übergeben, die kein TStringList sind. z.B.:
Delphi-Quellcode:
FillTokenList('EXEC', ',', Memo1.Lines);
Der vorgeschlagene Umweg über "TokenList.Text" ist keinesfalls zu empfehlen.

Der_Unwissende 14. Dez 2005 11:03

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Hi,
sorry aber ich muss mal ganz kurz eine andere Frage stellen, warum machst du es eigentlich so umständlich?

Delphi-Quellcode:
function TfmAppPanel.GetTokenList(sCommand, sSeparator : string) : TStringList;
begin
  Result := TStringList.Create;
  Result.Delimiter := Seperator;
  Result.DelimitedText := sCommand;
end;
Das sollte eigentlich genau das gleiche tun und mit Result.DelimitedText bekommst du auch den original Text zurück.

Ansonsten ist es natürlich komplett von dem was man machen möchte abhängig, wie ein StringTokenizer am sinnvollsten aufgebaut werden sollte. Ich persönlich sehe allerdings wenig Sinn darin den String ungetrennt zurück zu geben (wie es ja nach Änderungswunsch sein würde?).

Gruß Der Unwissende

RavenIV 14. Dez 2005 11:09

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Zitat:

Zitat von Der_Unwissende
Delphi-Quellcode:
function TfmAppPanel.GetTokenList(sCommand, sSeparator : string) : TStringList;
begin
  Result := TStringList.Create;
  Result.Delimiter := Seperator;
  Result.DelimitedText := sCommand;
end;

hiermit erzeugst du aber ein Speicherleck, weil die Stringlist nirgends zerstört (Free) wird.

Der_Unwissende 14. Dez 2005 11:21

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Zitat:

Zitat von RavenIV
Zitat:

Zitat von Der_Unwissende
Delphi-Quellcode:
function TfmAppPanel.GetTokenList(sCommand, sSeparator : string) : TStringList;
begin
  Result := TStringList.Create;
  Result.Delimiter := Seperator;
  Result.DelimitedText := sCommand;
end;

hiermit erzeugst du aber ein Speicherleck, weil die Stringlist nirgends zerstört (Free) wird.

Nun ja, die StringList ist Rückgabewert einer Funktion, der jenige der sie empfängt muss sich also darum kümmern, dass sie wieder frei gegeben wird. Das geht aber logisch aus einem solchen Typen als Rückgabewert hervor (gut, ist vielleicht nicht der sauberste/schönste Weg). Aber würde ich sie schon freigeben wäre die Funktion sinnfrei.

Kannst du natürlich auch als procedure machen und dann halt

Delphi-Quellcode:
procedure TfmAppPanel.GetTokenList(sCommand, sSeparator : string; result : TStringList) ;
begin
  Result.clear;
  Result.Delimiter := Seperator;
  Result.DelimitedText := sCommand;
end;
Sorry für den wie immer unkreativen Namen des Parameters, hatte nur keine Lust den Quellcode zu weit zu ändern (zwei weitere Umbenennungen sind viel :mrgreen:)

Gruß

inriz 14. Dez 2005 11:56

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Delphi-Quellcode:
sCommand := edtCommand.Text;
if not Length(sCommand) > 0 then
  exit;
AStringList := TStringList.Create;
if not Assigned(AStringList) then
  exit;

AStringList.Delimiter := ':';
AStringList.Text := sCommand;

lblShowListElement.Caption := AStringList[0];
lblDelimitedText.Caption := AStringList.DelimitedText;
lblDelimiter.Caption := AStringList.Delimiter;

AStringList.Free;
Diese Lösung habe ich jetzt implementiert und getestet, führt aber nicht zu dem gewünschtem Ergebnis.
Soweit ich die in der Hilfe angebotene Beschreibeung zu TStringList verstanden habe,
beschreibt Delimiter ein Zeichen, welches genutzt wird, um Text, der aus zusammen gesetzten TStrings besteht, mit Hilfe dieses Delimiters zu "einem" String zu formen.

Meine Aussage bzw. der Tatbestand meiner Ausführungen im obigen Beitrag scheinen mit diesem Beitrag widersprüchlich zu sein,
da dort der Text "einer" StringListe, dem Text einer "anderen" StringListe zugewiesen wird und das Arbeiten
mit dieser "anderen" StringListe einwandfrei funktioniert, sprich Zugriffe dieser Art AStringList[0] auch funktionieren.

Gruß inriz

Der_Unwissende 14. Dez 2005 12:07

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Zitat:

Zitat von inriz
Ich habe eine Funktion namens GetTokenList. Diese Funktion nimmt einen String entgegen (separiert durch ':'), splittet diesen
anhand des Separators auf und schreibt alles in ein Objekt vom Typ TStringList.
Diese TStringList wird in der Funktion allokiert und die Referenz dieses Objektes wird zurückgegeben.

Genau das würde
Delphi-Quellcode:
function TfmAppPanel.GetTokenList(sCommand, sSeparator : string) : TStringList;
begin
  Result := TStringList.Create;
  Result.Delimiter := Seperator;
  Result.DelimitedText := sCommand;
end;
machen.
Beispiel :

Delphi-Quellcode:
var s : String;
    tokenList : TStringList;
begin
  s := 'a:b:c:Irgendetwas:...';
  tokenList := GetTokenList(s, ':');
  // tokenList.Count = 5,
  // tokenList.Strings[0] = 'a'
  // tokenList.Strings[1] = 'b'
  // tokenList.Strings[2] = 'c'
  // tokenList.Strings[3] = 'Irgendetwas'
  // tokenList.Strings[4] = '...'
end;
Oder hab ich dich falsch verstanden? Werde mir mal gleich deinen Code anschauen, moment

Ja, ist genau das was deine Funktion auch macht nur schon gekapselt. By the way, eine TStringList arbeitet auf den DelimitedText wie ein StringTokenizer (wenn ein Delimitter vorhanden ist), nich auf Text. Wenn du also wie gepostet vorgehst, stehen in der StringList wie bei deinem Ergebnis die einzelnen Token drin

[Edit]Code angesehen und letzten Absatz eingefügt[/Edit]

inriz 14. Dez 2005 12:25

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Richtig:
Delphi-Quellcode:
AStringList.Delimiter := ':';
AStringList.DelimitedText:= sCommand;
Falsch:
Delphi-Quellcode:
AStringList.Delimiter := ':';
AStringList.Text:= sCommand;
War ein übersehener Fehler meinerseits. Danke für die Hilfe.

Gruß inriz

Der_Unwissende 14. Dez 2005 12:35

Re: Komplexe Datentypen als Rückgabewert einer Funktion
 
Hauptsache läuft :wink:

Der Unwissende


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:52 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