Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Probleme mit eigener Klasse (https://www.delphipraxis.net/3211-probleme-mit-eigener-klasse.html)

Luckie 28. Feb 2003 20:20


Probleme mit eigener Klasse
 
Ich habe mir eine eigene Klasse entworfen um einen String der durch Separatoren getrennt ist in einzelne Strings zu zerlegen.
Delphi-Quellcode:
type TSplitString = class
 private
   FString2Split : String;
   FSepChar     : Char;
   FStrings     : TSplitStrArray;
   FStringsCount : Integer;
   FSepPos      : array of Integer;
   procedure SetSplitString(SplitStr: String);
   procedure SetSepChar(sep: Char);
   procedure SetSepPos;
   procedure SplitString;
 public
   constructor create(SplitStr: String; sep: Char);
   property String2Split: String read FString2Split write SetSplitString;
   property SepChar: Char read FSepChar write SetSepChar;
   function StringsCount: Integer;
   property SplitStringEx: TSplitStrArray read FStrings write SplitString; { hier kommt die Meldung: "Inkompatible Typen" }
end;

constructor TSplitString.create(SplitStr: String; sep: Char);
var
  i : Integer;
begin
  FStringsCount := 0;
  SetSplitString(SplitStr);
  SetSepChar(sep);
  if SplitStr[length(SplitStr)] <> sep then
    SplitStr := SplitStr+sep;
  for i := 1 to length(SplitStr)-1 do
  begin
    if SplitStr[i] = sep then Inc(FStringsCount);
  end;
  SetSepPos;
end;

procedure TSplitString.SetSepPos;
var
  i, j : Integer;
begin
  j := 0;
  setlength(FSepPos, FStringsCount+1);
  FSepPos[0] := 0;
  for i := 1 to length(FString2Split)-1 do
  begin
    if FString2Split[i] = FSepChar then
    begin
      FSepPos[j+1] := i;
      Inc(j);
    end;
  end;
end;

procedure TSplitString.SetSplitString(SplitStr: String);
begin
  if SplitStr = '' then
    Messagebox(0, 'Die Zeichenfolge ist leer.', 'Hinweis - TSplitString', MB_ICONINFORMATION);
  FString2Split := SplitStr;
end;

procedure TSplitString.SetSepChar(sep: Char);
begin
  if sep = '' then
    Messagebox(0, 'Das Trennzeichen ist leer.', 'Hinweis - TSpliString', MB_ICONINFORMATION);
  FSepChar := sep;
end;

function TSplitString.StringsCount: Integer;
begin
  result := FStringsCount;
end;

procedure TSplitString.SplitString;
var
  i  : Integer;
begin
  setlength(FStrings, FStringsCount);
  for i := 0 to FStringsCount-1 do
  begin
    FStrings[i] := copy(FString2Split, FSepPos[i], FsepPos[i+1]-FSepPos[i]);
  end;
end;
An der besagten Stelle kommt eben diese Fehlermeldung.
Delphi-Quellcode:
property SplitStringEx: TSplitStrArray read FStrings write SplitString;
Soll zum einen das Array mit den aufgeteilten Strings zurückgeben und zum anderen es füllen. Aber irgendwie mache ich da was falsch.
Verbesserungsvorschläge und Vereinfachungen der Klasse sind auch herzlich willkommen.

Snoop007 28. Feb 2003 20:32

hi,
Delphi-Quellcode:
   
property String2Split: String read FString2Split write SetSplitString;
   property SepChar: Char read FSepChar write SetSepChar;
   function StringsCount: Integer;
   property SplitStringEx: TSplitStrArray read FStrings write SplitString; { hier kommt die Meldung: "Inkompatible Typen" }
mach mal
Delphi-Quellcode:
function StringsCount: Integer;
   property String2Split: String read FString2Split write SetSplitString;
   property SepChar: Char read FSepChar write SetSepChar;
   property SplitStringEx: TSplitStrArray read FStrings write SplitString; { hier kommt die Meldung: "Inkompatible Typen" }

Luckie 28. Feb 2003 20:37

Öhm, was hast du jetzt gemacht außer die Reihenfolge zu ändern? (Was übrigens auch nicht hilft. :( )

CalganX 28. Feb 2003 20:40

Die Funktion, die du in Write schreibst, muss, glaube ich, einen Parameter des Typs erhalten, der auch die Property hat.
So ungefähr... :roll:

Chris

PS: Ich weiß: ist ziemlich unverständlich!

Luckie 28. Feb 2003 20:50

OK, habe es jetzt so geändert:
Delphi-Quellcode:
type
  TSplitStrArray = array of String;

type TSplitString = class
 private
   FString2Split : String;
   FSepChar     : Char;
   FStrings     : TSplitStrArray;
   FStringsCount : Integer;
   FSepPos      : array of Integer;
   procedure SetSplitString(SplitStr: String);
   procedure SetSepChar(sep: Char);
   procedure SetSepPos;
   procedure SplitString(sArray: TSplitStrArray);
 public
   constructor create(SplitStr: String; sep: Char);
   function StringsCount: Integer;
   property String2Split: String read FString2Split write SetSplitString;
   property SepChar: Char read FSepChar write SetSepChar;
   property SplitStringEx: TSplitStrArray read FStrings write SplitString(sArray: TSplitStrArray); { Zeile 192 }
end;
Jetzt sagt er mir in der gleichen Zeile wie oben:
Zitat:

[Fehler] AdressDB.dpr(192): ';' erwartet, aber '(' gefunden
[Fehler] AdressDB.dpr(192): 'END' erwartet, aber ')' gefunden
Bei der ersten Meldung steht der Cursor direkt vor sArray. Beim zweiten vor dem Abschließenden Semikolon.

Luckie 28. Feb 2003 21:05

OK, OK, OK. Ich habs. Die letzte Zeile muß natürlich so
Delphi-Quellcode:
property SplitStringEx: TSplitStrArray read FStrings write SplitString;
heißen.

CalganX 28. Feb 2003 21:26

Jetzt funktionierts? :?:

Chris

Luckie 28. Feb 2003 21:28

Mehr oder weniger. Kompilieren tuit er, er macht nur nicht das, was ich will.

jbg 28. Feb 2003 21:54

Hier mal eine Nachbildung des Explode-Befehls von PHP. Das dürft wohl in etwa das sein, was du da in deine Klasse einprogrammieren willst.
Delphi-Quellcode:
uses Types;

// Explode trennt S in die durch Separator getrennten Elemente auf. Wenn Limit
// > 0 ist, so werden max. Limit Elemente getrennt, wobei im letzen Element
// die Restzeichenkette steht.
{type
  TStringDynArray = array of string;}

function Explode(const Separator, S: string; Limit: Integer = 0): TStringDynArray;
var
  SepLen: Integer;
  F, P: PChar;
  ALen, Index: Integer;
begin
  SetLength(Result, 0);
  if (S = '') or (Limit < 0) then Exit;
  if Separator = '' then
  begin
    SetLength(Result, 1);
    Result[0] := S;
    Exit;
  end;
  SepLen := Length(Separator);
  ALen := Limit;
  SetLength(Result, ALen);

  Index := 0;
  P := PChar(S);
  while P^ <> #0 do
  begin
    F := P;
    P := AnsiStrPos(P, PChar(Separator));
    if (P = nil) or ((Limit > 0) and (Index = Limit - 1)) then P := StrEnd(F);
    if Index >= ALen then
    begin
      Inc(ALen, 5); // mehrere auf einmal um schneller arbeiten zu können
      SetLength(Result, ALen);
    end;
    SetString(Result[Index], F, P - F);
    Inc(Index);
    if P^ <> #0 then Inc(P, SepLen);
  end;
  if Index < ALen then SetLength(Result, Index); // wirkliche Länge festlegen
end;

Luckie 28. Feb 2003 21:59

Zitat:

Zitat von jbg
Hier mal eine Nachbildung des Explode-Befehls von PHP. Das dürft wohl in etwa das sein, was du da in deine Klasse einprogrammieren willst.

Du hast es erfaßt. :mrgreen: Und ich werde wohl deinen Code nehmen. Denn mit einer Klasse schießt man damit wohl mit Spatzen auf Kanonen. Trotzdem bleibt mein Wunsch aus dem anderen Topic bestehe, was man verbessern könnte oder ändern sollte. Dient ja auch der Übung.

Christian Seehase 28. Feb 2003 22:59

Moin Luckie,

noch ein kleiner Tip, um sich die Sache mit den Parametern bei den Get-/Setmethoden zu erleichtern:

Schreib' einfach nur

Delphi-Quellcode:
property Eigenschaft : typ read GetMethode write SetMethode
und dann noch STRG-SHIFT-C gedrückt und schon hat man die Methodedeklaration in der Klasse stehen, und die Grundfunktion unter implementation.
Das geht auch mit "nur" Deklarierten Methoden und auch mit mehreren auf einmal.
Also alle Methoden soweit deklarieren wie notwendig, STRG-SHIFT-C und schon hat man die Grundroutinen fertig.

CalganX 28. Feb 2003 23:08

Moin Christian,
STRG-SHIFT-C bewirkt bei mir nichts. :(
Was genau soll das bewirken und wo muss man mit dem Cursor sein?

Chris *gähn*

Christian Seehase 28. Feb 2003 23:12

Moin Chris,

angenommen, Du hast folgende Deklaration:

Delphi-Quellcode:
type
  Test = class(TObject)
  private
    FsTest : string;
  public
    property TestProp : string read GetString write SetString;
  end;
und unter implementation steht noch nichts, dann kannst Du, mit Cursor in der property Zeile, STRG-SHIFT-C drücken und hast anschliessend:

Delphi-Quellcode:
type
  Test = class(TObject)
  private
    FsTest : string;
    function GetString: string;
    procedure SetString(const Value: string);
  public
    property TestProp : string read GetString write SetString;
  end;

implementation

function test.GetString: string;
begin

end;

procedure test.SetString(const Value: string);
begin

end;

David Martens 20. Nov 2009 23:09

Re: Probleme mit eigener Klasse
 
Die Explode Funktion ist in Delphi schon implementiert:

Delphi-Quellcode:
var
  sl : TStringList;          
  i : Integer;
begin
  sl := TStringList.Create;

  sl.Delimiter := ' ';       // Trenner der einzelnen "Strings"
  sl.QuoteChar := '|';       // "Quotierung" der Strings

  // hier wird das String separiert und Delphi macht alles für uns
  sl.DelimitedText := '|123 abc| |yxz 987| |hinz und kunz 0192837465|';

  // jetzt noch eine kleine Ausgabe
  for i := 0 to sl.Count-1 do
    ShowMessage(sl[i]);      // oder sl.Strings[i]

  // fertig, Freigeben nicht vergessen
  sl.Free;
end;

Luckie 20. Nov 2009 23:11

Re: Probleme mit eigener Klasse
 
Ähm, der Thread ist fast sieben Jahre alt. :?

David Martens 21. Nov 2009 01:56

Re: Probleme mit eigener Klasse
 
JA, ich weiß, aber das Beispiel mit dem Explode hab ich schon öfters gesehen. Ich wollt jetzt deswegen kein neues Thema anfangen und die Code-Library ist ja geschlossen ;)

himitsu 21. Nov 2009 10:42

Re: Probleme mit eigener Klasse
 
Zitat:

Zitat von David Martens
die Code-Library ist ja geschlossen ;)

'nen neues Thema in "Neuen Beitrag zur Code-Library hinzufügen" erstellen und 'nen Link zum gesperrten CL-Eintrag.

@Luckie: besser spät als nie und so hast'e nun endlich eine Lösung für dein Problem :mrgreen:


Alle Zeitangaben in WEZ +1. Es ist jetzt 12:41 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz