Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi pos von hinten (https://www.delphipraxis.net/105585-pos-von-hinten.html)

qb-tim 25. Dez 2007 12:28


pos von hinten
 
Hi,

ich möchte einen Substring in einem String suchen, und zwar von HINTEN. d.h: PosHinten('a', 'abcabc') => 4 und nicht 1

Gibt es so eine Funktion?

rollstuhlfahrer 25. Dez 2007 12:52

Re: pos von hinten
 
geht doch ganz leicht:
Man nimmt die Länge und zieht davon die Position von vorne ab.

Delphi-Quellcode:
str := 'aabbccddee';
Poshi := Length(str) - Pos('b', str);
rollstuhlfahrer

PS: Code nicht getestet, evt. +/- 1 noch hinzufügen

qb-tim 25. Dez 2007 13:00

Re: pos von hinten
 
ich meine nicht die Position von hinten gezählt, sonder die Position des ersten SubStr von hinten:

Delphi-Quellcode:
s := 'hallo ich heiße albert'
PosHinten('a', s) // => 15 und nicht 2

ErazerZ 25. Dez 2007 13:02

Re: pos von hinten
 
Delphi-Quellcode:
function MyPosEx(const SubStr, s: string; Index: Integer = 1; Upwards: Boolean = False): Integer;
var
  i, intSubStrLen: Integer;
begin
  Result := 0;
  if (Index < 1) then Exit;
  if Upwards then
  begin
    intSubStrLen := Length(SubStr);
    if (Index >= Length(s)) then Exit;
    if (intSubStrLen < 1) then Exit;
    for i := Index to Length(s) do
    begin
      if (Copy(s, I, intSubStrLen) = SubStr) then
      begin
        Result := I;
        Exit;
      end;
    end;
  end else
  begin
    intSubStrLen := Length(SubStr);
    if (intSubStrLen < 1) then Exit;
    for i := Length(s) +1 downto Index do
    begin
      if (I - intSubStrLen < 1) then Exit;
      if (Copy(s, I - intSubStrLen, intSubStrLen) = SubStr) then
      begin
        Result := I - intSubStrLen;
        Exit;
      end;
    end;
  end;
end;


procedure TForm1.FormCreate(Sender: TObject);
const
  s = 'abcdefghijklmnopqrstuvwxyz';
  c = 'bc';
begin
  ShowMessage(Format('MyPosEx of c: %d' + #13#10 + 'MyPosEx of c (down): %d' + #13#10 + 'Pos of c: %d', [
            MyPosEx(c, s, 1, True), MyPosEx(c, s), Pos(c, s)]));

end;
Quickedit: sorry es müsste "for i := Length(s) +1 downto Index do" heißen und nicht "for i := Length(s) downto Index do". Jetzt funktioniert es wieder.

alzaimar 25. Dez 2007 13:25

Re: pos von hinten
 
Hier hat Amateurprofi eine wirklich verdammt schnelle Version geschrieben, die auch Rückwärts suchen kann.

Such mal hier und dann weiter unten nach dem Attachment 'Test_02.pas'.

Mondengel 3. Nov 2010 12:46

AW: pos von hinten
 
Ist mir klar das das wahrscheinlich nicht mehr gebraucht wird :roll:,
schreib aber für alle die das gleiche Problem haben ^^.

Hab einen kleinen aber schnellen Quellcode

Delphi-Quellcode:
uses StrUtils

function PosR(Substr, s : String) : Integer;
var
  rStr : string;
begin
  rStr := reverseString(s);
  result := Pos( reverseString(SubStr), reverseString(s));

  if( 0 <> result) then
  begin
    result := length(S)-result-Length(SubStr)+2;
  end;
end;
kurz und funktioniert :)
Bye :cheer:

DeddyH 3. Nov 2010 12:54

AW: pos von hinten
 
Wozu ist rStr da, wenn es nicht benutzt wird? Sagt Dein Compiler nichts dazu?

Namenloser 3. Nov 2010 12:56

AW: pos von hinten
 
Klein ist er, ja, aber schnell mit Sicherheit nicht. Hier wird ja erstmal der komplette String umgedreht und dann noch die Suche durchgeführt. Noch schlimmer: Er wird nicht nur umgedreht, sondern es wird ein 2. String erzeugt, der die Umkehrung des Originals beinhaltet.

Solange es keine performancekritische Stelle ist, kannst du den Code natürlich verwenden, aber ansonsten würde ich lieber auf die optimierte Funktion zurückgreifen.

Luckie 3. Nov 2010 12:59

AW: pos von hinten
 
Und warum +2?

