Using strtol to validate integer input in ANSI C

橙三吉。 提交于 2019-12-07 17:56:48

问题


I am new to programming and to C in general and am currently studying it at university. This is for an assignment so I would like to avoid direct answers but are more after tips or hints/pushes in the right direction.

I am trying to use strtol to validate my keyboard input, more specifically, test whether the input is numeric. I have looked over other questions on here and other sites and I have followed instructions given to other users but it hasn't helped me.

From what I have read/ understand of strtol (long int strtol (const char* str, char** endptr, int base);) if the endptr is not a null pointer the function will set the value of the endptr to the first character after the number.

So if I was to enter 84948ldfk, the endptr would point to 'l', telling me there is characters other than numbers in the input and which would make it invalid.

However in my case, what is happening, is that no matter what I enter, my program is returning an Invalid input. Here is my code:

void run_perf_square(int *option_stats)
{
   char input[MAX_NUM_INPUT + EXTRA_SPACES]; /*MAX_NUM_INPUT + EXTRA_SPACES are defined
                                              *in header file. MAX_NUM_INPUT = 7 
                                              *and EXTRA_SPACES 
                                              *(for '\n' and '\0') = 2. */
   char *ptr;
   unsigned num=0; /*num is unsigned as it was specified in the start up code for the 
                    *assignment. I am not allow to change it*/

   printf("Perfect Square\n");
   printf("--------------\n");
   printf("Enter a positive integer (1 - 1000000):\n");
   if(fgets(input, sizeof input, stdin) != NULL)
   {
      num=strtol(input, &ptr, 10);
      if( num > 1000001)
      {
         printf("Invalid Input! PLease enter a positive integer between 1 
                  and 1000000\n");
         read_rest_of_line();        /*clears buffer to avoid overflows*/
         run_perf_square(option_stats);
      }
      else if (num <= 0)
      {
         printf("Invalid Input! PLease enter a positive integer between 1 
                  and 1000000\n");
         run_perf_square(option_stats);
      }
      else if(ptr != NULL)
      {
         printf("Invalid Input! PLease enter a positive integer between 1 
                  and 1000000\n");
         run_perf_square(option_stats);
      }
      else
      {
         perfect_squares(option_stats, num);
      }
   }
}

Can anyone help me in the right direction? Obviously the error is with my if(ptr != NULL) condition, but as I understand it seems right. As I said, I have looked at previous questions similar to this and took the advice in the answers but it doesn't seem to work for me. Hence, I thought it best to ask for my help tailored to my own situation.

Thanks in advance!


回答1:


You're checking the outcome of strtol in the wrong order, check ptr first, also don't check ptr against NULL, derference it and check that it points to the NUL ('\0') string terminator.

if (*ptr == '\0') {
  // this means all characters were parsed and converted to `long`
}
else {
  // this means either no characters were parsed correctly in which
  // case the return value is completely invalid
  // or
  // there was a partial parsing of a number to `long` which is returned
  // and ptr points to the remaining string
}

num > 1000001 also needs to be num > 1000000

num < 0 also needs to be num < 1

You can also with some reorganising and logic tweaks collapse your sequence of if statements down to only a single invalid branch and a okay branch.




回答2:


OP would like to avoid direct answers ....

validate integer input

  1. Separate I/O from validation - 2 different functions.

  2. I/O: Assume hostile input. (Text, too much text, too little text. I/O errors.) Do you want to consume leading spaces as part of I/O? Do you want to consume leading 0 as part of I/O? (suggest not)

  3. Validate the string (NULL, lead space OK?, digits after a trailing space, too short, too long, under-range, over-range, Is 123.0 an OK integer)

  4. strtol() is your friend to do the heavy conversion lifting. Check how errno should be set and tested afterward. Use the endptr. Should its value be set before. How to test afterward. It consume leading spaces, is that OK? It converts text to a long, but OP wants the nebulous "integer".

Qapla'




回答3:


The function strtol returns long int, which is a signed value. I suggest that you use another variable (entry_num), which you could test for <0, thus detecting negative numbers.

I would also suggest that regex could test string input for digits and valid input, or you could use strtok and anything but digits as the delimiter ;-) Or you could scan the input string using validation, something like:

int validate_input ( char* input )
{
    char *p = input;
    if( !input ) return 0;
    for( p=input; *p && (isdigit(*p) || iswhite(*p)); ++p )
    {
    }
    if( *p ) return 0;
    return 1;
}


来源:https://stackoverflow.com/questions/19148611/using-strtol-to-validate-integer-input-in-ansi-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!