【问题标题】:Data validation in C - ensuring the input is in a correct formatC 中的数据验证 - 确保输入格式正确
【发布时间】:2016-05-15 19:41:05
【问题描述】:

我想编写一个代码来确保用户只输入一位数字。如果用户输入“0 1 3”之类的内容,我希望我的程序读取一条我不知道该怎么做的错误消息。任何人都知道如何解决这个问题?如果用户输入一堆中间有空格的数字,我当前的代码只接受第一个数字。

请在下面查看我的代码。谢谢:D

//Prompt the user to enter the low radius with data validation
printf("Enter the low radius [0.0..40.0]: ");
do
{   
    ret = scanf("%lf", &lowRadius);
    //type validation
    if (ret != 1)
    {
        int ch = 0;
        while (((ch = getchar()) != EOF) && (ch != '\n'));
        printf("Wrong input. Please enter one numerical value: ");  
    }
    //range validation      
    else if((lowRadius < 0 || lowRadius > 40))
    {
        printf("Incorrect value. Please enter in range 0-40: ");
    }
    else break;
} while ((ret != 1) || (lowRadius < 0 || lowRadius > 40));//end while lowRadius

【问题讨论】:

  • 你已经有代码了。使用getchar 从输入中读取,直到找到换行符。如果换行符之前有任何非空白字符,则输入无效。此外,您不需要do {} while 循环,因为无论如何您都在使用break。一个简单的while(1){}for(;;){} 循环将起作用。输入有效时只需break循环。
  • 那是因为 scanf 在很多层面上都是不安全的。请参阅this post 了解为什么不建议使用它,以及另一种选择。此外,您应该考虑使用外部或第 3 部分库来安全地解析您的输入。
  • 用户如何使用单个数字输入像39 这样的值?你的意思是“一个数字”吗?那么分数(39.23423)呢?正如您已经被告知的那样,scanf() 很可能不是工具。使用fgets()读取一行,然后可能sscanf()strtod()转换值,仔细处理错误情况并检查数字之后和换行之前是否有任何碎片。

标签: c validation


【解决方案1】:

如果将行读入字符串,然后对其进行分析,则可以避免挂在未提供的输入上的问题。您已经完成了大部分工作,但这显示了如何捕获过多的输入。它通过扫描double 之后的字符串来获取更多输入。 sscanf 的返回值告诉您是否存在,因为它返回成功扫描的项目数。

#include <stdio.h>
#include <stdlib.h>

void err(char *message)
{
    puts(message);
    exit(1);
}

int main(void)
{
    double lowRadius = 0.0;
    char inp[100];
    char more[2];
    int conv;
    if(fgets(inp, sizeof inp, stdin) == NULL) {
        err("Input unsuccesful");
    }
    conv = sscanf(inp, "%lf %1s", &lowRadius, more);  // conv is number of items scanned
    if(conv != 1) {
        err("One input value is required");
    }
    if(lowRadius < 0.0 || lowRadius > 40.0) {
        err("Number out of range");
    }
    printf("%f\n", lowRadius);
    return 0;
}

我不确定您对单个数字的规定,因为这不允许您输入最大值。

【讨论】:

    【解决方案2】:

    读取整行并将其转换为strtod

    【讨论】:

    • 这不是一个好的答案。您至少应该提供strdod 调用示例。
    【解决方案3】:

    亚历山大有正确的方法,但没有提供太多细节。这是我的做法,使用 getline() 读取输入,然后使用 strspn() 加上 strtod() 来解析读取的输入。如果您不熟悉使用指针,这将很难理解 - 但如果您正在学习 C,您最终会到达那里:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void) {
      double lowRadius;
      char *lineptr = NULL;
      size_t n;
      char *startptr;
      char *endptr;
      char *ws = " \t\n"; /* possible whitespace characters */
    
      printf("Enter the low radius [0.0..40.0]: ");
    
      while(1) {
        /* free lineptr if set - neeeded if we iterate on error input */
        if( lineptr ) {
          free(lineptr);
          lineptr = NULL;
        }
    
        /* now read a line of input */
        while( getline(&lineptr, &n, stdin) == -1 ) {
          /* error returned, just retry */
          continue;
        }
    
        /* skip over any leading whitespace */
        startptr = lineptr + strspn(lineptr,ws);
    
        /* Now try to convert double */
        lowRadius = strtod(startptr, &endptr);
    
        if( endptr==startptr || endptr[strspn(endptr,ws)] != 0 ) {
          /* either no characters were processed - e.g., the
             line was empty, or there was some non-whitespace
             character found after the number. */
          printf( "Wrong input.  Please enter one numerical value: ");
        } else if( (lowRadius < 0.0) || (lowRadius > 40.0) ) {
          printf( "Incorrect value. Please enter in range 0-40: " );
        } else {
          if( lineptr ) free(lineptr);
          break;
        }
      }
      printf( "value entered was %lf\n", lowRadius );
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-01-13
      • 2023-02-04
      • 2011-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多