Pos mit mehreren Funden.

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Pos mit mehreren Funden.

Beitrag von Mathias »

Ich suche eine Funktion, welche in einem String alle Vorkommen von substr findet und die Positionen in ein Array abspeichert.
Gibt es eine fertige Function, welche diese Arbeit macht ?
Bevor ich selbst eine schreibe.

Code: Alles auswählen

const
  s = '123-23-45-123';
type
  TIntegers = array of integer;
var
  Funde: TIntegers;

  function FindStrings(const substr, s: string): TIntegers;
  begin
    Result := [4, 7, 10]; // Nur als Pseudo
  end;

begin
  Funde := FindStrings('-', s);
  WriteLn(Length(Funde));
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10500
Registriert: Mo 11. Sep 2006, 19:01

Re: Pos mit mehreren Funden.

Beitrag von theo »

Kann man bestimmt mit Posex umsetzen:
https://www.freepascal.org/docs-html/rt ... posex.html

RegEx ginge wohl auch.

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 170
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Pos mit mehreren Funden.

Beitrag von Jorg3000 »

Moin!
Mein Vorschlag:

Code: Alles auswählen

type
  TIntegers = array of SizeInt;


function FindStrings(const substr, s: string): TIntegers;
var
     p, ArrLen, SubLen: SizeInt;
label
     Loop;
begin
  Result:=[];
  ArrLen:=0;
  SubLen:=Length(substr);
  p:=1;

  Loop:
    p:=Pos(substr,s,p);
    if p<=0 then Exit;

    inc(ArrLen);
    SetLength(Result,ArrLen);
    Result[ArrLen-1]:=p;

    inc(p,SubLen);
  Goto Loop;
end;
Grüße, Jörg

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Pos mit mehreren Funden.

Beitrag von kirchfritz »

Ein Beispielprogramm mit "GOTO"??????????????
Ich dachte "GOTO" ist verpönt und sollte heutzutage nicht mehr verwendet werden, wenn ich mich nicht irre?

Benutzeravatar
Jorg3000
Lazarusforum e. V.
Beiträge: 170
Registriert: So 10. Okt 2021, 10:24
OS, Lazarus, FPC: Win64
Wohnort: NRW

Re: Pos mit mehreren Funden.

Beitrag von Jorg3000 »

Hihi, auf einen Goto-Kommentar habe gewartet.
Ich finde, Goto ist hier die pragmatischte Lösung - unter der Voraussetzung, dass es alleinig in einer kleinen übersichtlichen Funktion vorkommt, die auf einen Blick zu erfassen ist.
Würde Pascal eine Schleifensyntax anbieten, die hier ohne zwei Abbruchbedingungen auskommen würde, würde ich ich sie nehmen. Gibt es meines Wissens aber nicht.

Man kann es einfach durch Repeat ... until false; ersetzen, wenn man möchte.
Ich weiß nicht, ob der Compiler bei "until false" wirklich eine Prüfung durchführt oder vielleicht sogar für diesen Fall optimiert ist.
Ach ja. eigentlich spielt es bzgl. der Geschwindigkeit wahrscheinlich keine Rolle.

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Pos mit mehreren Funden.

Beitrag von Mathias »

Ich war gestern wohl ein bisschen müde, es geht sehr einfach,

Code: Alles auswählen

{$modeswitch arrayoperators on}
uses
  SysUtils;
const
  s = '(123,abc,456,def)'; 
type
  TIntegers = array of integer;
var
   Funde: TIntegers;
  
  function FindStrings(s: string): TIntegers;
  var
    i: integer;
  begin
    Result := [];
    for i := 1 to Length(s) do begin
      if s[i] in ['(', ',', ')'] then begin
        Result += [i];
      end;
    end;
  end;   
  
  Funde := FindStrings(s);
  WriteLn(Length(Funde));    
Oder noch viel einfacher, da habe ich sogar schon die einzelnen Strings fertig.

Code: Alles auswählen

  sa := s.Split('(,)');  
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: Pos mit mehreren Funden.

Beitrag von Mathias »

Ich dachte "GOTO" ist verpönt und sollte heutzutage nicht mehr verwendet werden, wenn ich mich nicht irre?
Ich war auch schon in Situationen, da ich keine Alternative zu GOTO fand. Ansonsten ein typischer GW-BASIC Befehl.
Auch in Assembler findet man es viel als "jmp".
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Benutzeravatar
theo
Beiträge: 10500
Registriert: Mo 11. Sep 2006, 19:01

Re: Pos mit mehreren Funden.

Beitrag von theo »

Mathias hat geschrieben:
Di 19. Mär 2024, 08:22
Ich war gestern wohl ein bisschen müde, es geht sehr einfach,
Vor allem war/ist deine Frage/Titel komplett irreführend.
Du suchst nach Char nicht nach Substring. "Pos" hat damit nichts zu tun.
Jorg3000 hat geschrieben:
Di 19. Mär 2024, 07:17
Würde Pascal eine Schleifensyntax anbieten, die hier ohne zwei Abbruchbedingungen auskommen würde, würde ich ich sie nehmen. Gibt es meines Wissens aber nicht.

