【问题标题】:C - Do-while followed by a switch with int cases. Validation is badC - Do-while 后跟一个带有 int 大小写的 switch。验证不好
【发布时间】:2018-01-22 21:03:43
【问题描述】:

我正在尝试在切换之前进行一段时间,以便我确定用户输入将匹配其中一种情况。但我这里有 1 个问题。

如果我给出例如输入“5a”,它仍将使用 5 来执行案例 5。我如何验证它以便用户只能给出确切的数字作为输入?

int move;
char validation[50];

do {
  printf("Input must be from 1 to 8:\n");
  fgets(validation, sizeof(validation), stdin);
  move = atoi(validation);
}
while (move < 1 || move > 8);

  switch (move) {
    case 1:
      dx = -1;
      dy = -1;
      break;
    case 2:
      dx = 0;
      dy = -1;
      break;
    case 3:
      dx = 1;
      dy = -1;
      break;
    case 4:
      dx = 1;
      dy = 0;
      break;
    case 5:
      dx = 1;
      dy = 1;
      break;
    case 6:
      dx = 0;
      dy = 1;
      break;
    case 7:
      dx = -1;
      dy = 1;
      break;
    case 8:
      dx = -1;
      dy = 0;
      break;
  }

【问题讨论】:

  • 乍一看,您的while 条件毫无意义,显然(move != 1) || (move != 2) 始终为真。
  • 伙计们谢谢你们的cmets!我现在编辑了它,但仍然遇到第二个问题!
  • 虽然条件仍然很差:应该是while (move &lt; 1 || move &gt; 8); 更好的是,设置为while (! isValid(move)),并让该函数执行您想要的所有额外有效性检查。
  • atoi() 将尽可能多地解析输入字符串;如果您想检测无效输入,您可能应该使用strtol() 并在完成后验证endptr指向字符串的末尾(通过检查*endptr == '\0' 很容易检测到)。
  • 非常重视this advice。当代码明确说明它的作用时,出现错误就变得非常困难,而当代码太复杂而无法阅读并立即知道它的作用时,它本身就是一个错误。

标签: c validation input case do-while


【解决方案1】:

您无法使用 atoi 检测 55a。我建议改用strtol()

long int strtol (const char *str, char **endptr, int base);

使用值endPtr 确保您的输入符合预期。

【讨论】:

    【解决方案2】:

    标准函数atoi 声明如下

    int atoi(const char *nptr);
    

    其实代表strtol的调用

    atoi: (int)strtol(nptr, (char **)NULL, 10)
    

    但与strtol相反,无法判断输入是否正确。

    所以直接使用strtol 而不是atoi

    这是一个演示程序

    #include <stdlib.h>
    #include <stdio.h>
    #include <ctype.h>
    
    int main(void) 
    {
        const int LOW_MOVE   = 1;
        const int UPPER_MOVE = 8;
    
        int move;
        char validation[50];
    
    
        int valid;
        do 
        {
            printf( "Input must be from %d to %d: ", LOW_MOVE, UPPER_MOVE );
            fgets( validation, sizeof( validation ), stdin );
    
            char *endptr;
            move = ( int )strtol( validation, &endptr, 10 );
    
            valid = endptr != validation;
            while ( valid && *endptr ) valid = isspace( ( unsigned char )*endptr++ );           
        } while ( !valid || move < LOW_MOVE || move > UPPER_MOVE );
    
        printf( "move = %d\n", move );
    
        return 0;
    }
    

    它的输出可能看起来像

    Input must be from 1 to 8: a
    Input must be from 1 to 8: 5a
    Input must be from 1 to 8: 5 a
    Input must be from 1 to 8: 5 5
    Input must be from 1 to 8: 5
    move = 5
    

    【讨论】:

    • 我刚试过这个,它可以工作,问题是当我输入太多错误的输入时,我输入了正确的输入,它仍然要求正确的输入:/
    • @RuiMartins 我不明白你是如何输入数据的。但是程序演示了不同的无效输入。
    • 问题是如果我输入错误程序不会让我输入正确的。
    • 程序只需要接受1到8,但是如果我输入例如8H它会再次要求输入,然后我输入8它不起作用。但是如果我一开始就放 8 就可以了
    • @RuiMartins 你试过演示程序吗?该程序不接受 8H。但无效输入 8H 后的 8 除外。程序输出显示了逻辑。
    【解决方案3】:

    您可以确保验证文本中只有数字。这是一些修改后的代码。对于 while 循环,您可以只检查它是否真的超出范围,而不是对 8 个成功案例进行单独匹配。

    int ensure_numeric(char *str) {
    
      while (str[0]) {
        if (str[0] >= '0' && str[0] <= '9') {
          str++;
          continue;
        }
        if (str[0] == '\r' || str[0] == '\n') {
          str++;
          continue;
        }
        break;
      }
    
      if (str[0]==0) return 0;
    
      return -1;
    
    }
    
    do {
      printf("Input must be from 1 to 8:\n");
      fgets(validation, sizeof(validation), stdin);
      move = atoi(validation);
      if (ensure_numeric(validation)) {
        printf("You did not enter all digits only.\n");
        move = 0;
      }
     }
     while (move < 1 || move > 8);
    

    【讨论】:

    猜你喜欢
    • 2014-06-17
    • 1970-01-01
    • 2021-03-08
    • 2023-03-12
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 2015-05-24
    • 1970-01-01
    相关资源
    最近更新 更多