【问题标题】:Restrict user input to 8 digit number将用户输入限制为 8 位数字
【发布时间】:2013-05-31 02:20:03
【问题描述】:

我希望用户输入一个 8 位数的帐号。除非您有多个字母,否则我的代码似乎适用于所有内容,即:“bbb”作为输入。如果发生这种情况,它会运行 3 次 while 循环,显示 printf,但不要求其他输入。

欢迎任何有关如何解决此问题或更好的解决方法的意见!

现在,我正在使用:

#include <stdio.h>

int main()
{
int return_val = 0;
int account_number = 0;
int within_range = 0;

printf("Please enter your 8 digit account number:\n");
return_val = scanf("%d", &account_number);
getchar();
getchar();

if((account_number > 9999999) && (account_number < 99999999))
{
    within_range = 1;
}

while ((return_val != 1) || (within_range != 1))  
{
    printf("Invalid account number. Account number must be 8 digits.\n");
    printf("Please enter your 8 digit account number: \n");
    //scanf("%d", &clear);
    return_val = scanf("%d", &account_number);
    getchar();
    getchar();

    if((account_number > 9999999) && (account_number < 99999999))
    {
        within_range = 1;
    }
}

printf("Account #: %d", account_number);
}

【问题讨论】:

  • 你应该把它读成一个字符串,然后验证它的长度和数字内容,最后转换成一个整数。

标签: c validation int


【解决方案1】:

如果您将输入读取为字符串(使用fgets)并使用sscanf 从那里解析它会有帮助吗?您不必担心额外的getchars。

#include <stdio.h>

int get_acct_num()
{
    char line[80];
    int  acct_num;
    int return_val = 0;
    printf("Please enter your 8 digit account number:\n");
    fgets ( line, sizeof ( line ), stdin );
    return_val = sscanf(line, "%d", &acct_num);
    if ( return_val != 1 )
        return ( 0 );
    if ( ( acct_num < 10000000 ) || ( acct_num > 99999999 ) )
        return ( 0 );

    return ( acct_num );
}

int main()
{
    int account_number = 0;
    while ( ! ( account_number = get_acct_num() ) )
        printf("Invalid account number. Account number must be 8 digits.\n");


    printf("Account #: %d", account_number);
}

