How to Check If Input Is Numeric 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 a number

scanf's return value is an integer, telling you how many items were succesfully read. If your single integer was read successfully, scanf will return 1.

#include <stdio.h>

int main(){
int numbers[250000],i,m=0;
int itemsRead = 0;
while(itemsRead = scanf("%d",&i) != EOF){
if (itemsRead != 1)
{
printf("Wrong input");
return 0;
}
numbers[m]=i;
m++;
}
}

check if input is a number and if not return to input

Critique

#include <stdio.h>
#include <conio.h>

So you are working on Windows.

#include <ctype.h>
void main(void)

The return type of main() should be int, even though you'll find lots of examples to the contrary.

{
int val_a;
int val_b;
int result;

printf("Write a number A=");
scanf("%d", &val_a);

You should be testing the return value from scanf() to see whether it was able to read a number or not.

    if (isdigit(val_a))

This test 'works', but it checks whether the number entered was a value in the range 48..57 (which are the ASCII, CP1252, Unicode, ISO 8859-1, etc codes for the digits '0' to '9'). This probably wasn't what you had in mind.

    {
printf("\nWrite a number B=");
scanf("%d", &val_b);

The user entered a newline, so the newline in front ot the printf() format string is not necessary, though it is also not harmful. The same comment about checking scanf() applies here, too.

    }
else
printf("\nI said number.\n");

It is good to do error checking. However, you continue onwards even if you detect the error. You really need to stop.

    result = val_a + val_b;
printf("%d + %d = %d", val_a, val_b, result);

On the whole, it is best to end lines with a newline. It flushes the data to the file or screen.

    getch();
printf("\033[2J"); \\ to clear the screen

The printf() format string is not portable. Given that you included <conio.h>, you should probably use clrscr() (which probably does send that escape sequence, or an equivalent, to the terminal). I'm not convinced that it is necessary to clear the screen at the end of the program, but I work mainly on Unix systems, not with Windows.

}

Given that MSVC is still a C89 compiler, you should include return 0; at the end of the program to return a success status.

Rewritten

Adding all the changes, you'd end up with:

#include <stdio.h>
#include <conio.h>

int main(void)
{
int val_a;
int val_b;
int result;

printf("Write a number A=");
if (scanf("%d", &val_a) != 1)
{
printf("I said number.\n");
getch();
clrscr();
return(1);
}
printf("\nWrite a number B=");
if (scanf("%d", &val_b) != 1)
{
printf("I said number.\n");
getch();
clrscr();
return(1);
}

result = val_a + val_b;
printf("%d + %d = %d\n", val_a, val_b, result);
getch();
clrscr();
return(0);
}

When you've learned about writing functions, you might compress that to:

#include <stdio.h>
#include <conio.h>

static int get_a_number(const char *prompt)
{
int value;
printf(prompt);
if (scanf("%d", &value) != 1)
{
printf("I said number.\n");
getch();
clrscr();
exit(1);
}
return value;
}

int main(void)
{
int val_a = get_a_number("Write a number A=");
int val_b = get_a_number("Write a number B=");
int result = val_a + val_b;
printf("%d + %d = %d\n", val_a, val_b, result);
getch();
clrscr();
return(0);
}

The get_a_number() function is not a general purpose function, but it is useful in this context since it encapsulates a common piece of code.

  • A subroutine call permits us to summarize the irregularities in the argument list.
  • The subroutine itself summarizes the regularities of the code.

That's a quote from Kernighan & Plauger, "The Elements of Programming Style".


Using atexit()

