0

Here's the code that I'm using it to check whether key is a number:

string key;
cin>>key;
if(isalpha(atoi(key.c_str())) == 0)
{
     //do something
}
else
    //do something else

No matter what I input, isalpha always == 0. I tried treating it like a boolean by using if(isalpha(atoi(key.c_str()))) but it does the same thing.

The key is supposed to be an int, but cin.fail() and !(cin>>key) didn't work either.

LihO
  • 37,789
  • 9
  • 89
  • 156
SemicolonExpected
  • 589
  • 1
  • 10
  • 36
  • What are you trying to achieve? `isalpha` tests a char... you are converting a string to an int, and then testing the int for some odd reason. – David Mar 02 '13 at 23:40
  • @OliCharlesworth I'm using it to check if something is a number. It's to prevent errors. – SemicolonExpected Mar 02 '13 at 23:40
  • 3
    @ArcaneExplosion, Something like `try {std::stoi(key);} catch (IForgetWhichException) {//not a number}` will work. Alternatively, `boost::lexical_cast` will also throw an exception for a bad conversion and `strtol` will give error information. – chris Mar 02 '13 at 23:42
  • I thought `.c_str()` turns it back to a char * temporarily @Cthulhu – SemicolonExpected Mar 02 '13 at 23:42
  • 2
    That doesn't really answer my question... Anyway, here's an example of it "working": http://ideone.com/xDucNT. – Oliver Charlesworth Mar 02 '13 at 23:42
  • @OliCharlesworth but if I try something like '1' it doesn't work. I tested 65 like you did and it did though. – SemicolonExpected Mar 02 '13 at 23:45
  • 1
    @ArcaneExplosion: yes, that's because the code you've written is (alas) nonsense. `isalpha` expects a `char`, and checks whether its value corresponds to the ASCII code for an alphabetic character. So unless your string contains a text representation of such an ASCII code, it will return 0. – Oliver Charlesworth Mar 02 '13 at 23:47
  • 1
    Just check after `c_str()` if input is `> 'a' and < 'z'` and similarly for `A` and `Z`. – Anirudh Ramanathan Mar 02 '13 at 23:49
  • Oh, are these all strings with a length of 1? – chris Mar 02 '13 at 23:56
  • @chris they arent, also according to my compliler stoi isn't part of std. – SemicolonExpected Mar 03 '13 at 00:10
  • @ArcaneExplosion, It's part of C++11 and some versions of libraries with GCC don't quite have it without some extra compiler options. – chris Mar 03 '13 at 00:14

5 Answers5

2

In your code, key is a C++ string.

string key;

This converts the C++ string to a C string.

key.c_str()

This converts the C string to a number. An integer. (0 if the value can't be converted)

atoi(key.c_str())

And this checks whether that number is the ASCII code for a letter

isalpha(atoi(key.c_str()))

You're converting a C++ string to a C string to an integer to an ASCII value, and then checking whether that value is a letter of the alphabet (which won't tell you if it's a number, only whether it's "a letter" or "not a letter")

The if statement you've written will be true only when the user enters something that is not the numeric ASCII value of a letter. E.g. entering 65 will go to the else clause, because 65 is the ASCII code for 'A'

Try the suggestion @chris kindly offers.

try
{
    int the_number = std::stoi(key);
    //do something
}
catch( std::exception& )
{
    //do something else
}
Drew Dormann
  • 50,103
  • 11
  • 109
  • 162
0

You are defining key with no contents and use its t_str method immediately in a case that it returns a char pointer to empty array. Therefore atoi always returns zero.

Please refer here http://www.cplusplus.com/reference/cstdlib/atoi/

On the given example key is empty and atoi parameter is invalid such that atoi always returns zero

hmatar
  • 2,335
  • 2
  • 15
  • 27
0

If you need to test if the input is numeric or not-:

string key;
cin>>key;
if (key.size() && isalpha(*(key.c_str()))
{
    //do something with non-numeric input
}
else
    // numeric input, use atoi to get integer value
suspectus
  • 14,884
  • 8
  • 41
  • 53
  • If the input was an int, the code would enter the else branch of the if statement. I'm assuming the user cannot be trusted to do the right thing :) – suspectus Mar 03 '13 at 00:16
  • @ArcaneExplosion careful, that code will assume that `@` or `!abc` or `5andwich` is a number. – Drew Dormann Mar 03 '13 at 00:28
  • 1
    This checks whether the input string is longer than 0 characters AND whether the first character is one of the following: `a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z`, which doesn't seem to be useful validation at all. – LihO Mar 03 '13 at 00:34
  • I'm pretty sure if I use a `for` loop and treat the string as an array, I can check each letter to make sure if it's a number or not. – SemicolonExpected Mar 03 '13 at 01:01
0

Note that using atoi for determining whether the string contains a number isn't very lucky choice. If you want to make sure that your string contains only digits, then the best you can do is to iterate through its characters and check each character (you could use std::isdigit).

Then for extraction of integral value from this string, in C++11 you can use std::stoi, otherwise you could use std::istringstream:

int val;
std::string key;
// ...
if (std::istringstream(key) >> val)
{
    // success
}
else
{
    // failure
}

which will will end up with success when key starts with a string representing a number. So it will also work for strings like 42abc, 0x21zzz, etc. Then it depends on your specific situation, but maybe you won't even need any previous validation in this case.

Related question that might help: How to determine if a string is a number with C++?

Community
  • 1
  • 1
LihO
  • 37,789
  • 9
  • 89
  • 156
0

As @suspectus did except iterating through each character in the string and using isDigit instead so it doesn't think ! or @ is a number.

for(int i = 0; i<key.size(); i++)
{
   if(!(isdigit(key[i])))
   {
      //fails
   }
}
SemicolonExpected
  • 589
  • 1
  • 10
  • 36