1

I need to read a positive number only (unsigned long long), a nothing is more, so I use scanf("%llu", &num);. But it also allows to input negative values.
How to validate positive numbers in this case? The user must input a positive number in [0..2^(64)-1] but he can miss and input a negative value in same interval. But I can't declare a long long variable to check it cuz it can contain 2^64 - 1 totally.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Denis Sologub
  • 7,277
  • 11
  • 56
  • 123

2 Answers2

2

Read the number as a string with fgets(), then validate it, e.g. with strchr(). Finally use strtoull() to convert the string to number, which will fail if the number is out range:

If the value read is out of the range of representable values by an unsigned long long int, the function returns ULLONG_MAX (defined in <limits.h>), and errno is set to ERANGE.

Example:

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

int main(void) {
    char str[100]=;
    fgets(str, sizeof(str), stdin);
    str[strcspn(str, "\n")] = '\0';

    if(strchr(str, '-') == NULL) {
        printf("Not a negative number\n");
        unsigned long long number = strtoull (str, NULL, 10);
        printf("%llu\n", number);
    } else {
        printf("Negative number\n");
    }

    return 0;
}

Output:

Not a negative number
12343566

and for -12343566, it gives:

Negative number
gsamaras
  • 71,951
  • 46
  • 188
  • 305
1

You could read the input into a character array using fgets(), check if the first character is -ve symbol a character other than a digit and then use strtoull() to convert it to unsigned long long.

char c, buff[100];
fgets(buff, sizeof(buff), stdin);
//sscanf(buff, "%*[ ]%c", &c);
sscanf(buff, "%s", buff);
//if( (c<'0' || c>'9') )
if(buff[0]<'0' || buff[0]>'9')
{
     printf("\nNegative or invalid number!");
}
else
{
     num=strtoull(buff, NULL, 10);
}    

strtoull() will return ULLONG_MAX (defined in limits.h) and sets errno to ERANGE(to use these, errno.h header file must be included) if the value returned by it won't fit in an unsigned long long.

if(num==ULLONG_MAX && errno==ERANGE)
{
    printf("\nOverflow");
}

The %*[ ] in the sscanf() is used to ignore the leading white spaces in the string. The first non-space character is found and stored in c whose value is checked.

As explained here, sscanf(buff, "%s", buff); would trim the string buff on both sides to get rid of the spaces.

J...S
  • 5,079
  • 1
  • 20
  • 35