Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Problem mit Pos/PosEx (https://www.delphipraxis.net/207585-problem-mit-pos-posex.html)

NoGAD 11. Apr 2021 22:46


Problem mit Pos/PosEx
 
Hallo,

durch folgenden Beitrag habe ich Hilfe im Umgang mit Pos/PosEx bekommen: https://www.delphipraxis.net/207571-...-kopieren.html

Nun habe ich ein weiteres Problem, welches für mich wieder total unlogisch erscheint.

Ich versuche aus einem Text Stellen zu entfernen, nach ähnlichem Schema wie in dem anderen Beitrag. Eigentlich sollte es durch ändern des Codes sehr leicht klappen. Aber Pos/PosEx schießt über das Ziel hinaus.


Code:
'[[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch'
Aus diesem String versuche ich
Code:
|data-sort-value="Diplomica"
zu löschen. Ich kenne aber nur die Teilstrings:
Code:
1. |data-sort-value="
2. " // das ist das zweite Gänsefüßchen
Mit folgendem Code klappt es leider nicht bei mir:

Delphi-Quellcode:
var
  sText: String;
  sRemoveText: String;
  Pos1: Integer;
  Pos2: Integer;
  Pos3: Integer;
begin

  sText := '[[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch';
  try
    while stext.Length > 0 do
    begin
      Pos1 := Pos('||data-sort-value="', stext,1);
      Pos2 := Pos('"', stext, Pos1+1 ); // oder PosEx nutzen, ist aber in meiner Version gleich
      sRemoveText := Trim(Copy(stext, Pos1, Pos2-pos1));
      Pos3 := Pos(slinebreak, sRemoveText);
      if Pos3 > 0 then
        sRemoveText := Trim(Copy(sRemoveText, 1, Pos3 - 1));

      if sRemoveText.Length = 0 then
        break;
      stext := StringReplace(stext, sRemoveText, '', [rfReplaceAll, rfIgnoreCase]);
    end;
  finally
    result := true;
  end;
Hier steht dann bei mir
Code:
'||data-sort-value="Diplomica"| [[Diplom'
in sRemoveText drin.

Ich begreife es einfach nicht.

LG Mathias


Anmerkung: Pos = PosEx seit einiger Zeit, daher steht oben nur Pos() im Code.
http://docwiki.embarcadero.com/Libra...StrUtils.PosEx (Hinweis: PosEx entspricht System.Pos.)


Die Lösung zum Problem habe ich dann doch gefunden:
https://www.delphipraxis.net/158932-...ern-chaos.html

KodeZwerg 11. Apr 2021 23:41

AW: Problem mit Pos/PosEx
 
Liste der Anhänge anzeigen (Anzahl: 1)
Delphi-Quellcode:
program Project13;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

const
  derText = '[[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch';
// |data-sort-value="" soll raus
var
  i: Integer;
  Pos1, Pos2: Integer;
  s: string;
begin
  try
    Pos1 := Pos('|data-sort-value="', derText, 1);
    Pos2 := Pos('"|', derText, Pos1 + 1) + 2;
    WriteLn(derText);
    s := Copy(derText, 1, Pos1);
    s := s + Copy(derText, Pos2, Length(derText));
    WriteLn('');
    WriteLn(s);
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Delphi.Narium 11. Apr 2021 23:42

AW: Problem mit Pos/PosEx
 
Ungefähr sowas? (nur hingedaddelt ala Delphi 7)
Delphi-Quellcode:
function GetText(sText : string; sData : String; cDelim : Char) : String;
var
  iPos1 : Integer;
  iPos2 : Integer;
  iData : Integer;
begin
  // Länge des zu entfernenen Textes zuzüglich Delimiter ermitteln:
  iData := Length(sData + cDelim);
  // '[[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch';
  // Position von ||data-sort-value=" ermitteln:
  iPos1 := Pos(sData,sText);
  // Alles hinter dieser Position plus der Länge von ||data-sort-value=" holen:
  // Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch
  sData := Copy(sText,iPos1 + ciData,Length(sText));
  // Die Position von " ermitteln:
  iPos2 := Pos(cDelim,sData);
  // Alles ab der 1. Stelle hinter dieser Postion holen:
  // | [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch
  sData := Copy(sData,iPos2 + 1,Length(sData));
  // Aus dem Ursprungstext alles vor der Positon holen:
  // '[[Hamburg]] || 2008 
  sText := Copy(sText,1,iPos1 - 1);
  // Den ersten Teil des Ursprungstexte und den hinteren Teil zusammenfügen:
  Result := sText + sData;
end;

begin
  sText := '[[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch';
  sText := GetText(sText, '||data-sort-value=','"');
end;
Sollte aus einem gegebenen Text auch andere Fragmente entfernen können.

NoGAD 12. Apr 2021 00:05

AW: Problem mit Pos/PosEx
 
Vielen Dank euch beiden!


Dennoch verstehe und erkenne ich leider meinen Fehler nicht.


LG Mathias

Delphi.Narium 12. Apr 2021 00:17

AW: Problem mit Pos/PosEx
 
Delphi-Quellcode:
    // Pos1 ist die Position des Ersten | in ||data-sort-value="
    Pos1 := Pos('||data-sort-value="', stext,1);
    // Pos1 + 1 ist die Position des Zweiten | in ||data-sort-value="
    // Damit wird Pos2 die Position des gleichen " enthalten, wie Pos1.
    Pos2 := Pos('"', stext, Pos1+1 ); // oder PosEx nutzen, ist aber in meiner Version gleich
    // Es muss aber ab der Position Pos1 + der Länge von ||data-sort-value=" + 1 weitergesucht werden.
    Pos2 := Pos('"', stext, Pos1 + Length(||data-sort-value=") + 1); // sollte funktionieren

NoGAD 12. Apr 2021 00:48

AW: Problem mit Pos/PosEx
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1486915)
Delphi-Quellcode:
    // Pos1 ist die Position des Ersten | in ||data-sort-value="
    Pos1 := Pos('||data-sort-value="', stext,1);
    // Pos1 + 1 ist die Position des Zweiten | in ||data-sort-value="
    // Damit wird Pos2 die Position des gleichen " enthalten, wie Pos1.
    Pos2 := Pos('"', stext, Pos1+1 ); // oder PosEx nutzen, ist aber in meiner Version gleich
    // Es muss aber ab der Position Pos1 + der Länge von ||data-sort-value=" + 1 weitergesucht werden.
    Pos2 := Pos('"', stext, Pos1 + Length(||data-sort-value=") + 1); // sollte funktionieren

Es klappt einfach nicht.


Ich habe nun versucht eure beiden Codes zusammenzufügen, weil ich eigentlich nicht den Text drum herum benötige, sondern den Suchtext aus dem Text entfernen möchte.

Mein eigentlicher Text ist dieser:

https://de.wikipedia.org/w/index.php...edit&section=1

Alles, was in der Textbox auf der Webseite steht, soll umgewandelt werden. Doch vorher möchte ich diese störenden Tags entfernen.

Delphi-Quellcode:
function GetText(var stext: string; SearchTextA, SearchTextB: String; var Dummy_StringList: TStringList): boolean;
var
  Pos1: Integer;
  Pos2: Integer;
  Data: Integer;

  Dummy_String: String;
begin

  try
    while (Length(stext) > 0) and (stext <> SearchTextA) do
    begin
      Pos1 := Pos(SearchTextA, stext, 1);
      Pos2 := Pos(SearchTextB, stext, Pos1 + 1) + Length(SearchTextA);

      Dummy_String := Copy(stext, Pos1, Pos2); // Hier sollte doch nun eigentlich (z.B. data-sort-value="Diplomica" drin stehen. Tut es aber nicht, weil das zweite Suchargument (" bzw. "| nicht gefunden wurde. Der überspringt das einfach.
      Delete(stext,pos1,pos2); // das sollte bitte eigentlich auch funktionieren.. ?
      Dummy_StringList.Add( Dummy_String); // Als Test für mich, wird momentan nur im Debugger geprüft

    end;
  finally
    result := true;
  end;

end;

NoGAD 12. Apr 2021 00:58

AW: Problem mit Pos/PosEx
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier mal ein Screenshot vom Debugger.

Delphi.Narium 12. Apr 2021 01:07

AW: Problem mit Pos/PosEx
 
Mir scheint, dass diese Zeile falsch ist.
Delphi-Quellcode:
    Pos2 := Pos(SearchTextB, stext, Pos1 + 1) + Length(SearchTextA);


Die Suche muss ab Pos1 + 1 + Length(SearchTextA) beginnen.
Delphi-Quellcode:
    Pos2 := Pos(SearchTextB, stext, Pos1 + 1 + Length(SearchTextA));


Die Längenermittlung vor den Beginn der zweiten Suche muss mit in den Funktionaufruf von Pos und nicht zum Ergebnis der zweiten Pos addiert werden.

Es ist letztlich ein Problem der Klammersetzung.

NoGAD 12. Apr 2021 01:10

AW: Problem mit Pos/PosEx
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1486919)
Es ist letztlich ein Problem der Klammersetzung.


Leider war das nicht die Lösung. Dummy_String ändert sich trotzdem nicht.

Ich geh erstmal ins Bett. :(

LG Mathias

KodeZwerg 12. Apr 2021 01:25

AW: Problem mit Pos/PosEx
 
Hatte mir Deinen Code nicht angeschaut, nur gelesen was das Ziel war.
Mein code funktioniert bei mir mit Deiner Vorgabe.

Wenn sich die Vorgabe geändert hat, muss der Code auch geändert werden.

Wo liegt das problem nochmal? Bin vielleicht nur zu müde und hab die entscheiden Stelle überlesen.

KodeZwerg 12. Apr 2021 01:53

AW: Problem mit Pos/PosEx
 
Vielleicht so besser?
Delphi-Quellcode:
program Project13;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

const
  derText = '[[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch';
// |data-sort-value="" soll raus
var
  sArr: TArray<string>;
  cArr: array[0..0] of Char;
  i: Integer;
  s: string;
begin
  try
    cArr[0] := '|';
    sArr := derText.Split(cArr);
    for i := Low(sArr) to High(sArr) do
      if Pos('data-sort-value', sArr[i], 1) = 0 then
        s := s + sArr[i] + '|';
    s := Copy(s, 1, Length(s) - 1);
    WriteLn(s);
    ReadLn;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.
Ergebnis ist wie aus Post #2

Delphi.Narium 12. Apr 2021 01:54

AW: Problem mit Pos/PosEx
 
Hier mal ein PascalScript, dass mit den Daten von Wikipedia (wie mir scheint) funktioniert:
Delphi-Quellcode:
program Test;

function DeleteSearchText(sText, sSearchTextA, sSearchTextB : String) : String;
var
  iPos1 : Integer;
  iPos2 : Integer;
  iLenA : Integer;
  iLenB : Integer;
begin
  iLenA := Length(sSearchTextA);
  iLenB := Length(sSearchTextB);
  while Pos(sSearchTextA,sText) > 0 do begin
    iPos1  := Pos(sSearchTextA,sText);
    iPos2  := PosEx(sSearchTextB,sText,iPos1 + iLenA);
    sText := Copy(sText,1,iPos1 - 1) + Copy(sText,iPos2 + 1,Length(sText));
  end;
  Result := sText;
end;

var
  i    : Integer;
begin
  for i := 0 to Editor.Count - 1 do begin
    WriteLn(DeleteSearchText(Editor[i],'data-sort-value="','"'));
  end;
end.
Editor ist 'ne Stringliste, in die ich den fraglichen Inhalt der Seite https://de.wikipedia.org/w/index.php...edit&section=1 per Copy&Paste eingefügt habe.
Code:
aus

|style="border-style:none; text-align:center;" data-sort-value="A!"|

wird

|style="border-style:none; text-align:center;" |

aus

| [[Acabus Verlag|ACABUS Verlag]] || [[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch

wird

| [[Acabus Verlag|ACABUS Verlag]] || [[Hamburg]] || 2008 ||| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch

aus

|data-sort-value="Krüger"| [[Bücher Krüger]] || Dortmund || 1833 ||data-sort-value="2009"| † 2009 ||

wird

|| [[Bücher Krüger]] || Dortmund || 1833 ||| † 2009 ||

KodeZwerg 12. Apr 2021 01:58

AW: Problem mit Pos/PosEx
 
lol, heut haben wir es ja echt miteinander @Delphi.Narium

post #2 und #3 nur paar sekunden getrennt und nun schon wieder *lach*

Gute Nacht :-)

himitsu 12. Apr 2021 09:35

AW: Problem mit Pos/PosEx
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1486919)
Mir scheint, dass diese Zeile falsch ist.
Delphi-Quellcode:
    Pos2 := Pos(SearchTextB, stext, Pos1 + 1) + Length(SearchTextA);


Die Suche muss ab Pos1 + 1 + Length(SearchTextA) beginnen.
Delphi-Quellcode:
    Pos2 := Pos(SearchTextB, stext, Pos1 + 1 + Length(SearchTextA));


Die Längenermittlung vor den Beginn der zweiten Suche muss mit in den Funktionaufruf von Pos und nicht zum Ergebnis der zweiten Pos addiert werden.

Es ist letztlich ein Problem der Klammersetzung.

Um das genauer zu erklären,
mit Pos1+1 findet das zweite Pos/PosEx natürlich das " im ersten Suchstring,
darum muß die zweite Suche
auch hinter dem ersten Suchstring begonnen werden.

Wenn der zweite Suchstring nicht im Ersten vorkäme, ware es egal. (man könnte die zweite Suche also an der selben Position beginnen, wie die Erste, auch wenn es sinnlos wäre, aber zumindestens paar Byte Code sparen täte)
z.B. nach
Delphi-Quellcode:
'"|'
suchen

NoGAD 12. Apr 2021 11:12

AW: Problem mit Pos/PosEx
 
Vielen Dank an euch alle!


Die Erklärungen sind (augenscheinlich) ja richtig. Weiterhin verstehe ich dennoch nicht, was der Fehler an meinem Gedankengang war:

Delphi-Quellcode:
var
  stext: string;
  SearchTextA, SearchTextB: String;
  Dummy_String: String;
  Pos1, Pos2: Integer;
begin
  stext := '|-' +
    '| [[A1 Verlag]] || München || 1990 ||2017, Tätigkeit eingestellt' +
    '| Belletristik, Sachbuch' +
    '|-' +
    '| [[Abenteuer Medien Verlag]] || Hamburg || 1993 || || Phantastik, Fantasyspiele' +
    '|-' +
    '| [[Acabus Verlag|ACABUS Verlag]] || [[Hamburg]] || 2008 ||data-sort-value="Diplomica"| [[Diplomica Verlag|Verlagsgruppe Diplomica]] || Belletristik, Sachbuch' +
    '|-' +
    '| [[Achterbahn (Verlag)|Achterbahn]] || [[Kiel]] || 1991 || 2003 Lappan Verlag, Oldenburg (nach Insolvenz) || Comics' +
    '|-';

  SearchTextA := 'data-sort-value="';
  SearchTextB := '"|';

  Pos1 := Pos(SearchTextA, stext, 1);
  Pos2 := Pos(SearchTextB, stext, Pos1 + 1 + Length(SearchTextA)) + Length(SearchTextB);

  Dummy_String := Copy(stext, Pos1, Pos2);
  showmessage(Dummy_String);
In diesem Beispiel sollte doch Dummy_String die Zeichenkette data-sort-value="Diplomica"| beeinhalten.

Aber probiert es selbst aus.


Ich versuche den Fehler zu finden. Oder muss ich meine Logik anpassen?

LG Mathias

Delphi.Narium 12. Apr 2021 11:33

AW: Problem mit Pos/PosEx
 
Der zweite Fehler ist hier:
Delphi-Quellcode:
Dummy_String := Copy(stext, Pos1, Pos2);


Pos1 ist der Beginn von SearchTextA.
Pos2 ist die Länge von SearchTextA zuzüglich der Länge von SearchTextB.

Nun gehst Du her und kopierst genau diesen Teil aus sText. Damit erhälst Du dann SearchTextA + SearchTextB als einen String.

Du möchtest aber alles vor SearchTextA und alles hinter SearchTextB.

Von daher musst Du zuerst den Teilstring vor Pos1 und dann den Teiltring hinter Pos2 kopieren.

Delphi-Quellcode:
Dummy_String := Copy(stext, 1, Pos1 - 1) + Copy(stext, Pos2 + 1,Length(stext));

NoGAD 12. Apr 2021 12:22

AW: Problem mit Pos/PosEx
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1486933)
Der zweite Fehler ist hier:
Delphi-Quellcode:
Dummy_String := Copy(stext, Pos1, Pos2);
[..]
Nun gehst Du her und kopierst genau diesen Teil aus sText. Damit erhälst Du dann SearchTextA + SearchTextB als einen String.


Nur nochmal zur Rekapitulation (ich begreife es einfach nicht).
Pos/PosEx suchen beide nach Vorkommen.

Bei der ersten Suche wird korrekt aus einem Text das erste Vorkommen gefunden. Basis ist hier der Textbeginn.
Bei der zweiten Suche möchte ein Vorkommen gefunden werden, aber erst nach der Position der ersten Suche. Suchbasis ist NICHT der Textbeginn, sondern die Position der ersten Suche.

Delphi-Quellcode:
var
  StringA: String;
  Pos1, Pos2: Integer;
  Dummy_String: String;
begin

  StringA := 'ABCDEFGHJK';
  Pos1 := Pos('DE', StringA, 1); // Pos1 ist korrekt VOR der 4. Stelle
  Pos2 := Pos('G', StringA, Pos1); // Pos2 ist wie gewünscht VOR der 7. Stelle
  Dummy_String := Copy(StringA, Pos1, Pos2); // enthält DEFGHJK; sollte aber eigentlich DEF beinhalten

  Pos2 := Pos('G', StringA, Pos1) - Pos1; // Pos2 ist wie gewünscht an Position 7 - 4
  Dummy_String := Copy(StringA, Pos1, Pos2); // enthält endlich DEF

  showmessage(Dummy_String);

end;
Ich glaube, ich habe es nun doch endlich verstanden. Mein Fehler war immer, dass ich vom Basistext ausgegangen bin, also Pos1 und Pos2 immer vom Anfang des Textes verstanden haben wollte. Im Endeffekt ist es ja auch korrekt so. Die Positionen stimme ja überein, jedoch ist dann Copy nicht darauf aus, zweimal vom Anfang des Textes zu suchen, sondern nur einmal und im Anschluss nur die Anzahl der zu kopierenden Zeichen. Somit war es ein logischer Fehler meinerseits.

Vielen lieben Dank!
Nach 20 Jahren - es ist eigentlich zum Schämen - habe ich endlich verstanden, warum das nie klappen wollte, wenn ich diese und ähnliche String-Funktionen nutzen wollte.

Liebe Grüße
Mathias

KodeZwerg 12. Apr 2021 12:30

AW: Problem mit Pos/PosEx
 
ich glaube ich verstehe so langsam, es ging dir nicht um codes von delphinarium oder mir sondern dir zu erklären warum dein code kaputt ist/war.
(hier hätte man nur einen "else" einbauen brauchen um den string zu erhalten hehehe)

NoGAD 12. Apr 2021 12:39

AW: Problem mit Pos/PosEx
 
Zitat:

Zitat von KodeZwerg (Beitrag 1486936)
ich glaube ich verstehe so langsam, es ging dir nicht um codes von delphinarium oder mir sondern dir zu erklären warum dein code kaputt ist/war.


Ja. :-D


Delphi-Quellcode:
      if Pos('data-sort-value', sArr[i], 1) = 0 then
        s := s + sArr[i] + '|'
      else
        variable := sArr[i];
Meinst Du das mit else?

KodeZwerg 12. Apr 2021 12:47

AW: Problem mit Pos/PosEx
 
Zitat:

Zitat von NoGAD (Beitrag 1486937)
Delphi-Quellcode:
      if Pos('data-sort-value', sArr[i], 1) = 0 then
        s := s + sArr[i] + '|'
      else
        variable := sArr[i];
Meinst Du das mit else?

auch Ja hahahaha
frag mich nicht was schneller ist, aber das ist generischer glaube ich

freimatz 12. Apr 2021 13:55

AW: Problem mit Pos/PosEx
 
<gelöscht>


Alle Zeitangaben in WEZ +1. Es ist jetzt 00:22 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 by Thomas Breitkreuz