20

I need to check if a C string is a valid integer.

I tried both

int num=atoi(str);

and

int res=sscanf(str, "%d", &num);

But sending the string "8 -9 10" in both of the lines returned simply 8, without indicating the invalidity of this string.

Can anyone suggest an alternative?

royhowie
  • 11,075
  • 14
  • 50
  • 67
sara
  • 3,824
  • 9
  • 43
  • 71
  • `atoi` does no error checking; its behavior if `str` doesn't contain a representation of an `int` value is undefined. (Typical implementations return `0`.) `sscanf` is better, but its behavior is undefined if the value in the string is not representable as an `int`. Also, your title says you want to check for a valid int, but the body of your question says "valid integer"; they aren't the same thing. `int` is one of several *integer* types. – Keith Thompson Mar 18 '12 at 00:22

5 Answers5

30

Have a look at strtol(), it can tell you about invalid parts of the string by pointer return.

And beware of enthusiastic example code.. see the man page for comprehensive error-handling.

blueshift
  • 6,742
  • 2
  • 39
  • 63
  • strtol() just sets the pointer to the next "object" in the string. It does not validate anything. –  Mar 17 '12 at 20:41
  • 1
    @g24l If that pointer ends up pointing to NULL, then you know the entire string was valid. If not, not. Tadaa! – blueshift Mar 17 '12 at 20:45
  • If it is a null terminated string. –  Mar 17 '12 at 20:47
  • 2
    ok, you are right I just noticed that she specified C string. –  Mar 17 '12 at 20:52
  • 4
    Note that `strtol()` returns a `long` result. If you want to check for a valid `int`, you'll also need to check that the result is in the range `INT_MIN` .. `INT_MAX`. – Keith Thompson Mar 18 '12 at 00:23
  • The problem is that `strtol` even returns a correct value and set `errno = 0 ` if you input "123dfds" which is not an correct number. – M.K. aka Grisu Feb 19 '15 at 16:16
8

Maybe I'll get flamed for not using strtol or similar libc functions, but reasoning about this problem is not that hard:

#include <stdbool.h>  // if using C99...  for C++ leave this out.
#include <ctype.h>

bool is_valid_int(const char *str)
{
   // Handle negative numbers.
   //
   if (*str == '-')
      ++str;

   // Handle empty string or just "-".
   //
   if (!*str)
      return false;

   // Check for non-digit chars in the rest of the stirng.
   //
   while (*str)
   {
      if (!isdigit(*str))
         return false;
      else
         ++str;
   }

   return true;
}

[NB: I might have otherwise done isdigit(*str++) instead of the else to keep it shorter but my recollection is that the standards say it's possible that isdigit is a macro.]

I guess one limitation is that this does not return false if the number in the string won't fit in an integer. That may or may not matter to you.

asveikau
  • 39,039
  • 2
  • 53
  • 68
3

A simple way to do this robustly would be to read the int and make sure it's string representation is identical to the input string, for example combining atoi and itoa:

int is_int(char const* p)
{
    return strcmp(itoa(atoi(p)), p) == 0;
}
Inverse
  • 4,408
  • 2
  • 26
  • 35
0

For checking if string contains a valid number you can use a regular expression. For example for integers use:

[-+]?[0-9]+

and a general case for floating point numbers:

[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?

In the case of C++11 regular expression functions are avalaible in library, e.g. "std::regex_match(.....)" gives the exact match. The code should look like this:

#include <regex>
.....
std::string strnumber("-1.234e+01");
float number;
if(regex_match(strnumber,std::regex("[+-]?[0-9]+[.]?[0-9]*([eE][-+]?[0-9]+)?"))
number=std::stof(strnumber);
else
std::cout<<"error, string is not a valid number";
Kazik
  • 1
  • 1
0

Sorry for digging up the topic, but for the sake of completeness and because this thread is the first match when doing a google search...

It is possible to use something like:

ret = sscanf(string, "%d%n", &number, &idx);
if (ret == 0 || string[idx] != '\0')
    /* handle the error */

the %n directive, which seems to be standard C according to the man page, counts the number of characters processed .

[Edit] sscanf doesn't seem to provide a way to detect overflows, so the strtoX functions family should be preferred IMHO.

ncarrier
  • 433
  • 3
  • 14