Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi String in Array zerlegen (Markanter Punkt: ',') (https://www.delphipraxis.net/1203-string-array-zerlegen-markanter-punkt.html)

rebugger 31. Okt 2002 16:59


String in Array zerlegen (Markanter Punkt: ',')
 
Hallo,
habe einen String, der folgendermaßen aussieht:
var1:='$0045CDFA,clNone,0,1,0,0'

Nun möchte ich var1 in ein Array zerlegen, dass in $var2[0] '$0045CDFA'
und in $var2[1] 'clNone', usw. steht !

Wie kann ich das machen ?
Wie lautet der Befehl ?

jbg 31. Okt 2002 17:04

Re: String in Array zerlegen (Markanter Punkt: ',')
 
Zitat:

Zitat von rebugger
Wie kann ich das machen ?

Zumindest nicht so wie in PHP.

Zitat:

Wie lautet der Befehl ?
Ein von Delphi bereitgestellter Befehl ist mir nicht bekannt. Da heißt es wohl selbst Hand anlegen.
-> Pos(), Copy(), ggf. auch Delete()

Luckie 31. Okt 2002 17:07

Code:
[b]type[/b] TZeile = [b]array[/b] [b]of[/b] [b]string[/b];

[color=#000080][i]{ Zeile parsen }[/i][/color]
[b]function[/b] Parse(zeile: [b]string[/b];zeilennummer:longint ):TZeile;
[b]var[/b] i    :longint;
    anzahl:longint;
    pos  :[b]array[/b] [b]of[/b] integer;
[b]begin[/b]
  anzahl:=0;
  SetLength(pos,0);
  SetLength(result, 0);
  [b]for[/b] i := 1 [b]to[/b] Length(zeile) [b]do[/b]
    [b]if[/b] zeile[ i ] = ';' [b]then[/b] // <-- ACHTUNG KORRIGIERT!!!
    [b]begin[/b]
      inc(anzahl);
      SetLength(pos, anzahl);
      pos[anzahl-1]:=i;
      SetLength(result, anzahl);
    [b]end[/b];
  [b]for[/b] i:=0 [b]to[/b] high(result) [b]do[/b]
    [b]begin[/b]
      [b]if[/b] i=0 [b]then[/b]
        result[i ]:=copy(zeile,1,pos[0]-1)
      [b]else[/b]
        result[i ]:=copy(zeile,pos[i-1]+1,pos[i ]-1-pos[i-1]); // <-- ACHTUNG KORRIGIERT!!!
    [b]end[/b];
  [color=#000080][i ]//if Length(result)=0 then Messagebox(0, '', 'Fehler', 0);[/i][/color]
[b]end[/b];
Und auf ruf mit:
Code:
[b]var[/b]
  Zeile : TZeile;
[b]begin[/b]
  Zeile := Parse(s, 0);
Auf die einzelnen Elemente kannst du dann mit den Index zugreifen. Das erste Element bekommst du dann mit Zeile[0].

rebugger 31. Okt 2002 17:24

Habe es nun so gemacht:
Code:
type TZeile = array of string;
.
.
.
//Deine Funktion
.
.
.
function TMain.Intialize_Highlight(): Bool;
var
  ini: TIniFile;
  php_comment, php_identifier, php_invalidsymbol, php_key,
  php_number, php_space, php_string, php_symbol, php_variable: TZeile;
  tmp_style: TFontStyle;
begin
  ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'highlight.cfg');
  try
    php_comment := Parse(ini.ReadString('PHP','Comment','$0045CDFA,clNone,0,1,0,0'), 0);
    { Zeile 180 }PHPhigh.CommentAttri.Foreground := IntToStr(php_comment[0]);
    PHPhigh.CommentAttri.Background := IntToStr(php_comment[1]);

    if IntToStr(php_comment[2]) = 1 then
      PHPhigh.CommentAttri.Style := fsBold;
    if IntToStr(php_comment[3]) = 1 then
      PHPhigh.CommentAttri.Style := fsItalic;
    if IntToStr(php_comment[4]) = 1 then
      PHPhigh.CommentAttri.Style := fsUnderline;
    if IntToStr(php_comment[5]) = 1 then
      PHPhigh.CommentAttri.Style := fsStrikeOut;

  finally
    ini.Free;
  end;
end;
Aber er sagt:
[Fehler] main_unit.pas(180): Es gibt keine überladene Version von 'IntToStr', die man mit diesen Argumenten aufrufen kann

Luckie 31. Okt 2002 17:35

php_comment[2]

Das ist doch schon ein String. Kuck dir doch mal die Typdeklarartion von TZeile an: array of String.

MathiasSimmack 1. Nov 2002 07:01

Re: String in Array zerlegen (Markanter Punkt: ',')
 
Zitat:

Zitat von jbg
Ein von Delphi bereitgestellter Befehl ist mir nicht bekannt.

Mir auch nicht, aber wenn es immer bei einem Komma bleiben wird, dann hätte ich die Eigenschaft "CommaText" von TStringList herangezogen.

Zitat:

Da heißt es wohl selbst Hand anlegen.
Ja. Und die Idee mit dem eigenen Parser ist auf jeden Fall eleganter, wenn man davon ausgeht, dass sich der Separator ändern könnte.

Luckie 1. Nov 2002 12:18

ACHTUNG, ACHTUNG der Coderformatierer hat ein paar [*i*]'s geschluckt. Ich habe es korrigiert. Bitte überprüf noch mal deinen Code. Danke

Christian Seehase 1. Nov 2002 13:28

Moin Luckie,

ich hab' jetzt mal den Code aus dem Posting genommen, alle Blanks vor bzw. hinter den eckigen Klammern entfernt und den Formatierer laufen lassen.

Kein Fehler feststellbar. :shock:

rebugger 1. Nov 2002 13:33

OK, Alles nochmal:
Code:
type TZeile = array of string;
.
  public
    { Public-Deklarationen }
    function Intialize_Highlight(): Bool;
    function Parse(zeile: string;zeilennummer:longint ):TZeile;
.
function TMain.Parse(zeile: string;zeilennummer:longint ):TZeile;
var i    :longint;
    anzahl:longint;
    pos  :array of integer;
begin
  anzahl:=0;
  SetLength(pos,0);
  SetLength(result, 0);
  for i := 1 to Length(zeile) do
    if zeile[ i ] = ';' then // <-- ACHTUNG KORRIGIERT!!!
    begin
      inc(anzahl);
      SetLength(pos, anzahl);
      pos[anzahl-1]:=i;
      SetLength(result, anzahl);
    end;
  for i:=0 to high(result) do
    begin
      if i=0 then
        result[i ]:=copy(zeile,1,pos[0]-1)
      else
        result[i ]:=copy(zeile,pos[i-1]+1,pos-1-pos[i-1]); // <-- ACHTUNG KORRIGIERT!!!
    end;
  //if Length(result)=0 then Messagebox(0, '', 'Fehler', 0);
end;

function TMain.Intialize_Highlight(): Bool;
var
  ini: TIniFile;
  php_comment, php_identifier, php_invalidsymbol, php_key,
  php_number, php_space, php_string, php_symbol, php_variable: TZeile;
  tmp_style: TZeile;
begin
  ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'highlight.cfg');
  try
    php_comment := Parse(ini.ReadString('PHP','Comment','$0045CDFA,clNone,0,1,0,0'), 0);
    PHPhigh.CommentAttri.Foreground := IntToStr(php_comment[0]);
    PHPhigh.CommentAttri.Background := IntToStr(php_comment[1]);

    if IntToStr(php_comment[2]) = 1 then
      PHPhigh.CommentAttri.Style := fsBold;
    if IntToStr(php_comment[3]) = 1 then
      PHPhigh.CommentAttri.Style := fsItalic;
    if IntToStr(php_comment[4]) = 1 then
      PHPhigh.CommentAttri.Style := fsUnderline;
    if IntToStr(php_comment[5]) = 1 then
      PHPhigh.CommentAttri.Style := fsStrikeOut;

  finally
    ini.Free;
  end;
end;
Er sagt mir:
[Fehler] main_unit.pas(157): Operator ist auf diesen Operandentyp nicht anwendbar
Die Zeile:
Code:
result[i ]:=copy(zeile,pos[i-1]+1,pos-1-pos[i-1]);
Wo liegt der Fehler ?
Kann ich das ganze nicht verkürzen ?
Ich müsste das ganze sonst noch mit PHPhigh.IdentifierAttri.... und noch weiteren 40 Objekten machen und das wäre sehr viel Code !
Kann man das alles nicht in eine Funktion zusammenfassen, an die ich nur noch z.B. "PHPHigh.CommentAttri" übergeben muss ?

Luckie 1. Nov 2002 13:36

Also bei mir tut es die Funktion jedes mal. Keinen Plan, was du da gemacht hast. :?

Christian Seehase 1. Nov 2002 13:39

Moin Rebugger,

Du hast pos als array of integer deklariert, dann aber ohne Index benutzt

Code:
result[i ]:=copy(zeile,pos[i-1]+1,[color=red]pos[/color]-1-pos[i-1]);
wobei ich etwas unglücklich finde einen Funktionsnamen (pos) als Variablennamen zu benutzten. ;-)

