Prüfen, ob ein String einen Interger darstellt.

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut

Prüfen, ob ein String einen Interger darstellt.

Beitragvon Mathias » 22. Mär 2020, 16:01 Prüfen, ob ein String einen Interger darstellt.

Ich habe dies so gelöst:
Code: Alles auswählen
  function IsNumber(s: string): boolean;
  var
    i, er: integer;
  begin
    Val(s, i, er);
    Result := er = 0;
  end;   

Gibt es da schon etwas fertiges ?
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4488
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Ally » 22. Mär 2020, 16:13 Re: Prüfen, ob ein String einen Interger darstellt.

Hallo Mathias,

schau dir mal TryStrToInt an, das könnte sein was du suchst.

Gruß Roland
Ally
 
Beiträge: 144
Registriert: 11. Jun 2009, 08:25

Beitragvon Mathias » 22. Mär 2020, 16:42 Re: Prüfen, ob ein String einen Interger darstellt.

Danke, hat mir weiter geholfen. Spart wieder ein paar Zeilen. :wink:
Code: Alles auswählen
  if TryStrToInt(StringGrid1.Cells[ACol, ARow], i0) and TryStrToInt(StringGrid1.Cells[BCol, BRow], i1) then begin
    Result := i0 - i1;
  end else begin
    Result := CompareStr(StringGrid1.Cells[ACol, ARow], StringGrid1.Cells[BCol, BRow]);
  end;


Intern arbeitet TryStrToInt auch mit val.
Code: Alles auswählen
function TryStrToInt(const s: string; out i : Longint) : boolean;
var Error : word;
begin
  Val(s, i, Error);
  TryStrToInt:=Error=0
end;   
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4488
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Winni » 22. Mär 2020, 18:24 Re: Prüfen, ob ein String einen Interger darstellt.

Hi!

Oder ganz einfach selbst machen:
Code: Alles auswählen
 
function IsInteger(s: string) : boolean;
const digits = ['0'..'9'];
var i : integer = 1;
begin
result := true;
while result and (i<= length(s) ) do
  begin
  result := s[i] in digits;
  if result then inc(i);
  end; // while 
end;


Grüße, Winni
Winni
 
Beiträge: 78
Registriert: 2. Mär 2009, 16:45
Wohnort: Fast Dänemark
OS, Lazarus, FPC: Laz2.06, fpc 3.04 | 
CPU-Target: 64Bit
Nach oben

Beitragvon Mathias » 22. Mär 2020, 19:16 Re: Prüfen, ob ein String einen Interger darstellt.

Bringt dies bei einem PC etwas ?
Wird val und str nicht von der CPU unterstützt ?
Mit Lazarus sehe ich gün
Mit Java und C/C++ sehe ich rot
Mathias
 
Beiträge: 4488
Registriert: 2. Jan 2014, 17:21
Wohnort: Schweiz
OS, Lazarus, FPC: Linux (die neusten Trunc) | 
CPU-Target: 64Bit
Nach oben

Beitragvon Warf » 22. Mär 2020, 19:51 Re: Prüfen, ob ein String einen Interger darstellt.

Winni hat geschrieben:Hi!

Oder ganz einfach selbst machen:
Code: Alles auswählen
 function IsInteger(s: string) : boolean;
const digits = ['0'..'9'];
var i : integer = 1;
begin
result := true;
while result and (i<= length(s) ) do
  begin
  result := s[i] in digits;
  if result then inc(i);
  end; // while
end;


Grüße, Winni


Warum am ende der branch? Der verhindert das genau einmal ein unnötiges INC ausgeführt wird, die schnellste instruction die eine CPU kann, um statdessen bei jedem anderen mal einen branch und eine instruction auszuführen. Also in jedem Fall in dem nicht direkt das erste zeichen keine Zahl ist, ist es strikt schlechter, (weil ungefähr mehr instructions ausgeführt werden) und in dem Fall ersetzt du einen INC aufruf durch einen branch, was auch nicht schneller ist (vielleicht sogar langsamer)

