Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - String zwischen zwei Zeichen auslesen


Dibelius - Do 24.04.08 18:11
Titel: String zwischen zwei Zeichen auslesen
Hallo,

ja, ich weiß, das Thema gab es schon Dutzende Male und ich hab vorher auch die SuFu genutzt. So richtig schlau wurde ich daraus aber nie ganz, zumal ich in Delphi immer noch Anfänger bin.

Wie auch immer, ich hoffe, dass mir jemand explizit zu meinem Problem Auskunft geben kann.

Ich möchte aus einem String Werte auslesen, die von " umschlossen sind. Es geht dabei speziell um XML-tags.
Ein Beispiel dazu:


XML-Daten
1:
<tag value1="1.0" value2="2.052365" value3="0.5043" />                    

Ich hab es also über Pos() und Copy() probiert, um mir die Position des 1. "-Zeichens angeben zu lassen. Soweit auch nichts Besonderes. Über Copy() wollte ich anschließend den Wert (zb. von value1, also 1.0) in ein string array kopieren.

Mein Problem ist aber, dass mir nicht ganz klar ist, wie ich das Ende des strings festlege, sodass nur zwischen den beiden " kopiert wird. Die Werte können, wie oben im Beispiel, unterschiedlich lang sein, was die Zeichen angeht, sodass ein direktes Auslesen über String[I] schonmal weg fällt, denke ich.
Weiterhin müssen ja die Werte von value2 und 3 ebenfalls noch ausgelesen werden.

Wäre nett, wenn mir da jemand ein paar Denkanstöße geben könnte.
Ich brauche keinen komplett vorgekauten Code. Sofern es nicht in Richtung Experten-Coding geht, bin ich auch schon für einen ungefähren Algo, die benötigten Funktionen oder Pseudocode dankbar.

MfG
Dibelius


AXMD - Do 24.04.08 20:44

Suche in: Delphi-Forum POSEX oder in deinem Fall besser Suche in: Delphi-Forum XML PARSER

AXMD


Dibelius - Fr 25.04.08 15:23

ok, ich hab's jetzt mit posex probiert und dachte mir das ganze in der Art:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm1.Button1Click(Sender: TObject);
var
  Len, i, j: integer;
  Str: string;
  P: array[1..6of byte;  // Positionen von " innerhalb des Strings Str
begin
  if (RBByte.Checked) then begin
    Len:= Edit1.GetTextLen;
    Str:= Edit1.Text;

    if Len>0 then begin
      for i:=1 to Len do begin
        Str[i]:=Str[i];
        if Str[i]='"' then begin
          for j:=1 to 6 do begin P[j]:= PoSex('"',Str,i);
        end;
      end;
    end;

  end;
end;

Zur Erklärung, wie ich mir das dachte: Das Zeichen " kommt immer genau 6x vor, sofern der richtige tag in das Editfeld eingegeben wurde. Deshalb dachte ich mir, lass ich die äußere Schleife von 1 bis Textende laufen, um jedes Zeichen einzeln auszulesen. Sobald das Zeichen gefunden wurde, sollte durch die innere Schleife mit j die Position P[j] des Zeichens im array gespeichert werden, welches ich dann später für Copy() brauche, um Start- und Endpunkt festzulegen.

Die innere Schleife funktioniert aber nicht so, wie sie soll... und ich steh da grad aufm schlauch.
Jedes Feld von P[1..6] ist nun mit der Position vom letzten Vorkommen des Zeichens gefüllt. :/


Zorro - Fr 25.04.08 15:44

Ganz ohne Posex, dafür mit dem Vorteil, dass das Vorkommen der Anführungszeichen nicht auf 6 festgelegt ist (sondern 2n betragen kann):


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure TForm1.Button1Click(Sender: TObject);
Var S,T: String;
    z: Integer;
    BinInQuotes: Boolean;
begin
  S := edit1.text;
  T := '';
  BinInQuotes := False; // init
  For z := 1 To Length(S) Do Begin
    If BinInQuotes Then Begin
      If (S[z] <> '"')
      Then T := T + S[z]
      Else Begin
        Listbox1.Items.Add(T);
        T := '';
      End;
    End;
    If S[z] = '"'
    Then BinInQuotes := (Not BinInQuotes);
  End;
end;


Greetz
Zorro


Dibelius - Fr 25.04.08 16:02

versteh ich irgendwie nicht ganz, sry :(

Ich würde auch ganz gern bei pos() bzw. posex() bleiben, wenn ich schonmal dabei bin. Das erscheint mir persönlich logischer, auch wenn's sicher mehrere (und professionellere) Wege zum Ziel gibt.

// Edit: ich glaub, ich hab's nun... ich hab wieder viel zu kompliziert gedacht ^^
Eigentlich ganz einfach, aber hinterher ist man immer schlauer.


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
      j:=1;  // init
      for i:=1 to Length(Str) do begin
        Str[i]:=Str[i];
        if Str[i]='"' then begin
          P[j]:= PoSex('"',Str,i);
          Inc(j);
        end;
      end;


Danke für die Hilfe und Denkanstöße!


bflegel - Fr 25.04.08 16:26

Hallo,

nicht schön, aber folgendes ermittelt die Stellen im String, an denen sich ein " befinden:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure TForm1.Button1Click(Sender: TObject);
var
s : string;
int_array : array [1..6of integer;
i : integer;

begin
  i:=1;
  s:=edit1.text;
  while Pos('"', S) > 0 do
    begin
      int_array[i] := Pos('"', S);
      S[Pos('"', S)] := '0';
      inc(i);
    end;
  for i := 1 to 6 do
    listbox1.Items.Add(inttostr(int_array[i]));
end;


P.S. Ich musste Pos nehmen, da unter Delphi 5 anscheinend PosEx (noch) nicht vorhanden ist.

Bye
bflegel


Nico72 - Fr 25.04.08 16:34

Hallo,

lass mal

Delphi-Quelltext
1:
Str[i]:=Str[i]                    

weg...
Das in deinem Array nur die Position des letzte " drinsteht, ist ja klar. Du schreibst es ja rein:

Delphi-Quelltext
1:
for j:=1 to 6 do begin P[j]:= PoSex('"',Str,i);                    

füllt für jedes i das gesamte(!) Array mit der Position von " ab i. Übrigens heisst die Funktion PosEx :roll:

Wenn du mit deinem Ansatz weiterarbeiten möchtest, dann versuch doch mal folgendes:
Beim ersten Finden von " schreibst du dir die Position des Zeichens in dein Array, und zwar in das erste Feld.
Beim den nächsten " schreibst du dir die Position des Zeichens in dein Array, und zwar in das jeweils nächste Feld.