【讨论】:

    【解决方案2】:

    在这种情况下最好解析一个字符串

    #include <ctype.h>
    ...
    
    char input[200];
    
    scanf("%s", input);
    
    int len = strlen(input);
    int dig = 0;
    
    if (len == 8) {
      for ( ; dig<len ; dig++) if ( ! isdigit(input[dig])) break;
    }
    
    if (dig == 8) printf("OK\n");
    else printf("Not ok\n");
    

    代码确保我们有 8 位数字,输入中没有其他内容(打印“OK”)。

    【讨论】:

      【解决方案3】:
      #include <stdio.h>
      #include <string.h>
      #include <ctype.h>
      #include <stdlib.h>
      int main()
      {
          int account_number = 0;
          int inval = 0;
          char acc_buf[256];
          printf("Please enter your 8 digit account number:\n");
          scanf("%s", acc_buf);
          if (strlen(acc_buf) == 8) {
              for (int i = 0; i < 8; i++)
                  if (!isdigit(acc_buf[i])) {
                      inval++;
                      break;
                  }
          } else inval++;
          if (!inval) {
              account_number = atoi(acc_buf);
              printf("Account #: %d\n", account_number);
          }
          return 0;
      }
      

      【讨论】:

      • 可以,但需要 。我很确定“%8d”只使用 就可以工作。
      【解决方案4】:

      我可以建议稍微重写一下吗?

      #include <stdio.h>
      #include <string.h> /* this is for strlen */
      #include <stdlib.h> /* this is for atoi */
      
      int main()
      {
          char input [55]; /* this is to store the user input */
      
          int account_number = 0;
      
          printf("Please enter your 8 digit account number:\n");
      
          while (fgets(input, 55, stdin)[0] == '\n')
              ;  /* this is a safer way to get input, loop until there is input, ignore new lines */
      
           account_number = atoi(input); /* convert to an int */
      
          if (account_number < 10000000 || account_number > 99999999) 
              return -1; 
          /* quit if invalid input */
      
          printf("Account #: %d\n", account_number);
      
          return 0;
      }
      

      编辑:我在这里使用了fgetsatoi,因为我认为熟悉这些功能会很好。话虽如此,atoi 不一定是转换为数字的最佳方式。 Strtol 更可靠,但使用起来有点复杂。

      这是在这种情况下使用strtol 的一种方式:

       char* temp = 0;
       account_number = strtol(input, &temp, 10); /* convert to an int */
      

      更多关于将字符串转换为数字的主题here

      EDIT-2: 考虑到chux的评论,循环也可以这样构造:

      char* out;
      do
      {
          out = fgets(input, 55, stdin);
      }
      while (out == NULL || out[0] == '\n')
          ;
      

      【讨论】:

      • 在极少数情况下,EOF(通过重定向输入)或 I/O 错误会导致 fgets() 返回 NULL。在这些特殊情况下,fgets(input, 55, stdin)[0] 可能会崩溃。
      • 注意,谢谢,我已经更新了我的帖子,提出了一种处理 NULL 的简单方法。
      【解决方案5】:

      我真的不喜欢使用scanf(),更喜欢fgets(),然后是sscanf()
      详情如下。
      2 条关键线:

      if (fgets(buf, sizeof(buf), stdin) == NULL)
      ...
      while (1 != sscanf(buf, " %8lu %c", &AccontNummner, &ch));
      

      解决方案

      #include <stdio.h>
      #include <stdlib.h>
      // Get 8 digit account number.  Returns -1 on I/O error or EOF
      // Parsing error just tries again.
      long Get8DigitAccountNumber(void) {
        const char *prompt = "Enter 8 digit account number: ";
        unsigned long AccontNummner;
        char ch;  // Extra text
        char buf[1024];
        do { // or while (1)
          ch = '\0';
          printf(prompt);
          fflush(stdout);  // Appears to be needed on some systems.
          prompt = "Error, try again: ";  // Used on re-try
          if (fgets(buf, sizeof(buf), stdin) == NULL) {
            return -1;  // handle I/O error
          }
        // If not _exactly_ one 1-8 digit field parsed, then try again.
        // Leading and trailing whitespaces are OK
        } while (1 != sscanf(buf, " %8lu %c", &AccontNummner, &ch));
        return (long) AccontNummner;
      }
      
      int main() {
        long AccontNummner;
        while ((AccontNummner = Get8DigitAccountNumber()) >= 0) {
          printf("# %lu\n", AccontNummner);
        }
        return 0;
      }
      

      如果您想准确地阅读 8 位数字...

        int n1 = 0;
        int n2 = 0;
        } while ((1 != sscanf(buf, " %n%8lu%n %c", &n1, &AccontNummner, &n2, &ch) || ((n2 - n1) != 8));
      

      可接受的格式:[可选空格][1-8 位][可选空格][仅此而已]
      sscanf() 格式:" %8lu %c"
      使用%u 而不是%d 不允许'-'
      明确允许可选的前导和尾随空格。
      %c 在 8 位数字之后捕获任何非白色字符。
      通过%c 扫描任何内容会导致sscanf() 返回2。

      【讨论】:

        【解决方案6】:

        我已经有一段时间没有用 C 中的格式化输入愚弄了,但尝试 scanf("%8d", &account_number);

        【讨论】:

        • 这不起作用。它最多查找 8 位输入,但不完全按照要求查找 8 位。
        • 我看不出哪里需要 8 位掩码,只需要 8 位输入。在这里推测,但这看起来像一个家庭作业,所以我认为使用 是一个错误(尽管这样做的好方法)。但是,您可以在 printf 语句的格式说明符中添加前导零以获得 8 位帐号。
        • 我确信这是一个家庭作业,但他已经做出了诚实的努力并且被卡住了。我相信这是一个 8 位掩码,因为他构造了他的原始代码,检查 8 位输入。
        • 如果是这样,那么我同意字符串是合适的。
        猜你喜欢
        • 1970-01-01
        • 2013-12-29
        • 2013-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-11-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多