AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

String nach bestimmten muster auflösen

Ein Thema von Overphil · begonnen am 19. Okt 2015 · letzter Beitrag vom 20. Okt 2015
Antwort Antwort
Seite 1 von 2  1 2      
Overphil

Registriert seit: 19. Okt 2015
4 Beiträge
 
#1

String nach bestimmten muster auflösen

  Alt 19. Okt 2015, 12:07
Hallo zusammen, ich habe folgendes Problem.
Ich will ein Programm schreiben, mit dem ich mittels eigenen Textbefehlen aus einem editfeld in einer Imagekomponente zeichnen kann. Also z.B. V90R45V90 soll 90px "nach vorne" zeichnen, dann wird um 45 grad nach rechts gedreht und wieder 90px in die neue richtung gezeichnet.
Außerdem gibt es noch wiederholungsbefehle, die zb so aussehen könnten: W4(v90r45). In dem fall soll das in der klammer 4 mal wiederholt werden. Mein problem ist jetzt das umschreiben dieser wiederholungsstrings. Mein ansatz war, den inhalt der klammern in einen neuen string zu speichern und diesen dann eben entsprechend oft zu wiederholen. Durch eine while schleife ermittle ich, wo sich die erste und zweite klammer des jeweiligen W befindet und speichere dann den Inhalt in einem neuen string. Meine frage also jetzt, wie mache ich es, dass der string so lange aufgelöst wird, bis er keine wiederholungsbefehle mehr enthält, denn so ein string könnte ja auch so aussehen W2(w2(v90)), wenn man das auflöst, hätte man ja w2(v90)w2(v90), was wiederrum aufgelöst werden muss.
Hier meine kleine Funktion, die den string auflösen soll:

Meine Variablen
repInt: gibt die Anzahl der wiederholungen an, die nach einem W steht
wCount: Variable zum finden der zugehörigen klammer
bracketPlace1/2: Position der ersten bzw. zweiten Klammer
repStr: Der string, der wiederholt werden soll(dieser soll eigentlich dann voll aufgelöst und der rückgabestring sein)
oldRepStr: der wiederholungsstring vom letzten schleifendurchlauf
strToCopy: beinhaltet den befehl in einer klammer


Code:
function TForm1.interpretateString(str:string) : string;
var repInt, wCount, bracketPlace1, bracketPlace2, i, j: integer;
  repStr, oldRepStr, strToCopy: string;
begin
     wCount:=0;
     bracketPlace2:=0;
     oldRepStr:='';
     repStr:='';
     for i:=1 to Length(str) do begin
         if str[i]='W' then begin



              repInt:=getCount(str, i);

              bracketPlace1:=i+Length(IntToStr(repInt))+2;
              j:=bracketPlace1;
              while wCount<>-1 do begin
                    if str[j]=')' then begin
                       wCount:=wCount-1;
                       if wCount=-1 then begin
                          //Delete(str, j, 1);
                          bracketPlace2:=j+1;
                          break;
                       end;
                    end
                    else if str[j]='(' then begin
                         wCount:=wCount+1;
                    end;

                   j:=j+1;
              end;

              strToCopy:=Copy(str, bracketPlace1, bracketPlace2-bracketPlace1-1);


              repStr:=repStr+repeatString(strToCopy, repInt);


              ShowMessage('repStr: '+repstr);
              oldRepStr:=repStr;

              ShowMessage('ors... '+ oldRepStr);

              result:=repStr+oldRepStr;

         end;
     end;

end;
PS: Ich weiß, dass manches da nach der while schleife nicht viel sinn gibt, aber das ist eben meine frage, wie ich nach der schleife weiter mache, sodass alles aufgelöst in einem string gespeichert wird.

Danke im vorraus
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#2

AW: String nach bestimmten muster auflösen

  Alt 19. Okt 2015, 14:00
Der einfachste Weg ist rekursiv.

Du zerlegst den Befehl und bei einer Klammer nimmst du den Zeil zwischen den Klammern und übergibst ihn ebenfalls an die Parserfunktion.

Zwischen = Klammern zählen bei ( +1, bei ) -1 und wenn 0, dann ist das die zugehörige schließende Klammer.

Bei W2 wird der Teilstring dann halt doppelt ausgewertet.