rebugger 1. Nov 2002 13:46

Ja, is klar...
Blick nur nich durch, was daran geändert werden muss (welcher array wert dort hineingehört)

Habe nun eine extra funktion für den aufruf von parse() geschrieben:
Code:
function TMain.Intialize_Highlight(Highlight: TSynHighlighterAttributes; Section: String; Part: String; Standard: String): Bool;
var
  ini: TIniFile;
  tmp_style: TZeile;
begin
  ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'highlight.cfg');
  try
    tmp_style := Parse(ini.ReadString(Section,Part,Standard), 0);
    Highlight.Foreground := StrToInt(tmp_style[0]);
    Highlight.Background := StrToInt(tmp_style[1]);

    if StrToInt(tmp_style[2]) = 1 then
      Highlight.Style := [fsBold];
    if StrToInt(tmp_style[3]) = 1 then
      Highlight.Style := [fsItalic];
    if StrToInt(tmp_style[4]) = 1 then
      Highlight.Style := [fsUnderline];
    if StrToInt(tmp_style[5]) = 1 then
      Highlight.Style := [fsStrikeOut];
  finally
    ini.Free;
  end;
  result := TRUE;
end;
Jetzt müsste nur noch der Fehler in der Funktion Parse() gefixed werden.
Weiß aber net, was da reingehört !