Außerdem darf man nicht vergessen das const keinen konstanten ausdruck definiert, sondern ein objekt im Data segment des Programms (so wie static in C). Obwohl der Optimizer zwar beweisen können müsste das digits auch als konstanter ausdruck benutzt werden kann, ist das nicht unbedingt garantiert. Der Unterschied ist, wenn es ein Konstanter ausdruck ist kann der Optimizer mehr darüber beweisen, z.b. das das ein zusammenhängendes Set ist, also ein range vergleich (c<min c>max) ausreichend ist. Außerdem kann bei einem Konstanten ausdruck eine Jumping-Table benutzt werden (wie bei einem case-of ausdruck).

Daher mein Vorschlag (vor allem ist er auch kürzer und deutlich leserlicher):

Code: Alles auswählen
function IsInteger(s: string): boolean; inline;
var
  c: char;
begin
  Result := s.length > 0;
  for c in s do
    if not (c in ['0'..'9']) then
      exit(False); // oder Result := False; und break;
end;


An dieser stelle sollte der Optimizer entscheiden was die beste implementierung ist, ansonsten kann man ein case oder ein range if versuchen
Code: Alles auswählen
function IsInteger(s: string): boolean; inline;
var
  c: char;
begin
  Result := s.length > 0;
  for c in s do
    case c of
    '0'..'9':
    else:
      exit(False); // oder Result := False; und break;
    end;
end;

oder:
Code: Alles auswählen
function IsInteger(s: string): boolean; inline;
var
  c: char;
begin
  Result := s.length > 0;
  for c in s do
    if (c < '0') or (c > '9')
      exit(False); // oder Result := False; und break;
end;


Aber das sollte man dem optimizer überlassen, dafür ist er da
Warf
 
Beiträge: 1369
Registriert: 23. Sep 2014, 16:46
Wohnort: Aachen
OS, Lazarus, FPC: MacOS | Win 10 | Linux | 
CPU-Target: x86_64
Nach oben

Beitragvon six1 » 22. Mär 2020, 21:35 Re: Prüfen, ob ein String einen Interger darstellt.

strtointdef wäre auch interessant.
Gruß, Michael
six1
 
Beiträge: 155
Registriert: 1. Jul 2010, 18:01

Beitragvon Winni » 23. Mär 2020, 21:30 Re: Prüfen, ob ein String einen Interger darstellt.

Hi!

Ja, nicht immer diese langweiligen Konstanten:

BoDieGrosseZersplitterung := StrToIntDef('I Ging',23);

Winni
Winni
 
Beiträge: 78
Registriert: 2. Mär 2009, 16:45
Wohnort: Fast Dänemark
OS, Lazarus, FPC: Laz2.06, fpc 3.04 | 
CPU-Target: 64Bit
Nach oben

Beitragvon six1 » 24. Mär 2020, 07:59 Re: Prüfen, ob ein String einen Interger darstellt.

ich verwende es in der Art:

Code: Alles auswählen
 
var
  str:string;
begin
  str:='123A';
  if strtointdef( str, -1) = -1 then
   showmessage('Keine Zahl')
  else
   showmessage('Zahl: '+str);
end;
 
Gruß, Michael
six1
 
Beiträge: 155
Registriert: 1. Jul 2010, 18:01

Beitragvon m.fuchs » 24. Mär 2020, 08:48 Re: Prüfen, ob ein String einen Interger darstellt.

six1 hat geschrieben:
Code: Alles auswählen
 
  if strtointdef( str, -1) = -1 then
   showmessage('Keine Zahl')
  else
   showmessage('Zahl: '+str);
 

Was allerdings nicht korrekt ist. So ein Einsatz von magischen Konstanten wie deine -1 ist problematisch. Was machst du wenn wirklich jemand -1 eingibt?
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
Lazarusforum e. V.
 
Beiträge: 2184
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (Lazarus 2.0, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon Timm Thaler » 24. Mär 2020, 09:05 Re: Prüfen, ob ein String einen Interger darstellt.

m.fuchs hat geschrieben:Was allerdings nicht korrekt ist. So ein Einsatz von magischen Konstanten wie deine -1 ist problematisch. Was machst du wenn wirklich jemand -1 eingibt?


Dann enthält der Wert -1. ;-)

Normalerweise hat man ja einen gültigen Zahlenbereich, in dem der Wert liegen kann. Und gerade Eingaben sollte man auf diesen prüfen.

So kann man zum Beispiel definieren: cNaN16 = −32768;

