Check if input is a correct integer
I have a little problem with checking my input. I know that there a already similar questions but sincerly it does not solve my problem. I'm already using one of the suggestions from the other questions and it does not work.
#include <iostream>
#include <stdio.h>
#开发者_StackOverflow中文版include <ctype.h>
int main ()
{
int a;
printf("Please type in your number: ");
scanf_s("%d", &a);
if(isdigit(a))
{
printf("True.");
}
else
{
printf("False.");
}
std::cin.get();
std::cin.get();
return 0;
}
I don't know what i'm doing wrong but my output is always "False" when i type in a number. When i type in a letter the compiler has an error.
a
is already an integer variable.std::isdigit
only checks whether a character corresponds to a digit, i.e. the characters'0'
to'9'
.Try not to mix C libraries (
printf
,scanf
etc.) with C++ libraries (cout
andcin
). Stick to either one.As for how to actually check whether the user entered a number or not, see this answer.
You are using isdigit
function incorrectly.
Even though isdigit
receives an int
as its only parameter, it expects a char
value (a byte/number representing an ASCII letter) not a pure int
as you are now using it.
I.E.:
is_digit('1'); // true
is_digit('a'); // false
scanf
will already return a parsed integer value, so you don't need to check if it is a digit or not.
Perhaps if you specify what exactly you are trying to accomplish, we could help some more.
Although isdigit()
takes an int
as an argument, it checks the character value of your variable. This:
scanf_s("%d", &a);
gives you an integer value, not a character value.
You're using scanf
with %d, which will convert the digit(s) to an integer, but isdigit
is intended to work with raw characters that have not been converted yet. If you use it, you'd (probably) want to read a string, then check whether all the characters entered were digits, (with isdigit
) and only after you've done that would you try to convert to an integer.
Alternatively, you could use something like strtol
to convert the string to an integer, and tell you where (and if) it failed.
If you need to do this in c, follow the answers other ppl already posted.
If you want to do this in c++, I'd recommend:
int num = boost::lexical_cast<int>( somestring );
And the documentation on boost::lexical_cast
isdigit takes a character and return true or false depending on whether the character is a digit or not. So you could use this on each character of the the string representation of your integer, but your 'a' is already an integer, as set by scanf_s
scanf_s will only translate the first digits of the input into the equivalent integer, then will stop scanning. You need instead to process the actual characters entered, so you probaly want something like fgets.
Once you have the string, you can loop over every character in it checking if it is a digit (or you can use a library function like strtol to do this for you and return the integer value, checking afterwards that it consumed all the input when it did so (to reject things like 123X)
I suggest reading a line into a string and then trying to parse that string according to your needs. If the parse fails, simply prompt the user again. You can bury the messy details in a function template:
#include <iostream>
#include <sstream>
#include <string>
template <typename T>
T read(std::string prompt)
{
for (; ;)
{
std::cout << prompt;
std::string line;
getline(std::cin, line);
std::istringstream ss(line);
T x;
if ((ss >> x) && (ss >> std::ws).eof()) return x;
}
}
int main ()
{
int a = read<int>("Please type in your number: ");
std::cout << "You entered " << a << '\n';
}
Don't use scanf
and family. Use fgets
then strtol
/strtoul
/etc. to parse numbers.
If you're really determined to use scanf, you can verify if the conversion took place by checking scanf's return value. It returns the number of successfully processed format items, or -1 on error. In your case, successful input should return 1 from scanf.
http://www.cplusplus.com/reference/clibrary/cstdio/scanf/
Here's another method that's more in the spirit of C++ (although I am not a C++ expert, so there's probably a better way to do this):
#include <iostream>
#include <exception>
#include <cctype>
int main()
{
using namespace std;
int a;
cout << "Please type in your number: " << flush;
/**
* Tell the input operation to throw an exception if the input
* is not properly formatted for the target data type; note that
* this will only catch bad input that *starts* with a non-numeric
* character.
*/
cin.exceptions(ios_base::failbit);
try
{
cin >> a;
if (!isspace(cin.get())
cout << "false" << endl; // non-numeric, non-whitespace character found
// at end of input string, e.g. "12w"
else
cout << "true" << endl;
}
catch(ios_base::failure& e) // non-numeric, non-whitespace character found
{ // at beginning of input string, e.g. "x23"
cout << "false" << endl;
}
return 0;
}
Now i have found a solution which works for me, but there is still a little problem. This is my modified code:
#include <iostream>
#include <stdio.h>
#include <ctype.h>
int main ()
{
int a;
printf("Please type in your number: ");
if(scanf_s("%d", &a) == 1)
{
printf("True.");
}
else
{
printf("False.");
}
std::cin.get();
std::cin.get();
return 0;
}
Now the problem is that i must put a "std::cin.get()" for each letter i type in. That's crazy. So when i want to check if "hello" is a number or not i must put a total amount of 7x "std::cin.get()" to hold the screen so that i can see the result.
精彩评论