C: Scanf 在类型不匹配中被忽略
C: Scanf Ignored in Type Mismatch
是的,SO 上已经有类似的问题 scanf()
在“解释”回车键之前不等待用户输入,但我的问题是这个问题只发生在扫描时——这是 %ld
(前面有一个 space)——读取一个字符串而不是另一个长数字。如果此摘要看起来令人费解,请在下面查看详细信息。
我在 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("INVALID\n");
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
没有从用户那里收到正确的输入类型时才会发生。有人可以帮忙吗?
提前致谢。
how not all invalid inputs will result in this bug!)
如果您输入的不是数字,则 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 中的 return 值说明。
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-exiting-of-functions .
如果您输入的不是整数,那么您需要从输入缓冲区中删除无效输入。
这是一个演示程序。
#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 = %ld\n", x );
return 0;
}
控制台输出可能类似于
A
12
x = 12
请注意,使用 goto
语句是一种糟糕的编程风格。相反,您可以使用我的程序中显示的 do-while 语句。这实际上是您程序中的 goto
语句是多余的。
是的,SO 上已经有类似的问题 scanf()
在“解释”回车键之前不等待用户输入,但我的问题是这个问题只发生在扫描时——这是 %ld
(前面有一个 space)——读取一个字符串而不是另一个长数字。如果此摘要看起来令人费解,请在下面查看详细信息。
我在 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("INVALID\n");
goto LOOP;
}
validate = false;
// ... (validate will be processed here, and there will be a case where "validate" will be true)
}
while (validate != true);
}
输入:
4003600000000014
:有效,长度为 16400360000000001
:打印INVALID
,长度为15asdf
:无限循环(注意并非所有无效输入都会导致此错误!)
Number: INVALID
Number: INVALID
Number: INVALID
...
我在别处读到 scanf
会忽略最后一行缓冲区(或其他内容),但在我的例子中,只有当 scanf
没有从用户那里收到正确的输入类型时才会发生。有人可以帮忙吗?
提前致谢。
how not all invalid inputs will result in this bug!)
如果您输入的不是数字,则 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 中的 return 值说明。
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-exiting-of-functions .
如果您输入的不是整数,那么您需要从输入缓冲区中删除无效输入。
这是一个演示程序。
#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 = %ld\n", x );
return 0;
}
控制台输出可能类似于
A
12
x = 12
请注意,使用 goto
语句是一种糟糕的编程风格。相反,您可以使用我的程序中显示的 do-while 语句。这实际上是您程序中的 goto
语句是多余的。