Mondengel 3. Nov 2010 13:01

AW: pos von hinten
 
OOOOOOOOOps :shock:

danke für den Hinweis DeddyH ich war wohl etwas zu schnell :lol:

Nartürlich brauch man rStr nicht :stupid:

Delphi-Quellcode:
uses StrUtils

function PosR(Substr, s : String) : Integer;
begin
  result := Pos(reverseString(SubStr), reverseString(s));

  if( 0 <> result) then
    result := length(S) - result - Length(SubStr) + 2;
end;
Ist besser nicht 8-)

@NameLozer
Das hab ich nicht gewusst sorry :pale:
sollt nur ein weiterer Vorschlag sein

Luckie 3. Nov 2010 13:04

AW: pos von hinten
 
Warum das +2?

Mondengel 3. Nov 2010 13:04

AW: pos von hinten
 
Zitat:

Und warum +2?
Naja einmal weil ein String bei 1 anfängt und nicht bei 0 und
weil beim Anfangsbuchstaben des Substr die Position angegeben werden soll

-187- 3. Nov 2010 17:19

AW: pos von hinten
 
Hm ich habe mir den String immer umgedreht und dann ganz normal mit Pos gearbeitet... Die Länge des Strings - Die Reversed Position+1 ist das Ergebnis :D


Delphi-Quellcode:
function String_Reverse(S:String):String;
var
  i: Integer;
begin
  Result:='';
  for i:=Length(S) downto 1 do
    begin
      Result:=Result+Copy(S,i,1);
    end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MyStr: String;
  MyPos: Integer;
begin
  MyStr:=String_Reverse(Edit1.Text);
  MyPos:=Pos('$',MyStr);
  ShowMessage('Die Position: '+IntToStr(Length(Edit1.Text)-MyPos+1));
end;
Naja wahrscheinlich hab ich mir das etwas zu kompliziert gestaltet :)

himitsu 3. Nov 2010 17:32

AW: pos von hinten
 
Zitat:

Delphi-Quellcode:
function String_Reverse(S:String):String;
var
  i: Integer;
begin
  Result:='';
  for i:=Length(S) downto 1 do
    begin
      Result:=Result+Copy(S,i,1);
    end;
end;

Also der Code ist ja extremst grausam und unperformat.
Delphi-Quellcode:
Copy(S,i,1) = S[i]
.
Und die Unmasse an String-Concationen ist sehr unperformant.

Delphi-Quellcode:
program Project5;

{$APPTYPE CONSOLE}

uses
  Windows, StrUtils;

function StringReverse_Copy(S: String): String;
var
  i: Integer;
begin
  Result := '';
  for i := Length(S) downto 1 do
    Result := Result + Copy(S, i, 1);
end;

function StringReverse_Char(S: String): String;
var
  i: Integer;
begin
  Result := '';
  for i := Length(S) downto 1 do
    Result := Result + S[i];
end;

function StringReverse_Direct(S: String): String;
var
  L, i: Integer;
begin
  L := Length(S);
  SetLength(Result, L);
  for i := L downto 1 do
    Result[i] := S[L - i + 2];
end;

var
  S, S2: String;
  C: Cardinal;
  i: Integer;

begin
  SetLength(S, 1234567);

  C := GetTickCount;
  for i := 0 to 9 do begin
    S2 := StringReverse_Copy(S);
    S2 := '';
  end;
  WriteLn(GetTickCount - C);

  C := GetTickCount;
  for i := 0 to 9 do begin
    S2 := StringReverse_Char(S);
    S2 := '';
  end;
  WriteLn(GetTickCount - C);

  C := GetTickCount;
  for i := 0 to 9 do begin
    S2 := StringReverse_Direct(S);
    S2 := '';
  end;
  WriteLn(GetTickCount - C);

  C := GetTickCount;
  for i := 0 to 9 do begin
    S2 := ReverseString(S);
    S2 := '';
  end;
  WriteLn(GetTickCount - C);

  ReadLn;
end.
Code:
2047
1296
110
47
Je länger der String, um so grausamer wird die nahezu expotentiell zur Zeichenanzahl steigene Rechenzeit.

-187- 3. Nov 2010 17:42

AW: pos von hinten
 
Ja offensichtlich nicht sehr performant :) Spielt aber auch keine große Rolle bei meinen Bastler Tools ;)

Mondengel 4. Nov 2010 08:57

AW: pos von hinten
 
Zitat:

Hm ich habe mir den String immer umgedreht und dann ganz normal mit Pos gearbeitet... Die Länge des Strings - Die Reversed Position+1 ist das Ergebnis
Funktioniert ja auch wenn es nur ein Zeichen ist, aber wenn ich mehrere Zeichen habe funktioniert der Code nicht mehr 8-)

