2

Consider the following simple C program.

//C test

#include<stdio.h>

int main()
{
   int a, b, c;

   printf("Enter two numbers to add\n");
   scanf("%d%d",&a,&b);

   c = a + b;
   printf("Sum of entered numbers = %d\n",c);
   return 0;
}

How do you check the values entered are actually two integers in some sensible range? Currently, if you just enter "a" and then return you get the output "Sum of entered numbers = 32767".

Examples of incorrect input I would like to prevent.

  1. 2 3 4 (wrong number of numbers)
  2. apple (not a number)
  3. 11111111111111111111111111 1111111111111111111111111111111111111 (numbers out of range)

Or should I be using fgets and sscanf or even strtol ?

marshall
  • 2,443
  • 7
  • 25
  • 45

6 Answers6

2

You can use like:

if( scanf("%d%d",&a,&b) == 2)
{
   //two integer values has been read successfully
   //do your stuff here
}
else
{
   //Wrong input
}
Midhun MP
  • 103,496
  • 31
  • 153
  • 200
  • 2 3 4 is not reported as an error on input for some reason with your code and 111111111111111111111111111111 111111111111111111111111111111111111 gives the answer -2. – marshall Nov 28 '13 at 09:36
2

Also you can do this to prevent anything after second number

int a,b;
char c;
if( scanf("%d%d%c", &a, &b, &c) == 3) {
    if (c == '\n') {
        puts("good");
    }
} else {
    puts("bad");
}
    return 0;
}
Deck
  • 1,969
  • 4
  • 20
  • 41
2

User input is evil. Parse per:

(optional whitespace)[decimal int][whitespace][decimal int](optional whitespace)

strtol() and family have better error handling than scanf().
Coda: Best to handle user input in a helper function. Break into 2 parts: I/O and parsing.

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

// return 1 (success), -1 (EOF/IOError) or 0 (conversion failure)
int Readint(const char *prompt, int *dest, size_t n) {
  char buf[n * 21 * 2]; // big enough for `n` 64-bit int and then 2x

  fputs(prompt, stdout);  // do not use printf here to avoid UB
  fflush(stdout); // per @OP suggestion
  if (fgets(buf, sizeof buf, stdin) == NULL) {
    return -1;
  }
  const char *p = buf;

  while (n-- > 0) {
    char *endptr;
    errno = 0;
    long l = strtol(p, &endptr, 10);
    if (errno || (p == endptr) || (l < INT_MIN) || (l > INT_MAX)) {
      return 0;
    }
    *dest++ = (int) l;
    p = endptr;
  }

  // Trailing whitespace OK
  while (isspace((unsigned char) *p)) p++;
  // Still more text
  if (*p) return 0;
  return 1;
}

int main() {  // for testing
  int Result;
  do {
    int dest[2] = { -1 };
    Result = Readint("Enter two numbers to add\n", dest, 2);
    printf("%d %d %d\n", Result, dest[0], dest[1]);
  } while (Result >= 0);
  return 0;
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Thank you. Maybe add an `fflush()` after the `fputs()`, just in case the prompt doesn't include a `\n` at the end) ? Also, if you enter a number with 200 digits say, you get multiple outputs from your code. I am not sure why. Finally, is there any guarantee INT_MAX < LONG_MAX ? – marshall Nov 28 '13 at 16:23
  • @marshall The 200 digits is due to `buf[n * 21 * 2]`. Adjust size up as needed. One _could_ dynamically grow `buf` should `fgets()` get input without a `\n`. But that is primarily an IO issue and your post is that, but more of a parsing one. – chux - Reinstate Monica Nov 28 '13 at 18:20
  • @marshall INT_MAX <= LONG_MAX is certainly true. The `(l < INT_MIN) || (l > INT_MAX)` is there should `long` have a wider range than `int`. – chux - Reinstate Monica Nov 28 '13 at 18:21
1

You can use the following macro

#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
    char tmp;\
    while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
            || !(COND)) {\
        printf("Invalid input, please enter again: ");\
    }\
} while(0)

and you call it in this way in the main

int main()

{
    int a, b, c;

    printf("Input first integer, valid choice between 0 and 10: ");
    SCAN_ONEENTRY_WITHCHECK("%d",&a,(a>=0 && a<=10));

    printf("Input second integer, valid choice between 0 and 10: ");
    SCAN_ONEENTRY_WITHCHECK("%d",&b,(b>=0 && b<=10));

    c = a + b;
    printf("Sum of entered numbers = %d\n",c);
    return 0;

}

for more detail concerning this macro please refer to: Common macro to read input data and check its validity

Community
  • 1
  • 1
MOHAMED
  • 41,599
  • 58
  • 163
  • 268
0

A simple way would be,

int a=0, b=0, c=0;

initialise them to 0

Additionally, the check suggested by Midhun is good to check if there are two inputs.

Suvarna Pattayil
  • 5,136
  • 5
  • 32
  • 59
0

you can test this one.

#include <stdio.h>

int main(void)
{
    int a, b, c;

    printf("Enter two numbers to add\n");
    scanf("%d%d",&a,&b);

    if(scanf("%d%d",&a,&b) == 2)
    {
        c = a + b;
        printf("Sum of entered numbers = %d\n",c);
    }
    return 0;
}
sunnyleevip
  • 165
  • 1
  • 14