我在C
中有以下代码#include <stdio.h>
int main()
{
int number;
// printf() displays the formatted output
printf("Enter an integer: ");
// scanf() reads the formatted input and stores them
scanf("%d", &number);
// printf() displays the formatted output
printf("You entered: %d", number);
return 0;
}
答案 0 :(得分:3)
对于初学者,没有参数的函数main应声明为
AVPlayer
只需按以下方式更改您的程序
int main( void )
看看如果您尝试输入字符#include <stdio.h>
int main( void )
{
int number;
// printf() displays the formatted output
printf("Enter an integer: ");
// scanf() reads the formatted input and stores them
if (scanf("%d", &number) == 1)
{
// printf() displays the formatted output
printf("You entered: %d\n", number);
}
else
{
puts("Invalid input");
}
return 0;
}
而不是数字会发生什么。
根据C标准中的功能描述(7.21.6.2 fscanf功能)
d匹配可选的带符号十进制整数,其格式为 与 strtol 功能的主题序列的预期相同 基本参数的值10。相应的论点应该是 指向有符号整数的指针。
和(7.22.1.4 strtol,strtoll,strtoul和strtoull函数)
7 如果主题序列为空或没有预期 表单,不执行转换; nptr的值存储在 endptr指向的对象,前提是endptr不是null 指针。
因此在演示程序中将执行else语句,因为(C标准,7.21.6.2 fscanf函数)
16如果输入,fscanf函数返回宏EOF的值 在第一次转换(如果有)完成之前发生故障。 否则,该函数返回分配的输入项数, 在发生的情况下,可能会少于,甚至为零 早期匹配失败
答案 1 :(得分:2)
你陷入了同样的陷阱,在尝试用它输入用户输入之前,几乎所有没有花时间完全理解scanf
函数族的新C程序员陷入困境。
在详细说明之前,无论何时进行用户输入,都必须 验证 输入。这意味着检查用于验证输入的任何函数的返回实际上已接收,并且如有必要,验证收到的输入是否在您的代码的预期/可接受的值范围内。使用scanf
也不例外。
用户输入的首选方法是fgets
,因为它避免了scanf
中固有的陷阱并且完全消耗了每一行输入(假设缓冲区足够大,或者重复调用它直到你验证最后读取的字符是'\n'
)
使用scanf
,如果(1)成功输入或(2)输入或匹配失败,由您自行决定并删除stdin
中保留的任何字符其中输入的其他尝试将随之而来。
要安全地使用scanf
进行用户输入,您有三个条件需要测试,(1)返回是否表示发生了格式字符串中指定的所有转换?如果是,请清空stdin
并检查根据需要收到的值范围。 (2)用户在'\n'
- (取决于OS&amp;编译器);最后(3)发生匹配或输入失败?如果是,请处理错误并清空stdin
中的任何无效字符。
当您接受用户输入时,无效输入对您没有好处。因此,您通常希望循环直到您收到有效输入或用户取消,这可以通过简单的无限循环相对容易地完成,例如
/** empty all characters reamining in stdin */
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
...
for (;;) { /* loop until valid input or user cancels */
int rtn = 0; /* variable to capture scanf return */
/* printf() displays the formatted output */
printf ("Enter an integer: ");
/* scanf() reads the formatted input and stores them */
rtn = scanf ("%d", &number);
if (rtn == 1) { /* we got an integer value */
empty_stdin(); /* empty any remaining characters */
break; /* continue with program */
}
else if (rtn == EOF) { /* user canceled with ctrl+d (ctrl+z on win) */
fprintf (stderr, "user canceled input.\n");
return 1;
}
/* handle input or matching failure */
fprintf (stderr, "error: matching or input failure occurred.\n");
empty_stdin(); /* empty any remaining characters */
}
通过输入循环,您将注意到必须检查的三个条件中的每一个都被处理,并且stdin
中保留的任何字符都被清空以准备下一个输入。您的完整代码只输出成功输入的结果(如果在Windows上,则添加最终getchar();
以防止终端窗口在运行IDE时关闭,例如
#include <stdio.h>
/** empty all characters reamining in stdin */
void empty_stdin()
{
int c = getchar();
while (c != '\n' && c != EOF)
c = getchar();
}
int main (void) {
int number = 0;
for (;;) { /* loop until valid input or user cancels */
int rtn = 0; /* variable to capture scanf return */
/* printf() displays the formatted output */
printf ("Enter an integer: ");
/* scanf() reads the formatted input and stores them */
rtn = scanf ("%d", &number);
if (rtn == 1) { /* we got an integer value */
empty_stdin(); /* empty any remaining characters */
break; /* continue with program */
}
else if (rtn == EOF) { /* user canceled with ctrl+d (ctrl+z on win) */
fprintf (stderr, "user canceled input.\n");
return 1;
}
/* handle input or matching failure */
fprintf (stderr, "error: matching or input failure occurred.\n");
empty_stdin(); /* empty any remaining characters */
}
/* printf() displays the formatted output */
printf ("You entered: %d\n", number);
#if defined (_WIN32) || defined (_WIN64)
getchar (); /* to hold terminal open -- don't use getch() */
#endif
return 0;
}
示例使用/输出
$ ./bin/scanf_int
Enter an integer: apples
error: matching or input failure occurred.
Enter an integer: a 10 b 50 c 90
error: matching or input failure occurred.
Enter an integer: 12345aaa
You entered: 12345
取消输入的示例。 (注意:在Win10上,ctrl + z默认不生成EOF
,请参阅CTRL+Z does not generate EOF in Windows 10 | PROC-X.com)
$ ./bin/scanf_int
Enter an integer: NO!
error: matching or input failure occurred.
Enter an integer: user canceled input.
仔细看看,如果您有其他问题,请告诉我。
答案 2 :(得分:1)
我认为“scanf()”不会像数字一样读取“a”而只是跳过将任意数字放入“number”中,而29是堆栈中找到的数字的初始值!
尝试用123之类的东西初始化“数字”,你将得到123输出。
答案 3 :(得分:1)
%d
期望在输入流中看到一个或多个十进制数字; ’a’
不是十进制数字,因此您得到匹配失败 - number
未更新,a
保留在输入流中,{{1返回0表示没有发生转换和赋值。
由于您在声明时未初始化scanf
,因此它包含 indeterminate 值,在本例中为number
。
C不会对意外输入使用异常 - 您必须检查29
的返回值。
scanf