Luckie 1. Nov 2002 13:46

In der zeile:
Code:
result[i ]:=copy(zeile,pos[i-1]+1,pos[i ]-1-pos[i-1]);
war noch ein Fehler drin. Ich habe ihn noch mal korrigiert.

rebugger 1. Nov 2002 13:50

Hm, trotzdem sagt er beim Start meines Programmes:
"Zugriffsverletzung auf Adresse 004A8725 in Modul 'project1.php'. Lesen von Adresse 00000000."

Luckie 1. Nov 2002 13:52

Dann hast du irgendwo eine ungültige Zeile drin. Bei dem Parser ist das Trennzeichen ein ";" du hast aber ein ",". Also in der Parse-Funktion anpassen.

rebugger 1. Nov 2002 13:56

Hm, dann sagt er mir beim Aufruf "clNone ist kein gültiger Integerwert"
Das liegt an
pos: array of integer;

Aber dieser lange String
Comment=$0045CDFA,clNone,0,1,0,0

Kann ja Buchstaben und Zahlen enthalten !

Luckie 1. Nov 2002 14:02

Kann es sein, dass dein Fehler irgendwo hier
Code:
if IntToStr(php_comment[2]) = 1 then
      PHPhigh.CommentAttri.Style := fsBold;
    if IntToStr(php_comment[3]) = 1 then
      PHPhigh.CommentAttri.Style := fsItalic;
    if IntToStr(php_comment[4]) = 1 then
      PHPhigh.CommentAttri.Style := fsUnderline;
    if IntToStr(php_comment[5]) = 1 then
      PHPhigh.CommentAttri.Style := fsStrikeOut;