Dann kann man dem Wert an Anfang temperatur := cNaN16; zuweisen, und erst wenn ein gültiger Messwert geliefert wird, wird dieser übernommen. Verarbeitet man den Messwert, dann fragt man ab ob temperatur <> cNaN16, nur dann kann man ihn verwenden. Oder Kalibrierwerte die per Uart übermittelt werden können so als gültig markiert werden. Liegen sie außerhalb des Bereiches: cal := cNaN16;

Bei AVR-Controllern, die auch weiterlaufen müssen wenn ein Sensorfehler auftritt und die nicht dem User einfach eine Fehlermeldung auf den Bildschirm klatschen können ist das schon praktisch.
Timm Thaler
 
Beiträge: 1021
Registriert: 20. Mär 2016, 22:14
OS, Lazarus, FPC: Win7-64bit Laz1.9.0 FPC3.1.1 für Win, RPi, AVR embedded | 
CPU-Target: Raspberry Pi 3
Nach oben

Beitragvon m.fuchs » 24. Mär 2020, 09:19 Re: Prüfen, ob ein String einen Interger darstellt.

Timm Thaler hat geschrieben:
m.fuchs hat geschrieben:Was allerdings nicht korrekt ist. So ein Einsatz von magischen Konstanten wie deine -1 ist problematisch. Was machst du wenn wirklich jemand -1 eingibt?

Dann enthält der Wert -1. ;-)

Nö, dann behauptet die Software "Keine Zahl". Eine Aussage die falsch ist. Und jeder Benutzer schaut auf den Bildschirm und weiß nicht mehr weiter.

Timm Thaler hat geschrieben:Normalerweise hat man ja einen gültigen Zahlenbereich, in dem der Wert liegen kann. Und gerade Eingaben sollte man auf diesen prüfen.

Vollkommen richtig. Worauf ich hinaus will: die Prüfung muss auch ein korrektes Ergebnis zurückgeben. Wenn die oben genannte Routine sagen würde "Keine positive Zahl" oder "Eingabe außerhalb des gültigen Wertebereichs" wäre ja alles in Ordnung.
Das mag jetzt etwas krümmelkackerich daherkommen, aber genau diese Art von ungenauen Fehlermeldungen führen zu Frustration bei Benutzern.
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
m.fuchs
Lazarusforum e. V.
 
Beiträge: 2184
Registriert: 22. Sep 2006, 18:32
Wohnort: Berlin
OS, Lazarus, FPC: Winux (Lazarus 2.0, FPC 3.0.4) | 
CPU-Target: x86, x64, arm
Nach oben

Beitragvon six1 » 24. Mär 2020, 14:53 Re: Prüfen, ob ein String einen Interger darstellt.

ja... man findet immer irgend etwas. Dann passt dieses Beispiel euren Gegebenheiten an.
Gruß, Michael
six1
 
Beiträge: 155
Registriert: 1. Jul 2010, 18:01

Beitragvon wp_xyz » 24. Mär 2020, 16:22 Re: Prüfen, ob ein String einen Interger darstellt.

Na dann viel Spaß beim Fehlersuchen in einem Jahr, wenn du all das hier vergessen hast und dich plötzlich wunderst, warum deine User dir empört melden, dein Programm würde die Eingabe -1 als "keine Zahl" bemängeln.
wp_xyz
 
Beiträge: 3123
Registriert: 8. Apr 2011, 08:01

Beitragvon six1 » 24. Mär 2020, 18:00 Re: Prüfen, ob ein String einen Interger darstellt.

wp_xyz hat geschrieben:Na dann viel Spaß beim Fehlersuchen in einem Jahr, wenn du all das hier vergessen hast und dich plötzlich wunderst, warum deine User dir empört melden, dein Programm würde die Eingabe -1 als "keine Zahl" bemängeln.


ja, superschlauer Einwand :roll:
Woher kennst du Interna meiner Programme?
Wenn es im jeweiligen Programm nicht passt strtointdef zu verwenden, würde ich es einfach nicht verwenden; schon mal drüber nachgedacht?

Diese Schlaumeierei ist manchmal echt schwer zu ertragen. Ein Hinweis auf mögliche Komplikationen hätte auch ausgereicht und das Problem verständlich gemacht.
Gruß, Michael
six1
 
Beiträge: 155
Registriert: 1. Jul 2010, 18:01

» Weitere Beiträge siehe nächste Seite »
Nächste

Zurück zu Freepascal



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

porpoises-institution
accuracy-worried