使用strtol验证ANSI C中的整数输入

时间:2013-10-02 23:46:40

标签: c string ansi strtol

我是编程和C的新手,目前正在大学学习。这是一个任务,所以我想避免直接的答案,但更多的提示或提示/推动正确的方向。

我正在尝试使用strtol来验证我的键盘输入,更具体地说,测试输入是否为数字。我已经查看过这里和其他网站上的其他问题,我已经按照给其他用户的说明,但它没有帮助我。

从我读过/理解的 strtol (long int strtol(const char * str,char ** endptr,int base);)如果 endptr 是不是空指针,该函数会将 endptr 的值设置为数字后面的第一个字符。

因此,如果我要输入84948ldfk, endptr 将指向'l',告诉我输入中除了数字之外还有其他字符会使其无效。

然而在我的情况下,正在发生的事情是,无论我输入什么,我的程序都返回一个无效的输入。这是我的代码:

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);
      }
   }
}

任何人都可以帮助我朝正确的方向发展吗?显然错误是我的 if(ptr!= NULL)条件,但据我所知它似乎是正确的。正如我所说,我已经看过以前类似的问题,并在答案中提出了建议,但这似乎对我没有用。因此,我认为最好根据自己的情况寻求帮助。

提前致谢!

3 个答案:

答案 0 :(得分:5)

您正在以错误的顺序检查strtol的结果,首先检查ptr,也不要检查ptr对NULL,对其进行修改并检查它是否指向NUL'\0')字符串终结符。

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也需要num > 1000000

num < 0也需要num < 1

您还可以通过一些重组和逻辑调整将if语句序列折叠为仅 一个无效的分支和一个好的分支。

答案 1 :(得分:3)

OP希望避免直接回答......

验证整数输入

  1. 将I / O与验证分开 - 2个不同的功能。

  2. I / O:假设敌对输入。 (文本,文本太多,文本太少.I / O错误。)您是否希望将前导空格作为I / O的一部分使用?您想要将前导0作为I / O的一部分使用吗? (建议不要)

  3. 验证字符串(NULL,引导空间OK ?,尾随空格后的数字,太短,太长,欠范围,超范围,是123.0是否为正整数)

  4. strtol()是您的朋友,可以进行重型转换。检查以后应如何设置和测试errno。使用endptr。它的值是否应该在之前设定。以后如何测试。它消耗领先的空间,是吗?它将文本转换为long,但OP需要模糊的“整数”。

  5. Qapla'

答案 2 :(得分:0)

函数strtol返回long int,这是一个有符号值。我建议您使用另一个变量(entry_num),您可以测试&lt; 0,从而检测负数。

我还建议正则表达式可以测试数字和有效输入的字符串输入,或者你可以使用strtok和除数字之外的任何东西作为分隔符;-)或者你可以使用验证扫描输入字符串,如:

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;
}