Ansonsten lernst du was eine Iteration ist und baust die Rekursion entsprechend um.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu (19. Okt 2015 um 14:02 Uhr)
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.094 Beiträge
 
Delphi 12 Athens
 
#3

AW: String nach bestimmten muster auflösen

  Alt 19. Okt 2015, 14:42
Nur mal am Rande;

Warum nimmst du nicht die gleichen Zeichenbefehle wie in TPathData ?
Könnte sein das dies so komplett definiert ist.

Bin zwar nicht sicher für alle Elemente, aber zumindest LineTo und MoveTo wird genauso wie in Inkscape geschrieben.
Ich würde einfach mal einen Path in Inkscape schreiben so wie du ihn gerne hättest, und dann mal analysieren
wie dies in Xml kodiert ist.
Wahrscheinlich macht eine solche "Zeichensprache" mehr Sinn wenn sie möglichst kompatibel ist (Inkscape, FireMonkey TPathData).

Rollo
  Mit Zitat antworten Zitat
hathor
(Gast)

n/a Beiträge
 
#4

AW: String nach bestimmten muster auflösen

  Alt 19. Okt 2015, 15:58
Kennst Du TURTLE ?
http://www.hsg-kl.de/faecher/inf/mat...ten/turtle.php

https://de.wikipedia.org/wiki/Turtle-Grafik

