【问题标题】:How to delete garbage characters from input in C如何从C中的输入中删除垃圾字符
【发布时间】:2019-01-28 03:19:30
【问题描述】:

我有一段代码可用于输入验证,我需要更多解释它为什么起作用。垃圾变量从 getchar 读取一个字符并检查它是否不等于 EOF 的行让我有点困惑。它的目的是从用户那里读取垃圾输入,并允许用户重新输入输入。我的问题是,这条线到底是如何工作的?

  int steps = 0;                                                
  int true;                                                 
  int garbage;                                              

printf("Enter the integer increment number in the range ");  
printf("of[%d - %d]: ", minInput, maxInput);
true = scanf("%d", &steps);

/* INPUT VALIDATION */

while (!true || isdigit(steps) ||(steps < minInput || steps > maxInput) ){  
    while ((garbage = getchar()) != EOF && garbage != '\n') {                   
    } // end while;

    printf("Invalid input... please enter a number in the range ");
    printf("of[%d - %d]: ", minInput, maxInput);
    true = scanf("%d", &steps);

}// end while

【问题讨论】:

  • isdigit(steps) 是我看到的第一个逻辑有问题的东西。它从未被读取为字符 (%c),它被读取为整数十进制 (%d)。该函数所做的只是测试一个字符在'0'...'9' 中的成员资格。 0..9 的值(整数值;不是字符)将永远导致 isdigit(steps) 为真,因此在您的条件中毫无意义。
  • true 是一个相当不明智的变量名称 - 它通常指的是一个值而不是变量,并且会与符号的 stdbool.h 定义冲突并排除 C++ 编译。
  • scanf("%d", &amp;steps)返回EOF时,while (...) { }是一个无限循环。

标签: c validation input


【解决方案1】:

带有%d 格式说明符的scanf() 调用将仅检索十进制数字字符,并在第一个非数字字符处停止解释输入。但是,在缓冲完整的行之前,它通常根本不会返回,因此至少会缓冲一个换行符,并且可能还有其他非数字字符。

while ((garbage = getchar()) != EOF && garbage != '\n')

语句读取所有缓冲的字符,直到行尾或 EOF。虽然控制台输入流发出“文件结尾”可能是不寻常的,但标准输入流可以从文件重定向,不需要引用控制台输入。 EOF 可以通过依赖于平台的 CTRL 代码插入到控制台输入流中,并且当从文件重定向时,如果文件包含没有换行符的行,则循环不会终止。

isdigit(steps) 的使用不正确 - steps 是一个整数值,isdigit() 测试一个 单个 字符值以确定它是否代表十进制数字。 steps 隐含地是一个有效值,因为 true 是非零且 %d 格式说明符,所以如果意图确定输入了一个数字,那么这就是 true 的用途。

【讨论】:

  • "steps 是一个隐含的有效值,因为 true 是非零的" --> 当 true == 1 时是这样。当true == EOFsteps 未被触及或不确定时,这是不正确的。 1EOF 都非零。