GarrickW
GarrickW

Reputation: 2241

Disambiguating std::isalpha() in C++

So I am currently writing a part of a program that takes user text input. I want to ignore all input characters that are not alphabetic, and so I figured std::isalpha() would be a good way to do this. Unfortunately, as far as I know there are two std::isalpha() functions, and the general one needs to be disambiguated from the locale-specific one thusly:

(int(*)(int))std::isalpha()

If I don't disambiguate, std::isalpha seems to return true when reading uppercase but false when reading lowercase letters (if I directly print the returned value, though, it returns 0 for non-alpha chars, 1 for uppercase chars, and 2 for lowercase chars). So I need to do this.

I've done so in another program before, but for some reason, in this project, I sometimes get "ISO C++ forbids" errors. Note, only sometimes. Here is the problematic area of code (this appears together without anything in between):

std::cout << "Is alpha? " << (int(*)(int))std::isalpha((char)Event.text.unicode) << "\n";

if ( (int(*)(int))std::isalpha((char)Event.text.unicode) == true)
{
    std::cout << "Is alpha!\n";
    //...snip...
}

The first instance, where I send the returned value to std::cout, works fine - I get no errors for this, I get the expected values (0 for non-alpha, 1 for alpha), and if that's the only place I try to disambiguate, the program compiles and runs fine.

The second instance, however, throws up this:

error: ISO C++ forbids comparison between pointer and integer

and only compiles if I remove the (int(*)(int)) snippet, at which point bad behavior ensues. Could someone enlighten me here?

Upvotes: 3

Views: 1241

Answers (2)

sth
sth

Reputation: 229854

You are casting the return value of the std::alpha() call to int(*)(int), and then compare that pointer to true. Comparing pointers to boolean values doesn't make much sense and you get an error.

Now, without the cast, you compare the int returned by std::alpha() to true. bool is an integer type, and to compare the two different integer types the values are first converted to the same type. In this case they are both converted to int. true becomes 1, and if std::isalpha() returned 2 the comparison ends up with 2 != 1.

If you want to compare the result of std::alpha() against a bool, you should cast that returned in to bool, or simply leave out the comparison and use something like if (std::isalpha(c)) {...}

Upvotes: 3

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145429

There is no need to disambiguate, because the there is no ambiguity in a normal call.

Also, there is no need to use the std:: prefix when you get the function declaration from <ctype.h>, which after C++11 is the header you should preferably use (i.e., not <cctype>) – and for that matter also before C++11, but C++11 clinched it.

Third, you should not compare the result to true.

However, you need to cast a char argument to unsigned char, lest you get Undefined Behavior for anything but 7-bit ASCII.

E.g. do like this:

bool isAlpha( char const c )
{
    typedef unsigned char UChar;
    return !!isalpha( UChar( c ) );
}

Upvotes: 2

Related Questions