0

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>
#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.

Ordo
  • 705
  • 8
  • 18
  • 29
  • Possible duplicate of [how do I validate user input as a double in C++?](http://stackoverflow.com/questions/3273993/how-do-i-validate-user-input-as-a-double-in-c) and many others... – Paul R Nov 08 '10 at 20:54
  • What happens when you try `48`? :-) – pmg Nov 08 '10 at 21:03
  • That's strange for 48 the output is true... – Ordo Nov 09 '10 at 05:41

11 Answers11

3
  1. a is already an integer variable. std::isdigit only checks whether a character corresponds to a digit, i.e. the characters '0' to '9'.

  2. Try not to mix C libraries (printf, scanf etc.) with C++ libraries (cout and cin). Stick to either one.

  3. As for how to actually check whether the user entered a number or not, see this answer.

Community
  • 1
  • 1
casablanca
  • 69,683
  • 7
  • 133
  • 150
2

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.

Pablo Santa Cruz
  • 176,835
  • 32
  • 241
  • 292
  • Ok, but what will scanf do when i type in a letter? My compiler does nothing. It just stops. So there must be a way to ask for a correct input in that case. – Ordo Nov 09 '10 at 06:51
2

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.

Alex Reynolds
  • 95,983
  • 54
  • 240
  • 345
2

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.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
2

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

jbremnant
  • 894
  • 6
  • 6
1

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)

The Archetypal Paul
  • 41,321
  • 20
  • 104
  • 134
1

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';
}
fredoverflow
  • 256,549
  • 94
  • 388
  • 662
1

Don't use scanf and family. Use fgets then strtol/strtoul/etc. to parse numbers.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
1

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/

1

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;
}
John Bode
  • 119,563
  • 19
  • 122
  • 198
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.

Ordo
  • 705
  • 8
  • 18
  • 29