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;
kobik
  • 20,439
  • 4
  • 54
  • 115
none
  • 4,256
  • 13
  • 54
  • 96
  • 6
    What is "infinite exceptions"? – David Heffernan Feb 03 '11 at 09:27
  • 4
    By number you mean integer? Or do you want to allow real numbers as well? – jpfollenius Feb 03 '11 at 09:29
  • 5
    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. – Rob Kennedy Feb 03 '11 at 15:04
  • 1
    @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...');` – Jørn E. Angeltveit Feb 04 '11 at 09:54
  • 2
    @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." – Rob Kennedy Feb 04 '11 at 15:56
  • @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. – Jørn E. Angeltveit Feb 04 '11 at 18:26

10 Answers10

65

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;
Community
  • 1
  • 1
ba__friend
  • 5,433
  • 2
  • 25
  • 20
27
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');
Wodzu
  • 6,705
  • 8
  • 57
  • 99
da-soft
  • 7,430
  • 25
  • 34
  • 4
    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. – jpfollenius Feb 03 '11 at 09:57
  • 2
    @none: `TryStrToInt` should be available in D7. Any reason why you accepted this solution and not the one posted by bassfriend? – jpfollenius Feb 03 '11 at 11:16
  • 9
    @Smasher @none `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. – David Heffernan Feb 03 '11 at 11:28
  • 6
    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); – gabr Feb 03 '11 at 14:38
  • 2
    I do not like this solution because it will leave you a hint that iValue is not used. – Wodzu Apr 08 '14 at 05:15
  • 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. – T.S Jan 26 '18 at 08:22
18

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;
Bharat
  • 6,648
  • 5
  • 31
  • 54
  • 4
    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. – jpfollenius Feb 03 '11 at 09:33
  • A useful function, but not addressing the question as asked. There is no way to tell whether or not the input was a number. – David Heffernan Feb 03 '11 at 09:33
  • @David: Yes you are correct but i just want to suggest an alternative which will help the user to set some default value also – Bharat Feb 03 '11 at 09:40
  • understood, I was just making the point for the benefit of the OP so that he was aware of the issue – David Heffernan Feb 03 '11 at 09:42
  • 1
    @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. – JensG Nov 30 '13 at 21:06
  • StrToInt / StrToIntDef can not handle longint though. Can it? – T.S Jan 25 '18 at 16:03
  • @Bharat Delphi 7 does have `TryStrToInt()` – Nat Jan 23 '19 at 23:46
7

XE4 and newer:

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

Don't forget:

uses System.Character    
zawuza
  • 654
  • 8
  • 14
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.

Robert Niestroj
  • 12,866
  • 12
  • 63
  • 101
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;

sina
  • 199
  • 3
  • 9
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;
GJ.
  • 10,234
  • 2
  • 39
  • 58
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;
LaBracca
  • 13,941
  • 34
  • 129
  • 224
Ivan Z
  • 1,215
  • 1
  • 12
  • 22
  • 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 :) – Pep Apr 02 '15 at 17:16
0

When you using procedure

val(s, i, iCode);

and set value xd ....

val('xd', i, iCode)

as a result we obtain: 13

androschuk.a
  • 279
  • 7
  • 19
-2

standard unit Variants

function VarIsNumeric(v:Variant):Boolean
chopper
  • 6,179
  • 6
  • 31
  • 53
Andrey Rubanko
  • 135
  • 1
  • 5