C:类型不匹配时忽略扫描



是的,SO上已经存在类似的问题,即scanf()在"解释";回车键,但我的问题是,只有当扫描(%ld(前面有一个空格(读取字符串而不是另一个长数字时,才会出现这个问题。如果这个摘要看起来很复杂,详细信息如下。

我在C中有以下程序:

#include <stdio.h>
#include <stdbool.h>
int main(void)
{
long int cardnum, tmp;
int num_of_digits;
bool validate; // valid value
LOOP:do
{
printf("Number: ");
scanf(" %ld", &cardnum);
tmp = cardnum, num_of_digits = 0;
while (tmp != 0)
{
tmp /= 10;
++num_of_digits;
}
if (num_of_digits != 16)
{
printf("INVALIDn");
goto LOOP;
}
validate = false;
// ... (validate will be processed here, and there will be a case where "validate" will be true)
}
while (validate != true);
}

输入:

  • 4003600000000014:作品,长度16
  • 400360000000001:打印INVALID,长度为15
  • asdf:无限循环(注意并非所有无效输入都会导致此错误!(
Number: INVALID
Number: INVALID
Number: INVALID
...

我在其他地方读到scanf忽略了最后一行缓冲区(或其他什么(,但在我的情况下,只有当scanf没有从用户那里接收到正确的输入类型时才会发生这种情况。有人能帮忙吗?

提前谢谢。

不是所有无效的输入都会导致这个错误!(

如果您的输入不是数字,则scanf将失败。因此,检查它是否未能扫描数字,如果扫描失败,则忽略输入,直到行的末尾。注意-您也应该处理EOF

if (scanf(...) != 1) {
int c;
// ignore input
while ((c = getchar()) != EOF) {
// until a newline!
if (c == 'n') {
break;
}
}
// when eof
if (c == EOF) {
// then exit our program with a failure!
printf("ERROR: End of input!");
exit(-1);
}
// if not eof, means user is ready to enter yet another line
printf("you inputted an invalid line - please input a line consisting of digits only!");
continue;
}

请参阅cppreference scanf中的返回值描述。


LOOP:do {goto LOOP;看起来像是一个可怕的想法——不要在那里使用goto,这似乎令人困惑。相反,您更喜欢重新构造代码,这样就不必使用goto。例如:

for (;;) {
if (some_check) {
continue;
}
if (some_another_check) {
continue;
}
// if we get here, means all checks succeeded - so we need to break
break;
}

goto有很好的用途,而且它恰好被使用了——参见前。https://www.kernel.org/doc/html/v4.10/process/coding-style.html#centralized-功能的退出。

如果您输入的不是整数,则需要从输入缓冲区中删除无效输入。

这是一个示范节目。

#include <stdio.h>
int main(void) 
{
long int x;
int valid;

do
{
if ( !( valid = ( scanf( " %ld", &x ) == 1 ) ) && valid != EOF )
{
scanf( "%*[^n]%*c");
}
} while ( !valid );

printf( "x = %ldn", x );

return 0;
}

控制台输出可能看起来像

A
12
x = 12

请注意,使用goto语句是一种糟糕的编程风格。相反,您可以使用dowhile语句,因为它在我的程序中显示。事实上,程序中的goto语句是多余的。

最新更新