Beispiel:
String: as9as9as0as9as9as0
Substring: as0

So nun drehst du den String und er sieht so aus
0sa9sa9sa9sa0sa9sa9sa9sa

So findet er nicht mehr as0

Darum drehe ich auch den Substring um :-D

himitsu 1. Jan 2011 21:02

AW: pos von hinten
 
Zitat:

Und warum +2?
Weil ich's grade nochmal sehe.

Die Strings sind ja 1-basierens (wie schon erwähnt)
Diese 2 sind nun zwei Mal die 1 (1+1=2, wenn man was wegkürzt) oder eher 4 Mal die 1 (1+1+1-1=2).

entweder
+1: einmal vom Pos, für die Umrechnung
+1: und das Length(SubString), um dort auf das letzte Zeichen umzurechen
Delphi-Quellcode:
Result := Length(S) - Length(SubStr) - Result + 2;
Result := Length(S) - (Length(SubStr) - 1) - (Result - 1);
also um den Index von a auf b zu verschieben
Code:
123456789
     678

987654321
 876
 a b
a = Ergebnis von Pos(...)
b = letztes Zeichen, welches nach dem Umdrehen dann das Erste ist.


oder
+1: Length(S) um den Startindex auf das letzte Zeichen zu verschieben (0-basierend)
+1: Pos(SubStr, S) auf 0-basierend umrechnen
+1: Length(SubStr) ebenfalls auf das letzte Zeichen umrechnen
-1: das Ergebnis auf 1-basierend umrechnen



so, und nun nochmal alles zusammen:

alle Delphi-Versionen (ab Delphi 2009 kein direktes ANSI verfügbar)
Delphi-Quellcode:
uses StrUtils;

function ReversePos(SubStr, S: String): Integer;
begin
  SubStr := AnsiReverseString(SubStr);
  S := AnsiReverseString(S);
  Result := Pos(SubStr, S);
  if 0 <> Result then Result := Length(S) - Length(SubStr) - Result + 2;
end;

function ReversePosEx(SubStr, S: String; Offset: Integer = 1): Integer;
begin
  SubStr := ReverseString(SubStr);
  S := ReverseString(S);
  Offset := Length(S) - Offset + 1;
  Result := PosEx(SubStr, S, Offset);
  if 0 <> Result then Result := Length(S) - Length(SubStr) - Result + 2;
end;
ab Delphi 2009
Delphi-Quellcode:
uses StrUtils, AnsiStrings;

function ReversePos(SubStr, S: String): Integer; overload;
function ReversePos(SubStr, S: AnsiString): Integer; overload;
function ReversePosEx(SubStr, S: String; Offset: Integer = 1): Integer; overload;
function ReversePosEx(SubStr, S: AnsiString; Offset: Integer = 1): Integer; overload;

implementation

function ReversePos(SubStr, S: String): Integer;
begin
  SubStr := ReverseString(SubStr);
  S := ReverseString(S);
  Result := Pos(SubStr, S);
  if 0 <> Result then Result := Length(S) - Length(SubStr) - Result + 2;
end;

function ReversePos(SubStr, S: AnsiString): Integer;
begin
  SubStr := AnsiReverseString(SubStr);
  S := AnsiReverseString(S);
  Result := Pos(SubStr, S);
  if 0 <> Result then Result := Length(S) - Length(SubStr) - Result + 2;
end;

function ReversePosEx(SubStr, S: String; Offset: Integer = 1): Integer;
begin
  SubStr := ReverseString(SubStr);
  S := ReverseString(S);
  Offset := Length(S) - Offset + 1;
  Result := PosEx(SubStr, S, Offset);
  if 0 <> Result then Result := Length(S) - Length(SubStr) - Result + 2;
end;

function ReversePosEx(SubStr, S: AnsiString; Offset: Integer = 1): Integer;
begin
  SubStr := AnsiReverseString(SubStr);
  S := AnsiReverseString(S);
  Offset := Length(S) - Offset + 1;
  Result := PosEx(SubStr, S, Offset);
  if 0 <> Result then Result := Length(S) - Length(SubStr) - Result + 2;
end;

Luckie 2. Jan 2011 08:37

AW: pos von hinten
 
Zitat:

Zitat von himitsu (Beitrag 1071689)
Zitat:

Und warum +2?
Weil ich's grade nochmal sehe.

Und genau deshalb wäre es sinnvoll daraus eine Konstante mit aussagekräftigen Bezeichner zu machen.


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