String in Zahlen zerlegen

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

String in Zahlen zerlegen

Beitrag von Mathias »

Gibt es eine fertige Funktion, welche Zahlen aus einem String auslesen kann ?

Oder muss ich mühsam mit Pos und Copy den String zerlegen, bevor ich die Zahlen mit Val/StrToInt/StToFloat in einen Integer/Single konvertieren kann ?

Code: Alles auswählen

1234 5678 9012
111.111 222.222 333.333


Bei dem Beispiel oben, hat es in der 1. Zeile 3 Integer und in der zweiten Zeile 3 Single.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

TBug
Beiträge: 177
Registriert: Mi 2. Sep 2015, 11:09
OS, Lazarus, FPC: Lazaurus 2.2.4 FPC 3.2.2
CPU-Target: Windows 32/64bit

Re: String in Zahlen zerlegen

Beitrag von TBug »

Mathias hat geschrieben:Oder muss ich mühsam mit Pos und Copy den String zerlegen, bevor ich die Zahlen mit Val/StrToInt/StToFloat in einen Integer/Single konvertieren kann ?

Du kannst zum Trennen der einzelnen Werte eine Stringliste benutzen und den entsprechenden Delemiter setzen und den Ausgangsstring der Property Text zuweisen.
Danach hast Du alle "Zahlen-Strings" einzeln und kannst sie bequem durchlaufen und in den gewünschten Typ umwandeln.


.

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

Re: String in Zahlen zerlegen

Beitrag von Mathias »

Habe folgenden Test probiert, aber bei Count kommt 1, und sl[0] beinhaltet den ganzen String.
Muss ich noch etwas aufrufen, das sl die Strings trennt ?

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
const
  s = '123 456 678 901';
var
  sl: TStringList;
begin
  sl := TStringList.Create;
  sl.Text := s;
  sl.Delimiter := ' ';
  ShowMessage(IntToStr(sl.Count));
  ShowMessage(sl[0]);
  sl.Free;
end;   
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

Achtzig
Beiträge: 90
Registriert: Mo 15. Okt 2007, 13:09
OS, Lazarus, FPC: Debian
CPU-Target: xxBit

Re: String in Zahlen zerlegen

Beitrag von Achtzig »

Du müstest erst den Delimiter setzen und dann DelimitedText anstatt Text verwenden:

Code: Alles auswählen

 
  sl.Delimiter := ' ';
  sl.DelimitedText := s;
 

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

Re: String in Zahlen zerlegen

Beitrag von Mathias »

Danke, jetzt geht's.
TStringList ist ja ein richtig mächtiges Werkzeug. :shock:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
const
  s = '123 456 678 901';
var
  sl: TStringList;
begin
  sl := TStringList.Create;
  sl.Delimiter := ' ';
  sl.DelimitedText := s;
  ShowMessage(IntToStr(sl.Count));
  ShowMessage(sl[0]);
  sl.Free;
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

marcov
Beiträge: 1100
Registriert: Di 5. Aug 2008, 09:37
OS, Lazarus, FPC: Windows ,Linux,FreeBSD,Dos (L trunk FPC trunk)
CPU-Target: 32/64,PPC(+64), ARM
Wohnort: Eindhoven (Niederlande)

Re: String in Zahlen zerlegen

Beitrag von marcov »

Ein anderer Anflug:

Code: Alles auswählen

var s : string;
    i,j,k : integer;
    ri,rj,rk : real;
 
begin
 s:='1234 5678 9012';
 readstr(s,i,j,k);
 writeln(i,'-',j,'-',k);
 
 s:='111.111 222.222 333.333'; rk:=10;
 readstr(s,ri,rj,rk);
 writeln(ri:7:3,'-',rj:7:3,'-',rk:7:3);
end.


Wenn man versucht mehr Variablen zu lesen dan drin sein, werden diejenige Variablen auf 0 gesetzt.

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

Re: String in Zahlen zerlegen

Beitrag von Mathias »

Dies ist sicher eine gute Variante, nur ist bei mir die Anzahl der Zahlen im String unbekannt, und es kann auch eine "0" im String sein, somit eignet sich im meinem Fall die Lösung mit TStringList besser.

Trotzdem Danke!
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: String in Zahlen zerlegen

Beitrag von theo »

Mathias hat geschrieben:Oder muss ich mühsam mit Pos und Copy den String zerlegen,

Nein, das muss man sowieso nicht. Das Ganze ist eine einfache Fingerübung, die man auch mit ganz wenig nachdenken lösen kann. :wink:

Code: Alles auswählen

 
var
  s, buf: string;
  i: integer;
begin
  s := '111.111 222.222 333.333';
  buf := '';
  for i := 1 to length(s) do
    if (s[i] = ' ') then
    begin
      ShowMessage(buf);
      buf := '';
    end else buf := buf + s[i];
  if buf <> '' then ShowMessage(buf);
end;   