liegt?

rebugger 1. Nov 2002 14:13

Jo, hab das jetzt korrigiert !
Wenn ich in der Funktion Parse()
Code:
if zeile[ i ] = ',' then
Kommt nurnoch dieser Fehler:
"clNone ist kein gültiger Integerwert"

Das liegt an
pos: array of integer;

Aber dieser String
$0045CDFA,clNone,0,1,0,0
kann ja Buchstaben und Zahlen enthalten

rebugger 1. Nov 2002 14:18

Halt, Stopp !
Kommando zurück !
Fehler-Stelle gefunden:
Code:
Highlight.Foreground := StrToInt(tmp_style[0]);
Highlight.Background := StrToInt(tmp_style[1]);
Lag an meiner Funktion !
Da ja hier bei tmp_style[1] "clNone" drin steht und nicht zu Integer umgewandelt werden kann !
Wie kann ich sonst von String in TColor umwandeln ?

Christian Seehase 1. Nov 2002 14:25

Moin Rebugger,

da auch dynamische Arrays wieder freigegeben werden müssen, hätte ich da noch zwei Vorschläge.

1. Mit Luckies Parse / TZeile

Code:
[b]function[/b] TMain.Intialize_Highlight(Highlight: TSynHighlighterAttributes; Section: [b]String[/b]; Part: [b]String[/b]; Standard: [b]String[/b]): Bool;
[b]var[/b]
  ini: TIniFile;
  tmp_style: TZeile;
[b]begin[/b]
  ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'highlight.cfg');
  [b]try[/b]
    tmp_style := Parse(ini.ReadString(Section,Part,Standard), 0);
    [b]try[/b]
      Highlight.Foreground := StrToInt(tmp_style[0]);
      Highlight.Background := StrToInt(tmp_style[1]);

      [b]if[/b] StrToInt(tmp_style[2]) = 1 [b]then[/b]
        Highlight.Style := [fsBold];
      [b]if[/b] StrToInt(tmp_style[3]) = 1 [b]then[/b]
        Highlight.Style := [fsItalic];
      [b]if[/b] StrToInt(tmp_style[4]) = 1 [b]then[/b]
        Highlight.Style := [fsUnderline];
      [b]if[/b] StrToInt(tmp_style[5]) = 1 [b]then[/b]
        Highlight.Style := [fsStrikeOut];
    [b]finally[/b]
      finalize(tmp_style);
      FreeAndNil(tmp_style);
    [b]end[/b];
  [b]finally[/b]
    ini.Free;
  [b]end[/b];
  result := TRUE;
[b]end[/b];
2. Mit einer TStringList statt array of string und StringReplace statt Parse

Code:
[b]function[/b] TMain.Intialize_Highlight(Highlight: TSynHighlighterAttributes; Section: [b]String[/b]; Part: [b]String[/b]; Standard: [b]String[/b]): Bool;
[b]var[/b]
  ini: TIniFile;
  tmp_style: TStringList;
