How to Validate Numeric Input in C++

how to check if the input is a number or not in C?

Another way of doing it is by using isdigit function. Below is the code for it:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXINPUT 100
int main()
{
char input[MAXINPUT] = "";
int length,i;

scanf ("%s", input);
length = strlen (input);
for (i=0;i<length; i++)
if (!isdigit(input[i]))
{
printf ("Entered input is not a number\n");
exit(1);
}
printf ("Given input is a number\n");
}

Check if input is integer type in C

num will always contain an integer because it's an int. The real problem with your code is that you don't check the scanf return value. scanf returns the number of successfully read items, so in this case it must return 1 for valid values. If not, an invalid integer value was entered and the num variable did probably not get changed (i.e. still has an arbitrary value because you didn't initialize it).

As of your comment, you only want to allow the user to enter an integer followed by the enter key. Unfortunately, this can't be simply achieved by scanf("%d\n"), but here's a trick to do it:

int num;
char term;
if(scanf("%d%c", &num, &term) != 2 || term != '\n')
printf("failure\n");
else
printf("valid integer followed by enter key\n");

Validation of integer with character input in C program

Some notes:
1) You aren't checking the scanf() return value, and this is very usable: the negative return means that the entered characters can't be converted to int (because of "%d" format), and the return value equal 0 means that the input is empty (no characters entered).

2) In case that the user entered wrong character(s) (not digit(s)), the input buffer will remain busy until you read it in other way. Good idea is to use additional scanf("%s") here to read any characters as string, so buffer will be empty after this call. Using rewind() is not enough here.

3) There is no need to additional checking of input in selectionChecking() for isdigit(), because "%d" format in scanf() doesn't allow to read anything else but number.

4) There is no need to pass pointer to selection value in selectionChecking() call - it will be enough to pass it as value.

So, try this below:

// declaration of 'selectionCheck()'
int selectionCheck(int input, int min, int max);

void main()
{
int selection;
while (1)
{
while (1)
{
printf("Enter Your Selection (0-4) > ");

int ret = scanf("%d", &selection);
if (ret < 0) // invalid characters on input
{
printf("Invalid characters\n");
scanf("%s"); // empty buffer, reading it as string and putting readed characters to nowhere ;)
continue; // go to top of loop
}

if (ret == 0) // empty input
{
printf("No (empty) input\n");
continue; // go to top of loop
}

// here 'ret' is greather than 0, so valid number was entered

if (selectionCheck(selection, 0, 4)) // is value between 0 and 4 ?
break; // yes, success, break current loop!

printf("Invalid value\n");
}

printf("Success\n");
}

system("pause");
}

int selectionCheck(int input, int min, int max)
{
if (input < min || input > max)
return 0;
else
return 1;
}

Of course, you can write 'selectionCheck()' more condensed:

int selectionCheck(int input, int min, int max)
{
return (input < min || input > max) ? 0 : 1;
}

or simply:

int selectionCheck(int input, int min, int max)
{
return (input >= min && input <= max);
}

int validation using scanf and isdigit

Don't use isdigit() — it is for checking whether a character is a digit or not. You've read a number. You must check the return value from scanf() — if it is not 1, you've got a problem. Depending on your requirements, the fact that there may be all sorts of stuff on the line after the number may or may not be a problem. I'm assuming when you say "validate the input is an integer", you want to allow for multiple-digit numbers, and negative numbers, and since you used %i rather than %d, you're fine with octal values (leading 0) or hexadecimal values (leading 0x or 0X) being entered too.

Note that if you have:

int checker = scanf("%i", &i);

then the result could be 1, 0, or EOF. If the result is 1, then you got an integer after possible leading white space, including possibly multiple newlines. There could be all sorts of 'garbage' after the number and before the next newline. If the result is 0, then after skipping possible white space, including possibly multiple newlines, the first character that wasn't white space also wasn't part of an integer (or it might have been a sign not immediately followed by a digit). If the result is EOF, then end-of-file was detected after possibly reading white space, possibly including multiple newlines, but before anything other than white space was read.

To continue sensibly, you need to check that the value returned was 1. Even then, there could be problems if the value is out of the valid range for the int type.

The full requirement isn't completely clear yet. However, I'm going to assume that the user is required to enter a number on the first line of input, with possibly a sign (- or +), and possibly in octal (leading 0) or hexadecimal (leading 0x or 0X), and with at most white space after the number and before the newline. And that the value must be in the range INT_MIN .. INT_MAX? (The behaviour of scanf() on overflow is undefined — just to add to your woes.)

The correct tools to use for this are fgets() or POSIX
getline() to read the line, and
strtol() to convert to a number, and isspace() to validate the tail end of the line.

Note that using strtol() properly is quite tricky.