Wegen jedem Mückenschiss eine fertige Funktion zu suchen, kann ganz schön anstrengend sein. Deshalb kann man ruhig auch mal etwas selber machen. :wink:
Die Lösung mit der StringList ist allerdings schon gut.

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: String in Zahlen zerlegen

Beitrag von Michl »

:D ...ein Codecontest - ich bin dabei :D

Ich benutze gern in solchen Fällen ExtractWord

Das Ganze könnte dann z.B. so aussehen:

Code: Alles auswählen

uses ..., StrUtils;
...
var
  s, buf: string;
  i: integer;
begin
  s := '111.111 222.222 333.333';
  for i := 1 to Length(s) do
  begin
    buf := ExtractWord(i, s, [' ']);
    if Length(buf) > 0 then
      ShowMessage(buf)
    else
      Break;
  end;
end

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

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

Re: String in Zahlen zerlegen

Beitrag von theo »

Michl hat geschrieben::D ...ein Codecontest - ich bin dabei :D


Du verwendest aber eine vorgefertigte Funktion. Das zählt nicht. :mrgreen:

Michl
Beiträge: 2505
Registriert: Di 19. Jun 2012, 12:54

Re: String in Zahlen zerlegen

Beitrag von Michl »

theo hat geschrieben:Du verwendest aber eine vorgefertigte Funktion. Das zählt nicht. :mrgreen:
:oops: Das wusste ich nicht. Bin ich nun disqualifiziert oder habe ich noch einen Versuch?

Vielleicht nicht so schön, wie der vorherige Versuch, dafür verdiene ich mir doch bestimmt einen Extrapunkt für die Rekursion?! :mrgreen:

Code: Alles auswählen

procedure TForm1.Button1Click(Sender: TObject);
begin
  ExtractRecursive('111.111 222.222 333.333');
end;
 
procedure TForm1.ExtractRecursive(const s: String);
var
  buf: string;
  i: Integer;
begin
  i := 1;
  buf := '';
  while (i <= Length(s)) and (s[i] <> ' ') do
  begin
    buf := buf + s[i];
    inc(i);
  end;
  if Length(buf) > 0 then
    ShowMessage(buf);
  if i > Length(s) then Exit;
  ExtractRecursive(Copy(s, i + 1, Length(s)));
end;
 

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection; 

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

Re: String in Zahlen zerlegen

Beitrag von theo »

Michl hat geschrieben:
theo hat geschrieben:Du verwendest aber eine vorgefertigte Funktion. Das zählt nicht. :mrgreen:
:oops: Das wusste ich nicht. Bin ich nun disqualifiziert oder habe ich noch einen Versuch?

Meinetwegen. Eine Variante mit PChar wäre auch schön.

buf := buf + s[i] könnte man auch schöner machen bzgl. Speicher Reservierung.

Assembler muss nicht, aber kann!! :mrgreen:

Nö, ich wollte dem OP eigentlich nur zeigen, dass es einfach ist und kein Copy/Pos benötigt.

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

Re: String in Zahlen zerlegen

Beitrag von Mathias »

So sieht nun die fertige Function aus:

Code: Alles auswählen

  function getInt(ins: ansistring): TIntArray;
  var
    i: integer;
    sl: TStringList;
  begin
    sl := TStringList.Create;
    sl.Delimiter := ' ';
    sl.DelimitedText := ins;
 
    SetLength(Result, sl.Count);
    for i := 0 to sl.Count - 1 do begin
      Result[i] := StrToInt(sl[i]);
    end;
 
    sl.Free;
  end;


Soviel ich wies, ist buf := buf + s[i] sher Rechenintensiv.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

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

Re: String in Zahlen zerlegen

Beitrag von theo »

Mathias hat geschrieben:Soviel ich wies, ist buf := buf + s[i] sher Rechenintensiv.


Naja, es wird ein bisschen Speicher reserviert. Ob TStringList als "Black Box" benutzt wirklich effizienter ist, weisst du nicht.

tryunderror
Beiträge: 57
Registriert: Di 9. Okt 2012, 17:32

Re: String in Zahlen zerlegen

Beitrag von tryunderror »

Mathias hat geschrieben:Gibt es eine fertige Funktion, welche Zahlen aus einem String auslesen kann ?

Oder muss ich mühsam mit Pos und Copy den String zerlegen, bevor ich die Zahlen mit Val/StrToInt/StToFloat in einen Integer/Single konvertieren kann ?

Code: Alles auswählen

1234 5678 9012
111.111 222.222 333.333


Bei dem Beispiel oben, hat es in der 1. Zeile 3 Integer und in der zweiten Zeile 3 Single.


Ich mische mal ein mit ganz anderen Argumenten. Warum Prozeduren im Alltag benutzen wie TStringList.Create.

Wenn man im Alltag zb mit Texten und Zahlen und Konvertierung zu tun hat
dann schreibt man doch mit einfachen Pascal Prozeduren sich selbst die Tools mit zb ord(ch) zum Integerwert. Erstens kenne ich dann die Befehle und kann besser absichern mit Abfragen als ein fremdes Tool.

Antworten