Computernerd
Computernerd

Reputation: 7766

isdigit is not working correctly

I am trying to test if a string contains an integer by iterating through the entire string and outputting the integer. My method involves converting the string to c-string , atoi the c-string and then testing if its an integer using isdigit function. For some unknown reason, isdigit function is returning false though it encounters a integer.

I need help resolving this issue

#include <iostream>
using namespace std;
#include <string>

int main()
{
    string p = "[ab, e2cd]";

    for (int k = 0; k < p.length(); k++)
    {
        if (isdigit(atoi(p.substr(k,1).c_str())) == true) //testing done here
        {
            cout << atoi(p.substr(k, 1).c_str());
        }
    }
}

Upvotes: 4

Views: 8043

Answers (3)

Devolus
Devolus

Reputation: 22084

atoi converts a cstring to a number. If the string is invalid, you wont know, because atoi returns 0, which could also be the number in the string.

isdigit Should be passed a character as an int and returns false if it is not a digit character. So you are comparing apple with oranges.

Just iterate over the string and pass each character to isdigit() and if this works, then you can use atoi to convert it.

One pitfall can be though, that the string contains + or - as part of the number, and isdigit() does not return true in this case. There may be other characters as well being part of a valid number, but for simple integer values, this should suffice.

Upvotes: 2

Keith Thompson
Keith Thompson

Reputation: 263237

The behavior of isdigit is fairly bizarre, for historical reasons.

It takes a character value, and tells you whether it's a decimal digit (one of '0', '1', ... '9') -- which means that applying it to the result of atoi() rarely makes sense.

But the character value is represented not as a char, but as an int whose value is in the range of unsigned char. Any other argument value (other than EOF, which is typically -1) causes undefined behavior. So if you want to test a char value, you should cast it to unsigned char; if plain char is signed, omitting the cast risks undefined behavior.

And the result isn't a bool. It's an int whose value is 0 for a non-digit, and any arbitrary non-zero value for a digit. Do not compare the result for equality to true. For that matter, don't compare any value that represents a condition for equality or inequality to false or true; it's already a condition, so just use it directly.

If c is a char, replace

if (isdigit(c) == true)

by

if (isdigit((unsigned char)c))

or

if (isdigit(static_cast<unsigned char>(c)))

Upvotes: 2

juanchopanza
juanchopanza

Reputation: 227390

isdigit takes an int with the value of a single character in your locale. It is OK to pass it an unsigned char cast from a char, and let the conversion to int do its thing. Since string contains chars, you can use it's elements like this:

if ( static_cast<unsigned char>(isdigit(p[k])) ) { ....

Upvotes: 3

Related Questions