Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to verify that user input number is in fact a valid unsigned int in c

Tags:

c

I am writing a program in c that takes in an argument from a user on the command line but that argument has to be a valid unsigned int. For example if the user put in the value -1, then I would have to print an error code. Or if the user entered anything higher than 4294967295, then I would also print an error code.

I am unsure how to check if their input is within the correct range (0 and 4294967295).

like image 851
user3662531 Avatar asked Oct 16 '25 12:10

user3662531


2 Answers

to verify that user input number is in fact a valid unsigned int in c

strtoul() is the right function to use. It poses some problems as it accepts '-'. Let us assume leading whitespace is OK and check the front end of the string manually.

// 0: invalid, 1: valid
int unsigned_int_valid(const char *s) {

  while (isspace((unsigned char) *s) s++;
  // Fail on '-' as any negative number is out of range.
  if (*s == '-') return 0;  // Could add code to allow "-0"
  if (*s == '+') s++;
  if (!isdigit((unsigned char) *s) return 0;
  // Code knowns string begins with a digit

  errno = 0;     // Clear this global value as code tests it later.
  char *endptr;  // Pointer where parsing stopped.
  unsigned long ul = strtoul(s, &endptr, 0);

  // Usually this test is needed to see if _any_ conversion happened,
  // but code knowns the first character is a digit.
  #if 0
  if (s == endptr) return 0;
  #endif

  // Could march down the end of the string allowing trailing white-space
  while (isspace((unsigned char) *endptr) endptr++;

  // Extra text after the digits?
  if (*endptr) return 0;

  // Overflow?  strtoul sets `errno = ERANGE` when "outside the range" of unsigned long
  if (errno) return 0;

  #if ULONG_MAX > UINT_MAX
  // Does 'ul` value exceeds `unsigned` range?
  if (ul > UINT_MAX) return 0;
  #endif

  return 1;
}
like image 158
chux - Reinstate Monica Avatar answered Oct 19 '25 02:10

chux - Reinstate Monica


It can be implemented as follow:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
int main(int argc, char** argv)
{
    long long num;
    char * pEnd;
    if(argc>=2)
    {
        num = strtoll(argv[1], &pEnd, 10);
        if(pEnd==argv[1]||*pEnd!='\0'||num<0||num>UINT_MAX)
        {
           // printf("Error\n");
           //Generate error message
        }
        else
        {
            // printf("Success\n");
        }
    }
}

Using strtoll() to convert string to integer. strtoll() can be use to check whether input is number or not. Then check number is in range [0, 4294967295].

EDIT

As Luis Colorado comment

let's suppose we have the same problem with unsigned long long integers. How do we solve the problem then?

To solve this problem this approach may work with string comparison. This version generate error for -0 and success for 0 and was not handled there as OP doesn't clarify this situation.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#include<ctype.h>
void trimWhiteSpace(char *ch)
{
    int j=0, i=0;
    while(isspace((unsigned char)ch[i])) i++;
    while(isdigit(ch[i])) ch[j++]=ch[i++];
    ch[j]='\0';
}
int main(int argc, char** argv)
{
    unsigned long long num;
    char * pEnd;
    const int max_len = snprintf(NULL, 0, "%llu", ULONG_LONG_MAX);
    char max_num[max_len+1];
    snprintf(max_num, max_len+1, "%llu", ULONG_LONG_MAX);
    if(argc>=2)
    {
        trimWhiteSpace(argv[1]);
        int len = strlen(argv[1]);
        num = strtoll(argv[1], &pEnd, 10);
        if(len==0||*pEnd!='\0'||len>max_len||(len==max_len&&strcmp(argv[1], max_num)==1)||argv[1][0]=='-')
        {
            printf("Error\n");
            //Generate error message
        }
        else
        {
            //Success
            printf("Success: %llu\n", strtoull(argv[1], NULL, 10));
        }
    }
}
like image 26
ashiquzzaman33 Avatar answered Oct 19 '25 00:10

ashiquzzaman33