Geändert von hathor (19. Okt 2015 um 16:01 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#5

AW: String nach bestimmten muster auflösen

  Alt 19. Okt 2015, 16:37
Warum nimmst du nicht die gleichen Zeichenbefehle wie in TPathData ?
Ich vermute, dass das ein krudes proprietäres Format ist, das Overphil unterstützen muss

Langfristig würde ich darüber nachdenken, die Stringersetzung durch einen AST zu ersetzen. Du hast Objekte, die einzelnen Syntaxelemente repräsentieren: in deinem Fall Befehle und Schleifen.
Mit einem Visitor kannst du das Ganze dann ausführen, in ein anderes Format exportieren, oder auch einfach die Schleifen entrollen.

Geändert von BUG (19. Okt 2015 um 17:02 Uhr)
  Mit Zitat antworten Zitat
Overphil

Registriert seit: 19. Okt 2015
4 Beiträge
 
#6

AW: String nach bestimmten muster auflösen

  Alt 19. Okt 2015, 21:31
So, hab es mal mit der Rekursion versucht, allerdings klappt das ganze noch nicht so. Es wird jetzt nur die erste Klammerebene aufgelöst, aber sobald eine wiederholung in einer klammer ist klappt das nicht mehr.

Code:
function TForm1.getRepStr(str:string; count:integer) : string;
var repInt, bracketPlace1, bracketPlace2, i, wCount : integer;
  repStr : string;
begin

     wCount:=0;
     repInt:=getCount(str, count);
     bracketPlace1:=count+Length(IntToStr(repInt))+2;

     i:=bracketPlace1;
     while wCount<>-1 do begin
           if str[i]=')' then begin
              wCount:=wCount-1;
              if wCount=-1 then begin
                 bracketPlace2:=i+1;
                 break;
                 end;
              end
              else if str[i]='(' then begin
                   wCount:=wCount+1;
              end;
     i:=i+1;
     end;

     repStr:=Copy(str, bracketPlace1, bracketPlace2-bracketPlace1-1);

     repStr:=repeatString(repStr, repInt);
     ShowMessage('repStr: ' + repStr);
     if containsW(repStr)=true then repStr:=getRepStr(repStr, 1)
     else result:=repStr;

end;
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#7

AW: String nach bestimmten muster auflösen

  Alt 20. Okt 2015, 01:25
Irgendwie so in der Art könnte es aussehen:
Delphi-Quellcode:
function TForm2.ParseString(Root: TTreeNode; const S: String): Integer;
var
  I, J: Integer;
  T: TTreeNode;
begin
  I := 1;
  while (I <= Length(S)) do
  begin
    if (S[I] in ['W', 'V', 'R']) then
    begin
      J := I + 1;
      while (J <= Length(S)) and (S[J] in ['0'..'9']) do
      begin
        Inc(J);
      end;
      T := TreeView1.Items.AddChild(Root, Copy(S, I, J - I));
      if (S[I] = 'W') then
      begin
        Inc(I, J - I + ParseString(T, Copy(S, J + 1, Length(S))));
      end else
      begin
        Inc(I, J - I);
      end;
    end else if (S[I] = ')') then
    begin
      Inc(I);
      Break;
    end else
    begin
      raise Exception.Create('Failed to parse string.');
    end;
  end;
  Result := I;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  TreeView1.Items.Clear;
  TreeView1.Items.BeginUpdate;
  try
    ParseString(nil, AnsiUpperCase('V900W2(w2(v90))V90W5(V45)'));
  finally
    TreeView1.Items.EndUpdate;
  end;
end;
Geht auf jeden Fall noch eleganter, aber die Lösung hier sollte recht einfach zu verstehen sein. Die Funktion zerlegt den String in seine Einzelteile und ordnet die Befehle dann in einen TreeView ein.
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#8

AW: String nach bestimmten muster auflösen

  Alt 20. Okt 2015, 07:30
Hier mal Pseudocode.
Delphi-Quellcode:
procedure Parse;
begin
  While GetNextCommand(command) do
    Execute(command);
end;

Function GetNextCommand(var cmd : TCommand) : Boolean;
var
  c : Char;

Begin
   if AtEof Then Exit(False)
   c := TakeChar;
   if c=')then Exit(False);
   if not (c in allowedCommands) then raise Exception.Create('Invalid command');
   cmd := TCommand.Create;
   cmd.Command := c;
   cmd.Value := TakeNumber;
   if (cmd.Command = RepeatCmd) then
     if TakeChar<>'(then Raise Exception.Create('Expected "("')
   result := True;
End;

Procedure Execute (aCmd : TCommand);
Begin
  case aCmd.Command of
    RepeatCmd : Parse;
    ForwardCmd : GoForward (aCmd.Value);
    RightCmd : TurnRight(aCmd.Value);
    ...
  end
end;

Function AtEof : Boolean;
Begin
  result := CurrentPtr>Length(InputString);
End;

Function TakeChar : Char;
Begin
  result := InputString[CurrentPtr];
  inc(CurrentPtr);
End;

Function TakeNumber : Integer;
Var
  p : Integer;

Begin
  p := CurrentPtr;
  While TakeChar in Digits and Not AtEof;
  if p=CurrentPtr then Raise Exception.Create('Not a number');
  result := StrToInt(Copy(InputString,p,CurrentPtr-p));
end;

Procedure Run (aString : String);
Begin
  InputString := aString;
  CurrentPtr := 1;
  Parse;
End;
Ganz grob skizziert.
  Mit Zitat antworten Zitat
Overphil

Registriert seit: 19. Okt 2015
4 Beiträge
 
#9

AW: String nach bestimmten muster auflösen

  Alt 20. Okt 2015, 12:57
Danke erstmal für die vielen Antworten, das mit dem TreeView klappt zwar gut, doch wie mache ich es jetzt, dass ich eine Funktion habe, der man einen string mitgibt und dann den fertigen aufgelösten string wieder zurückgibt?
  Mit Zitat antworten Zitat
Benutzerbild von Zacherl
Zacherl

Registriert seit: 3. Sep 2004
4.629 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#10

AW: String nach bestimmten muster auflösen

  Alt 20. Okt 2015, 17:05
Danke erstmal für die vielen Antworten, das mit dem TreeView klappt zwar gut, doch wie mache ich es jetzt, dass ich eine Funktion habe, der man einen string mitgibt und dann den fertigen aufgelösten string wieder zurückgibt?
Warum willst du den Tree denn überhaupt wieder in einen String auflösen? Du kannst doch jetzt wunderbar über die Struktur traversieren und die darin enthaltenen Befehle direkt ausführen.

Auf die Schnelle aus dem Kopf:
Delphi-Quellcode:
procedure Execute(Node: TTreeNode);
var
  S: String;
  I, J: Integer;
begin
  S := Node.Text;
  if (S[1] = 'W') then
  begin
    for I := 1 to {Anzahl an Iterationen} do
    begin
      for J := 0 to Node.Childs.Count - 1 do
      begin
        Execute(Node.Childs[J]);
      end;
    end;
  end else if (S[1] = 'V') then
  begin
    // ..
  end else if (S[1] = 'R') then
  begin
    // ..
  end;
end;
Projekte:
- GitHub (Profil, zyantific)
- zYan Disassembler Engine ( Zydis Online, Zydis GitHub)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:21 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