Man kann es einfach durch Repeat ... until false; ersetzen, wenn man möchte.
Ich bevorzuge in diesem Fall while true do... , wenn es wirklich notwendig ist.
Da sieht man von Anfang an worum es geht und dass irgendwo ein break folgen muss. Man wundert sich dann nicht über den Abbruch mit break (oder exit), bevor man "until false" gesehen hat.

Benutzeravatar
m.fuchs
Lazarusforum e. V.
Beiträge: 2641
Registriert: Fr 22. Sep 2006, 19:32
OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
CPU-Target: x86, x64, arm
Wohnort: Berlin
Kontaktdaten:

Re: Pos mit mehreren Funden.

Beitrag von m.fuchs »

kirchfritz hat geschrieben:
Di 19. Mär 2024, 06:56
Ich dachte "GOTO" ist verpönt und sollte heutzutage nicht mehr verwendet werden, wenn ich mich nicht irre?
marcov hat in einer anderen Diskussion dazu gesagt:

Man darf GOTO nutzen - man muss aber einen Aufsatz von einer A4-Seite Länge schreiben, warum es an dieser Stelle unbedingt nötig ist.

Mit dieser Nebenbedingung kann man aus meiner Sicht dann auch GOTO einsetzen.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de

kirchfritz
Beiträge: 172
Registriert: Mo 3. Jan 2011, 13:34
OS, Lazarus, FPC: Win10 (L 3.0 FPC 3.2.2)
CPU-Target: 64Bit
Wohnort: Nürnberg

Re: Pos mit mehreren Funden.

Beitrag von kirchfritz »

Ich biete folgende Lösung an:

Code: Alles auswählen

program Project1;

uses SysUtils;

var s: String;
    res : TStringArray;
    i : integer;

begin
  s := 'abcdef-ghi-jkl';
  res := s.Split('-');
  for i := 0 to high(res) do
    writeln(res[i]);
  readln;
end.


Warf
Beiträge: 1913
Registriert: Di 23. Sep 2014, 17:46
OS, Lazarus, FPC: Win10 | Linux
CPU-Target: x86_64

Re: Pos mit mehreren Funden.

Beitrag von Warf »

Das wäre eine einfache Lösung:

Code: Alles auswählen

function FindStrings(const substr, s: string): TIntegers;
var
  SearchIndex: SizeInt = 0;
begin
  Result := [];
  if substr.IsEmpty then
    Exit;
  while SearchIndex < s.Length-substr.Length do
  begin
    SearchIndex := s.IndexOf(substr, SearchIndex);
    if SearchIndex < 0 then
      Exit;
    Result += [SearchIndex];
    SearchIndex += substr.Length;
  end;
end;
Oder als Iterator:

Code: Alles auswählen

{$ModeSwitch advancedrecords}

uses
  SysUtils;

type
  TFindIterator = record
  private
    SearchPos: SizeInt;
    SearchString: String;
    DataString: String;
  public
    function MoveNext: Boolean; inline;
    property Current: SizeInt read SearchPos;
    function GetEnumerator: TFindIterator;
  end;

function TFindIterator.MoveNext: Boolean;
begin
  if SearchPos<0 then
    SearchPos := 0
  else
    SearchPos += SearchString.Length;
  SearchPos := DataString.IndexOf(SearchString, SearchPos);
  Result := SearchPos >= 0;
end;

function TFindIterator.GetEnumerator: TFindIterator;
begin
  Result := Self;
end;

function FindStrings(const substr, s: String): TFindIterator;
begin
  Result.SearchPos:=-1;
  Result.SearchString:=substr;
  Result.DataString:=s;
end;

var
  i: Integer;
begin
  for i in FindStrings('--', '123--23--45--123') do
    WriteLn(i);
end.

BeniBela
Beiträge: 309
Registriert: Sa 21. Mär 2009, 17:31
OS, Lazarus, FPC: Linux (Lazarus SVN, FPC 2.4)
CPU-Target: 64 Bit

Re: Pos mit mehreren Funden.

Beitrag von BeniBela »

Mathias hat geschrieben:
Di 19. Mär 2024, 08:22

Oder noch viel einfacher, da habe ich sogar schon die einzelnen Strings fertig.

Code: Alles auswählen

  sa := s.Split('(,)');  
das ist doch was ganz anderes als Pos

Sowas habe ich auch schon mal programmiert

PascalDragon
Beiträge: 834
Registriert: Mi 3. Jun 2020, 07:18
OS, Lazarus, FPC: L 2.0.8, FPC Trunk, OS Win/Linux
CPU-Target: Aarch64 bis Z80 ;)
Wohnort: München

Re: Pos mit mehreren Funden.

Beitrag von PascalDragon »

Mathias hat geschrieben:
Di 19. Mär 2024, 08:25
Auch in Assembler findet man es viel als "jmp".
In Assembler ginge auch vieles nicht ohne JMP oder ähnliches und viele Hochsprachen Features sind letztlich als irgendwie geartete Sprünge implementiert (Schleifen, Bedingungen, etc.).
FPC Compiler Entwickler

Antworten