3

我是编程和一般 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)条件有关,但据我所知,这似乎是正确的。正如我所说,我已经查看了与此类似的先前问题并在答案中采纳了建议,但它似乎对我不起作用。因此,我认为最好根据自己的情况寻求我的帮助。

提前致谢!

4

3 回答 3

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 语句序列折叠为仅一个无效分支和一个正常分支。

于 2013-10-02T23:50:45.483 回答
3

OP想避免直接回答....

验证整数输入

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

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

  3. 验证字符串(NULL,前导空格好吗?,尾随空格后的数字,太短,太长,低于范围,超出范围,123.0 是一个 OK 整数)

  4. strtol()是你的朋友做繁重的转换提升。之后检查errno应该如何设置和测试。使用endptr. 是否应该在之前设置它的值。以后怎么考。它消耗前导空格,可以吗?它将文本转换为 a long,但 OP 想要模糊的“整数”。

卡普拉

于 2013-10-03T03:30:31.100 回答
0

函数 strtol 返回 long int,它是一个有符号值。我建议您使用另一个变量 (entry_num),您可以测试它是否为 <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;
}
于 2013-10-03T03:09:32.847 回答