[b]begin[/b]
  ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'highlight.cfg');
  [b]try[/b]
    tmp_style := TStringList.Create;
    [b]try[/b]
      tmp_style := StringReplace(ini.ReadString(Section,Part,Standard),',',#13#10,[rfReplaceAll]);
      Highlight.Foreground := StrToInt(tmp_style[0]);
      Highlight.Background := StrToInt(tmp_style[1]);

      [b]if[/b] StrToInt(tmp_style[2]) = 1 [b]then[/b]
        Highlight.Style := [fsBold];
      [b]if[/b] StrToInt(tmp_style[3]) = 1 [b]then[/b]
        Highlight.Style := [fsItalic];
      [b]if[/b] StrToInt(tmp_style[4]) = 1 [b]then[/b]
        Highlight.Style := [fsUnderline];
      [b]if[/b] StrToInt(tmp_style[5]) = 1 [b]then[/b]
        Highlight.Style := [fsStrikeOut];
    [b]finally[/b]
      FreeAndNil(tmp_style);
    [b]end[/b];
  [b]finally[/b]
    ini.Free;
  [b]end[/b];
  result := TRUE;
[b]end[/b];

Christian Seehase 1. Nov 2002 14:27

Moin Rebugger,

Zitat:

Zitat von Rebugger
Wie kann ich sonst von String in TColor umwandeln ?

Fast hattest Du's:

Mit StringToColor :mrgreen:

Christian Seehase 1. Nov 2002 14:41

Moin Rebugger,

was mir gerade aufgefallen ist:
Die Style Attribute ergänzen sich nicht, sondern das zuletzt gefundene ersetzt bereits gesetzte.

Statt

Highlight.Style := [fsItalic];

müsste es also

Highlight.Style := Highlight.Style + [fsItalic];

heissen.

(bei den folgenden Attributen analog versteht sich).

rebugger 1. Nov 2002 21:30

Wow, Christian !
OK, habe deine 2. Methode mit der Stringlist genommen !
Einizger Fehler:
Code:
tmp_style := StringReplace(ini.ReadString(Section,Part,Standard),',',#13#10,[rfReplaceAll]);
[Fehler] main_unit.pas(197): Inkompatible Typen: 'TStringList' und 'String'

rebugger 1. Nov 2002 21:40

Hm, ok, Problem auch wieder gelöst !
Mein aktueller Code:
Code:
function TMain.Intialize_Highlight(Highlight: TSynHighlighterAttributes; Section: String; Part: String; Standard: String): Bool;
var
  ini: TIniFile;
  tmp_style: TStringList;
begin
  ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'highlight.cfg');
  try
    tmp_style := TStringList.Create;
    try
      tmp_style.Add(StringReplace(ini.ReadString(Section,Part,Standard),',',#13#10,[rfReplaceAll]));
      Highlight.Foreground := StringToColor(tmp_style[0]);
      Highlight.Background := StringToColor(tmp_style[1]);

      if tmp_style[2] = '1' then
        Highlight.Style := Highlight.Style + [fsBold];
      if tmp_style[3] = '1' then
        Highlight.Style := Highlight.Style + [fsItalic];
      if tmp_style[4] = '1' then
        Highlight.Style := Highlight.Style + [fsUnderline];
      if tmp_style[5] = '1' then
        Highlight.Style := Highlight.Style + [fsStrikeOut];
    finally
      FreeAndNil(tmp_style);
    end;
  finally
    ini.Free;
  end;
  result := TRUE;
end;
Jetzt sagt er beim Aufruf:
[b]'$0045CDFA
clNone
0
1
0
0' ist kein gültiger Integerwert8/b]

rebugger 1. Nov 2002 21:40

Hm, ok, Problem auch wieder gelöst !
Mein aktueller Code:
Code:
function TMain.Intialize_Highlight(Highlight: TSynHighlighterAttributes; Section: String; Part: String; Standard: String): Bool;
var
  ini: TIniFile;
  tmp_style: TStringList;
begin
  ini := TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'highlight.cfg');
  try
    tmp_style := TStringList.Create;
    try
      tmp_style.Add(StringReplace(ini.ReadString(Section,Part,Standard),',',#13#10,[rfReplaceAll]));
      Highlight.Foreground := StringToColor(tmp_style[0]);
      Highlight.Background := StringToColor(tmp_style[1]);

      if tmp_style[2] = '1' then
        Highlight.Style := Highlight.Style + [fsBold];
      if tmp_style[3] = '1' then
        Highlight.Style := Highlight.Style + [fsItalic];
      if tmp_style[4] = '1' then
        Highlight.Style := Highlight.Style + [fsUnderline];
      if tmp_style[5] = '1' then
        Highlight.Style := Highlight.Style + [fsStrikeOut];
    finally
      FreeAndNil(tmp_style);
    end;
  finally
    ini.Free;
  end;
  result := TRUE;
end;
Jetzt sagt er beim Aufruf:
'$0045CDFA
clNone
0
1
0
0' ist kein gültiger Integerwert

Christian Seehase 2. Nov 2002 01:51

Moin Rebugger,

war ein blöder Fehler von mir (kommt davon wenn man's nicht ausprobiert :oops: )

Es muss eigentlich heissen:

tmp_style.text := StringReplace(....

Dann sollte der beschriebene Fehler auch weg sein. Wenn Du die Zeile mit Add hinzufügst, werden die Steuerzeichen (#13#10) nicht als Zeilenumbruch gewertet, sondern mit in den ersten String der Liste übernommen.
Weist Du hingegen der Eigenschaft Text einen String zu, der die Zeilenumbruchzeichen enthält, dröselt Delphi das zu einzelnen Zeilen auf.

Der Nachteil aller komfortablen Stringfunktionen / -Klassen (z.B. eben StringReplace, TStringList) ist allerdings die oft schlechte Performance.

Wenn diese oft genutzt werden (z.B. in Schleifen) wirkt sich das meist stark auf die Geschwindigkeit aus.

MathiasSimmack 2. Nov 2002 07:44

Und deswegen hatte ich ja gedacht, Chris, du schiebst den komma-separierten String direkt an die Eigenschaft "CommaText". Dann hättest du dir den "StringReplace"-Kram sparen können.
Code:
tmp_style.CommaText := ini.ReadString(Section,Part,Standard);

rebugger 2. Nov 2002 08:10

Danke euch beiden (Christian und Mathias) !
Habe nun alles richtig und mein Programm läuft perfekt !

Vielen Dank nochmal !

Christian Seehase 2. Nov 2002 12:06

Moin Mathias,

stimmt, hast Du auch wieder wahr :mrgreen:

CommaText hatte ich bislang nie verwendet.

Wieder was gelernt.

CalganX 2. Nov 2002 16:47

Zitat:

Zitat von rebugger
"Zugriffsverletzung auf Adresse 004A8725 in Modul 'project1.php'. Lesen von Adresse 00000000."

Mal eine Frage zwischendurch: Warum nutzt du .php? Wenn du das ganze als PHP auf einem Server nutzen willst kann ich dir gleich sagen, dass das nicht funktionieren wird..

Chris

Daniel B 2. Nov 2002 17:20

Zitat:

Zitat von Chakotay1308
Mal eine Frage zwischendurch: Warum nutzt du .php? Wenn du das ganze als PHP auf einem Server nutzen willst kann ich dir gleich sagen, dass das nicht funktionieren wird..

Es soll ja noch Server mit NT geben. :wink:

MathiasSimmack 2. Nov 2002 17:50

Zitat:

Zitat von Daniel B
Es soll ja noch Server mit NT geben. :wink:

Ja, sicher. Aber wird aus einem Delphi-Quellcode mit der Endung ".php" automatisch ein PHP-Skript? Irgendwie habe ich da meine 2fel. :roll:

Daniel B 2. Nov 2002 17:57

Zitat:

Zitat von MathiasSimmack
Ja, sicher. Aber wird aus einem Delphi-Quellcode mit der Endung ".php" automatisch ein PHP-Skript? Irgendwie habe ich da meine 2fel. :roll:

Nein, das sicher nicht, das wäre das gleiche, als würde er eine .exe mit dem Editor öffnen. Wobei er das Prgramm gleich mit .exe erzeugen würde. Irgendwie ist noch nicht so ganz Klar was er vor hat.

rebugger 2. Nov 2002 19:33

hehe, musst mich net für doof halten... hatte nur die meldung falsch abgeschrieben ! das is natürlich .exe ! das mit .php war nur reine gewohnheit !


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