The code above was updated to include getch() and clrscr() on all exit paths (and to remove #include <ctype.h> since none of the functions from it were used any more). It's a nuisance to write out the two function calls repeatedly. Another way to avoid that problem is to write a function that is called when the program exits; you register it with the atexit() function, which is declared in <stdlib.h>:

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>

static void wait_at_exit(void)
{
getch();
clrscr();
}

static int get_a_number(const char *prompt)
{
int value;
printf(prompt);
if (scanf("%d", &value) != 1)
{
printf("I said number.\n");
exit(1);
}
return value;
}

int main(void)
{
atexit(wait_at_exit);
int val_a = get_a_number("Write a number A=");
int val_b = get_a_number("Write a number B=");
int result = val_a + val_b;
printf("%d + %d = %d\n", val_a, val_b, result);
return(0);
}

That code in main() assumes you can mix statements (such as atexit()) and declarations (such as int val_a) arbitrarily. That is permitted by both the current (2011) and old (1999) versions of Standard C, but was not permitted by the original (1989) version of Standard C. I believe MSVC adheres to the original standard. If so, you probably need to write that main() as:

int main(void)
{
atexit(wait_at_exit);
{
int val_a = get_a_number("Write a number A=");
int val_b = get_a_number("Write a number B=");
int result = val_a + val_b;
printf("%d + %d = %d\n", val_a, val_b, result);
}
return(0);
}

It is a fine discussion point whether the code inside the inner block (the inner braces) should be indented an extra level or not. You're always allowed to declare variables at the start of a block of code enclosed in braces, so that allows me write the call to atexit() and then define and use those variables.

If you read about Agile programming, you'll find that one of the mantras is:

  • DRY — Don't Repeat Yourself

The rewrites above to avoid the repeated getscr() calls could be considered an application of that mantra. Similarly with the get_a_number() function; it to applies the DRY mantra.


Trying again

If you want the program to go back and prompt again if the user makes a mistake in their typing, then you need to modify the get_a_number() function. And, because the function grows considerably more complex, you definitely need to be using a function for the job. You also run into a problem with scanf(); it doesn't allow you to enforce one number per line. If you typed 1 2 in response to the first prompt, the first call to get_a_number() would read the one and the blank, stop parsing (and put the blank back for reuse), and return with the value 1. The second call to get_a_number() would output the prompt but return with the value 2 without the user typing anything more. If that's not the behaviour you want, then you have to arrange to read the whole first line and scan for the number, and then discard the rest. There's another reason for worrying too. If the user types a instead of 1, the scanf() will never read anything more; it will go into a loop, finding that the a is not valid as a digit, returning 0 conversions complete, and your code will probably end up in an infinite loop, prompting for input and reading the a. This sort of problem is why many people (particularly me) avoid using scanf().

The simplest way to avoid most of the problems above is with fgets() and sscanf():

enum { MAX_LINELENGTH = 4096 };
enum { MAX_ATTEMPTS = 10 };

static int get_a_number(const char *prompt)
{
int value;
char line[MAX_LINELENGTH];
int count = 0;
while (fputs(prompt, stdout) != EOF &&
fgets(line, sizeof(line), stdin) != 0)
{
if (sscanf(line, "%d", &value) == 1)
return value;
if (count++ > MAX_ATTEMPTS)
{
printf("I give in; I don't understand what you're typing\n");
exit(1);
}
printf("I said please enter a number.\n");
}

printf("Oops: I got EOF or an error; goodbye!\n");
exit(1);
}

That covers quite a lot of issues. Often, it is a good idea to echo back the erroneous data. You could do that with:

        printf("I didn't understand what you meant when you typed:\n%s\n"
"I said please enter a number.\n", line);

This uses 'adjacent string concatenation', and shows the user what the program received, which can often help the user understand what's wrong.

I used fputs(prompt, stdout) instead of printf(prompt) to output the prompt. Either could be used (printf(prompt) != 0 would be the test), but there is a slight advantage to fputs() because if someone managed to subvert your program and get a % into the prompt, the printf() would try to process an argument it was not passed, whereas fputs() does not interpret its argument string at all. Here, the difference is negligible; it can reasonably be argued that I'm over-complicating things. But the security of programs is also something you end up learning, and techniques such as "do not use printf(variable)" can help make your programs more resilient. (Actually, the complication is the explanation; the code is quite simple.)

Another detailed discussion point is 'should there be a fflush() after fputs() and before fgets()?' It would be possible to add the extra 'condition' fflush(stdout) == 0 && to the loop control, but in practice it is usually unnecessary. It would only make a difference if standard input was coming from something other than the terminal and standard output was going to a file. So, I left it out.

The counter in the loop prevents things going badly awry — the program exits rather than hang around forever, frustrating the user who can't get the data entered correctly. Have you ever had a program pop up a dialog box at which you can only hit the 'OK' button (even though its not OK) and then come back with the same box again, over and over and over again? I hope not for your sake. I have; it frustrates me when it happens.

And you can see why it is advantageous to write the code in get_a_number() just once, rather than twice; that would be a lot of repetition.

How to check if input is an integer in C?

Note that C is not like Python: You want to input a number with a decimal point into a variable whose type is an integer. An integer type variable can only hold integers, so... This number will automatically become an integer and the number behind the dot will not be counted.

So when you trying to insert the value 1.5 into cislo the value is automatically converted to an int value, to 1.


Solution:

#include <stdio.h>

int main(int argc, char** argv) {
float cislo;

printf("ml' nob:\n");

if (scanf("%f", &cislo) != 1)
// Problem (Handle it)

if (cislo == 1) {
printf("Qapla'\n");
printf("noH QapmeH wo' Qaw'lu'chugh yay chavbe'lu' 'ej wo' choqmeH may' DoHlu'chugh lujbe'lu'.\n");
} else if (cislo == 2) {
printf("Qapla'\n");
printf("Qu' buSHa'chugh SuvwI', batlhHa' vangchugh, qoj matlhHa'chugh, pagh ghaH SuvwI''e'.\n");
} else {
printf("luj\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");

check that command line input is numeric

if (argc != 2)

must be

if (argc == 2)

Doing

if isdigit(argv[1][i])
{
printf("Success!\n");
}

you will print "Success" 4 times if the number has 4 digits, better to do something like :

for (int i = 0, n = strlen(argv[1]); i < n; i++)
{
if (!isdigit(argv[1][i])
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
printf("Success!\n");
return 0;

Example :

#include <stdio.h>
#include <string.h>
#include <ctype.h>

int main(int argc, char * argv[])
{
if (argc == 2)
{
int i, n;

for (i = 0, n = strlen(argv[1]); i < n; i++)
{
if (!isdigit(argv[1][i]))
{
printf("Error. Second argument can be numbers only\n");
return 1;
}
}
printf("Success!\n");
}
else {
puts("argument is missing");
return 1;
}

return 0;
}

Compilation and executions :

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra c.c
pi@raspberrypi:/tmp $ ./a.out
argument is missing
pi@raspberrypi:/tmp $ ./a.out az
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $ ./a.out 12
Success!
pi@raspberrypi:/tmp $ ./a.out 12a
Error. Second argument can be numbers only
pi@raspberrypi:/tmp $

Execution under valgrind :

pi@raspberrypi:/tmp $ valgrind ./a.out 123
==2051== Memcheck, a memory error detector
==2051== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2051== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2051== Command: ./a.out 123
==2051==
Success!
==2051==
==2051== HEAP SUMMARY:
==2051== in use at exit: 0 bytes in 0 blocks
==2051== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated
==2051==
==2051== All heap blocks were freed -- no leaks are possible
==2051==
==2051== For counts of detected and suppressed errors, rerun with: -v
==2051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 3)

Checking whether input is number in C

For example, you can change it as follows.

#include <stdio.h>

#define doSomethingElse(input) do{ printf("your input is %d\n", input); }while(0)

int main(void){
int input;
int status;

while ((status = scanf("%d", &input)) != EOF) {
if ( status == 0 ) {
printf("Not a number\n");
while(getchar() != '\n'); //clear input
}
else {
doSomethingElse(input);
}
}
}

However, this can not check input like 123.456. (accept 123)

So, It is recommended to input with fgets and check with strtol.


As already pointed out, like scanf(" %s %d", string, &input) can not check the input after the number.

So, For convenience, check backward input.

char string[32], ch;
int input;
int status;


while ((status = scanf("%31s %d%c", string, &input, &ch )) != EOF) {
if ( status == 3 && ch == '\n') {
doSomethingElse(input);
}
else {
printf("Not a number\n");
while(getchar() != '\n'); //clear input
}
}

Example using fgets and strtol

(mystrtoi has reorganized the answer of chux. thanks)

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

#define doSomethingElse(input) do{ printf("your input is %d\n", input); }while(0)

int mystrtoi(const char *str, int *err) {
char *endptr;
*err = errno = 0;
long l = strtol(str, &endptr, 0);
if (errno == ERANGE || *endptr != '\0' || str == endptr) {
*err = 1;
}
// Only needed if sizeof(int) < sizeof(long)
if (l < INT_MIN || l > INT_MAX) {
*err = 1;
}
return (int) l;
}


int main(void){
char line[128];
char string1[32], string2[128];
int num, err;

while (fgets(line, sizeof line, stdin)){
// if(2 != sscanf(line, "%31s %31s", string1, string2)){// or use strtok to split
if(2 != sscanf(line, "%31s %127[^\n]", string1, string2)){
printf("invalid input\n");
continue;
}
num = mystrtoi(string2, &err);
if(err) {
printf("Not a number\n");
}
else {
doSomethingElse(num);
}
}
}


Related Topics



Leave a reply



Submit