In the code below, note the cast to unsigned char in the call to isspace(). That ensures that a valid value is passed to the function, even if the plain char type is signed and the character entered by the user has the high bit set so the value would convert to a negative integer. The valid inputs for any of the ispqrst() or topqrst() functions are EOF or the range of unsigned char.

C11 §7.4 Character handling <ctype.h> ¶1

… In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

The GNU C library tends to protect the careless, but you should not rely on being nannied by your standard C library.

#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char line[4096]; /* Make it bigger if you like */

printf("Enter a number: ");
if (fgets(line, sizeof(line), stdin) == 0)
{
fprintf(stderr, "Unexpected EOF\n");
exit(EXIT_FAILURE);
}
errno = 0;
char *eon; /* End of number */
long result = strtol(line, &eon, 0);
if (eon == line)
{
fprintf(stderr, "What you entered is not a number: %s\n", line);
exit(EXIT_FAILURE);
}
if (sizeof(int) == sizeof(long))
{
if ((result == LONG_MIN || result == LONG_MAX) && errno == ERANGE)
{
fprintf(stderr, "What you entered is not a number in the range %ld..%+ld: %s\n",
LONG_MIN, LONG_MAX, line);
exit(EXIT_FAILURE);
}
}
else
{
if ((result == LONG_MIN || result == LONG_MAX) && errno == ERANGE)
{
fprintf(stderr, "What you entered is not a number in the range %ld..%+ld,\n"
"let alone in the range %d..%+d: %s\n",
LONG_MIN, LONG_MAX, INT_MIN, INT_MAX, line);
exit(EXIT_FAILURE);
}
}
char c;
while ((c = *eon++) != '\0')
{
if (!isspace((unsigned char)c))
{
fprintf(stderr, "There is trailing information (%c) after the number: %s\n",
c, line);
exit(EXIT_FAILURE);
}
}
if (result < INT_MIN || result > INT_MAX)
{
fprintf(stderr, "What you entered is outside the range %d..%+d: %s\n",
INT_MIN, INT_MAX, line);
exit(EXIT_FAILURE);
}
int i = result; /* No truncation given prior tests */
printf("%d is a valid int\n", i);
return(EXIT_SUCCESS);
}

That seems to work correctly for a fairly large collection of weird numeric and non-numeric inputs. The code handles both 32-bit systems where sizeof(long) == sizeof(int) and LP64 64-bit systems where sizeof(long) > sizeof(int) — you probably don't need that. You can legitimately decide not to detect all the separate conditions but to aggregate some of the errors into a smaller number of error messages.

C programming - validating int input so it isn't a character

Rather than trying to work out that it's not a character, work out that it is a digit and discard the rest using the isdigit function from ctype like below.

#include <ctype.h>

...

if (isdigit(num)) {
printf("You entered %d\n", num);
}

But this only works on single characters which is quite useless when you read in strings. So instead you could instead use the function sscanf. Like this.

int num;
if (sscanf(numstr, "%d", &num)){
printf("You entered %d\n", num);
} else {
printf("Invalid input '%s'\n", numstr);
}

Another option is to use the atoi function. But as I recall it doesn't handle errors and I find quite inferior to sscanf.

How can I validate scanf numeric input

The %d scanf specifier is to read int, if an alphabetic character is inputed, scanf will fail to read it and temp->data will retain its previous value.

A better condition for your cycle would be:

while (scanf("%d", &(temp->data)) == 0) //while input is not correctly parsed...
{
fprintf(stderr, "ERROR alph is not allowed\n"); //...print error message...
int c;
while((c = getchar()) != '\n' && c != EOF) {} //...and clear stdin
}

This makes it so that if the input is not parseable as an int a new input will be asked until a good value is inputed.

Note that, as @JohnBode pointed out, an input starting with a digit but that contains alphabetic characters will be parsed until the character is found, i.e. 123abc4 will parse 123. If you want to avoid this, using a combination of fgets and strtoll is a more robust method and will allow you to validate inputs like the above.

If it's something that you want to allow to happen, and continue using scanf, don't forget you need to then clear stdin which will have the characters that were not parsed, (in the exemplified case abc4\n), before asking for new inputs, @JohnBode's answer covers these matters perfectly, check that out.


There is another problem in the code you show, your temp pointer is NULL, it is not able to store any data. Either declare it as an object or allocate memory for it. As it is, it leads to undefined behavior.



How to validate numeric input in C++

double i;

//Reading the value
cin >> i;

//Numeric input validation
if(!cin.eof())
{
peeked = cin.peek();
if(peeked == 10 && cin.good())
{
//Good!
count << "i is a decimal";
}
else
{
count << "i is not a decimal";
cin.clear();
cin >> discard;
}
}

This also gives an error message with the input -1a2.0 avoiding the assignation of just -1 to i.



Related Topics



Leave a reply



Submit