Delphi isNumber
Asked Answered
F

10

22

Is there a method in Delphi to check if a string is a number without raising an exception?

its for int parsing.

and an exception will raise if one use the

try
  StrToInt(s);
except
  //exception handling
end;
Folkmoot answered 3/2, 2011 at 9:22 Comment(6)
What is "infinite exceptions"?Hattiehatton
By number you mean integer? Or do you want to allow real numbers as well?Landlady
Is the number in the string required to be a number that can be stored by a Delphi numeric type? Nineteen quintillion is a number, but it won't fit in any Delphi integral type. One hundred-thousandth is a number, but no Delphi numeric type can hold it.Purposeful
@Rob Kennedy: if Application.MessageBox('Is this a number?'#13#10+str, MB_YESNO + MB_ICONQUESTION + MB_DEFBUTTON1) = IdYes then ShowMessage(str +' IS a number!') else ShowMessage('Sorry. ''+str+'' doesn't seem to be a number...');Dacoity
@Jørn, it was a serious question. I'm just trying to stave off the embarrassment of displaying a nonsense error message like "19000000000000000 is not a number."Purposeful
@Rob Kennedy: Aha (blush), I thought you meant str:='Nineteen quintillion', and not str:='19000000000000000000'... In either case, my silly solution was meant to be humorous.Dacoity
S
28
var
  s: String;
  iValue, iCode: Integer;
...
val(s, iValue, iCode);
if iCode = 0 then
  ShowMessage('s has a number')
else
  ShowMessage('s has not a number');
Sentiment answered 3/2, 2011 at 9:48 Comment(6)
The advantage of this solution is that it works for real numbers as well. For the price of being a lot harder to read than TryStrToInt. And it requires at least two local variables.Landlady
@none: TryStrToInt should be available in D7. Any reason why you accepted this solution and not the one posted by bassfriend?Landlady
@Smasher @Folkmoot TryStrToInt is in D7, as well as its friends TryStrToInt64, TryStrToBool, TryStrToFloat, TryStrToCurr, TryStrToDate, TryStrToTime and TryStrToDateTime. Seems to me that the OP has accepted the wrong answer.Hattiehatton
You should be aware that Val supports hexadecimal numbers starting with 0x or $, which may or may not be what you need. Following two lines will both put '16' into 'i'. Val('$10', i, c); Val('0x10', i, c);Dupleix
I do not like this solution because it will leave you a hint that iValue is not used.Myatt
Val('5123456789', c, k); Will return error code "10" in k, in other words, the 10th character does not fit into the integer. Keep that in mind please, val is only suited for integers not longint. Use TryStrToInt64 if you suspect the string may contain a number greater than int. However.... TryStrToInt64 only returns the first numbers until it finds a non number - so "12345abc6778" will return 12345. Which is probably not what you want either.Monomania
H
69

function TryStrToInt(const S: string; out Value: Integer): Boolean;

TryStrToInt converts the string S, which represents an integer-type number in either decimal or hexadecimal notation, into a number, which is assigned to Value. If S does not represent a valid number, TryStrToInt returns false; otherwise TryStrToInt returns true.

To accept decimal but not hexadecimal values in the input string, you may use code like this:

function TryDecimalStrToInt( const S: string; out Value: Integer): Boolean;
begin
   result := ( pos( '$', S ) = 0 ) and TryStrToInt( S, Value );
end;
Hillock answered 3/2, 2011 at 9:25 Comment(1)
TryStrToInt returns true even for xFF, not only $FF.Springing
S
28
var
  s: String;
  iValue, iCode: Integer;
...
val(s, iValue, iCode);
if iCode = 0 then
  ShowMessage('s has a number')
else
  ShowMessage('s has not a number');
Sentiment answered 3/2, 2011 at 9:48 Comment(6)
The advantage of this solution is that it works for real numbers as well. For the price of being a lot harder to read than TryStrToInt. And it requires at least two local variables.Landlady
@none: TryStrToInt should be available in D7. Any reason why you accepted this solution and not the one posted by bassfriend?Landlady
@Smasher @Folkmoot TryStrToInt is in D7, as well as its friends TryStrToInt64, TryStrToBool, TryStrToFloat, TryStrToCurr, TryStrToDate, TryStrToTime and TryStrToDateTime. Seems to me that the OP has accepted the wrong answer.Hattiehatton
You should be aware that Val supports hexadecimal numbers starting with 0x or $, which may or may not be what you need. Following two lines will both put '16' into 'i'. Val('$10', i, c); Val('0x10', i, c);Dupleix
I do not like this solution because it will leave you a hint that iValue is not used.Myatt
Val('5123456789', c, k); Will return error code "10" in k, in other words, the 10th character does not fit into the integer. Keep that in mind please, val is only suited for integers not longint. Use TryStrToInt64 if you suspect the string may contain a number greater than int. However.... TryStrToInt64 only returns the first numbers until it finds a non number - so "12345abc6778" will return 12345. Which is probably not what you want either.Monomania
H
19

Try this function StrToIntDef()

From help

Converts a string that represents an integer (decimal or hex notation) to a number with error default.

Pascal

function StrToIntDef(const S: string; Default: Integer): Integer;

Edit

Just now checked the source of TryStrToInt() function in Delphi 2007. If Delphi 7 dont have this function you can write like this. Its just a polished code to da-soft answer

function TryStrToInt(const S: string; out Value: Integer): Boolean;
var
  E: Integer;
begin
  Val(S, Value, E);
  Result := E = 0;
end;
Hendershot answered 3/2, 2011 at 9:28 Comment(7)
This is a good option IF there is an obvious default value that actually makes sense. If only used to check whether the result is -1 afterwards (for example), TryStrToInt is a lot more robust and readable.Landlady
A useful function, but not addressing the question as asked. There is no way to tell whether or not the input was a number.Hattiehatton
@David: Yes you are correct but i just want to suggest an alternative which will help the user to set some default value alsoHendershot
understood, I was just making the point for the benefit of the OP so that he was aware of the issueHattiehatton
@David: There is a possibility. A string test contains a valid integer number iff StrToIntDef(test,-1) = StrToIntDef(test,0), accompanied by the test for leading '$' chars. I would not advocate that solution, but it is possible.Ethelinda
StrToInt / StrToIntDef can not handle longint though. Can it?Monomania
@Hendershot Delphi 7 does have TryStrToInt()Mozellamozelle
J
10

XE4 and newer:

for ch in s do
   TCharacter.IsNumber(ch);

Don't forget:

uses System.Character    
Jog answered 2/12, 2016 at 18:32 Comment(1)
Of course: this fails on negative numbers and those with a leading +. I'm surprised how many answers don't think of negative numbers.Squarerigged
C
3

In delphi 7 you can use the Val procedure. From the help:

Unit: System Delphi syntax: procedure Val(S; var V; var Code: Integer);

S is a string-type expression; it must be a sequence of characters that form a signed real number.

V is an integer-type or real-type variable. If V is an integer-type variable, S must form a whole number.

Code is a variable of type Integer.

If the string is invalid, the index of the offending character is stored in Code; otherwise, Code is set to zero. For a null-terminated string, the error position returned in Code is one larger than the actual zero-based index of the character in error.

Confederation answered 31/7, 2012 at 7:24 Comment(0)
M
3

use this function

function IsNumber(N : String) : Boolean;
var
I : Integer;
begin
Result := True;
if Trim(N) = '' then
 Exit(False);

if (Length(Trim(N)) > 1) and (Trim(N)[1] = '0') then
Exit(False);

for I := 1 to Length(N) do
begin
 if not (N[I] in ['0'..'9']) then
  begin
   Result := False;
   Break;
 end;
end;

end;

Monaghan answered 26/4, 2017 at 12:44 Comment(3)
Awful: why using Trim() when still checking every character? Why using Break and not Exit as previously? Why not setting Result := True at the end and assume failure from the very start? It also doesn't allow negative Integers or Integers with a leading +, which is legal and must be expected. The bad indention and post formatting fit the code quality.Squarerigged
Result:= True is in the first line, Trim() is useful if we have much white space at the beginning and end and for the positive and negative signs you must develop the function .. @SquareriggedMonaghan
Trim() is not useful at all (especially done again and again) when a check would already fail at the first character. Only the end needs true while multiple other options all result in false, hence setting the former as default is more logical. "You must develop the function" could have been the intro of your answer right away. Without any code.Squarerigged
S
2

For older Delphi versions from delphi 5 help example:

uses Dialogs;
var 

  I, Code: Integer;
begin
  { Get text from TEdit control }
  Val(Edit1.Text, I, Code);
  { Error during conversion to integer? }
  if Code <> 0 then
    MessageDlg('Error at position: ' + IntToStr(Code), mtWarning, [mbOk], 0);
  else
    Canvas.TextOut(10, 10, 'Value = ' + IntToStr(I));   
end;
Sisterhood answered 3/2, 2011 at 10:11 Comment(0)
H
1

In some languages decimal separators are different (for example, '.' is used in English and ',' is used in Russian). For these cases to convert string to real number the following procedure is proposed:

function TryStrToFloatMultiLang(const S : String; out Value : Extended) : Boolean;
var
  dc : char;
begin
  Result := false;
  dc := DecimalSeparator;
  DecimalSeparator := '.';
  try
    Result := TryStrToFloat(S, Value);
  except
    DecimalSeparator := ',';
    Result := TryStrToFloat(S, Value);
  end;
  DecimalSeparator := dc;
end;

Update

As @Pep mentioned TryStrToFloat catch exceptions, but it returns boolean value. So the correct code is:

function TryStrToFloatMultiLang(const S : String; out Value : Extended) : Boolean;
var
  dc : char;
begin
  Result := false;
  dc := DecimalSeparator;
  DecimalSeparator := '.';
  Result := TryStrToFloat(S, Value);
  if not Result then begin
    DecimalSeparator := ',';
    Result := TryStrToFloat(S, Value);
  end;
  DecimalSeparator := dc;
end;
Hirza answered 17/12, 2013 at 11:0 Comment(1)
While the remark about different decimal separators is definitively important, your sample code is trying to catch exceptions where there are not exceptions, because TryStrToFloat already catches any possible exception. This means that your "except" clause is never executed. "Good catch!", you might think :)Corrincorrina
A
0

When you using procedure

val(s, i, iCode);

and set value xd ....

val('xd', i, iCode)

as a result we obtain: 13

Apelles answered 1/11, 2013 at 8:40 Comment(0)
T
-2

standard unit Variants

function VarIsNumeric(v:Variant):Boolean
Tessin answered 18/3, 2014 at 5:41 Comment(2)
This tells you the type of the variant, not whether a string contains a number.Nobles
Although it doesn't answer the question, it's still good to know it exists. Thanks mate!Diverticulosis

© 2022 - 2024 — McMap. All rights reserved.