为什么scanf(“d”和“number”)会产生结果';a';C编程中的as 29?
我有一个C代码为什么scanf(“d”和“number”)会产生结果';a';C编程中的as 29?,c,scanf,C,Scanf,我有一个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() di
#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;
}
#包括
int main()
{
整数;
//printf()显示格式化的输出
printf(“输入一个整数:”);
//scanf()读取格式化的输入并存储它们
scanf(“%d”和编号);
//printf()显示格式化的输出
printf(“您输入了:%d”,编号);
返回0;
}
这里我需要输入一个数字,但我输入了一个字符“a”,结果是29。我期望它会抛出一个异常,但我对一个输出感到惊讶。
我认为“scanf()”没有将“a”读作数字,只是跳过将任何数字放入“number”中,29是堆栈中找到的数字的初始值
尝试用123之类的东西初始化“number”,输出中会得到123。对于初学者,不带参数的函数main应声明为
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;
}
#包括
内部主(空)
{
整数;
//printf()显示格式化的输出
printf(“输入一个整数:”);
//scanf()读取格式化的输入并存储它们
if(scanf(“%d”,&number)==1)
{
//printf()显示格式化的输出
printf(“您输入了:%d\n”,编号);
}
其他的
{
puts(“无效输入”);
}
返回0;
}
并查看如果您尝试输入字符'a'
而不是数字会发生什么
根据C标准中的功能描述(7.21.6.2 fscanf功能)
d匹配可选带符号的十进制整数,其格式为
与使用基本参数的值为10。相应的论点应为: 指向有符号整数的指针 和(7.22.1.4 strtol、strtoll、strtoul和strtoull功能) 7如果主题序列为空或没有预期的 形式,不进行转换nptr的值存储在 由endptr指向的对象,前提是endptr不是null 指针 因此,在演示程序中,将执行else语句,因为(C标准,7.21.6.2 fscanf函数) 16如果输入错误,fscanf函数返回宏EOF的值 在第一次转换(如果有)完成之前发生故障。 否则,函数将返回分配的输入项的数量, 如果发生以下情况,该值可以小于规定值,甚至为零 早期匹配失败
实际上,所有新的C程序员都陷入了同样的陷阱,他们在尝试接受用户输入之前,没有花时间完全理解
scanf
函数族
在了解具体情况之前,无论何时接受用户输入,都必须验证输入。这意味着检查用于验证输入的任何函数的返回,如果需要,验证接收的输入是否在代码的预期/可接受值范围内。使用scanf
也不例外
用户输入的首选方法是fgets
,因为它避免了scanf
中固有的缺陷,并且完全消耗了每行输入(前提是缓冲区足够大,或者在验证最后读取的字符是否为'\n'
之前重复调用缓冲区)
使用scanf
,如果(1)输入成功或(2)输入或匹配失败,随后会有更多的输入尝试,则由您负责解释并删除stdin
中保留的任何字符
为了安全地使用scanf
进行用户输入,您需要测试三个条件:(1)返回值是否指示在格式字符串中指定的所有转换都发生了?如果是这样,清空标准DIN,并根据需要检查接收到的数值范围。(2) 用户是否通过按Ctrl+d(或windoze上的Ctrl+z)取消输入。如果是这样,请优雅地退出,确保输出中提供了最终的“\n”
(取决于操作系统和编译器);最后(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上,则添加一个finalgetchar();
,以防止在使用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;
}
取消输入的示例。(注意:在Win10上,ctrl+z默认情况下不会生成EOF
,请参阅)
仔细检查一下,如果您还有其他问题,请告诉我。
%d
希望在输入流中看到一个或多个十进制数字;'a'
不是十进制数字,因此您会得到匹配失败-数字
未更新,a
保留在输入流中,而scanf
将0返回到indicate未发生任何转换和分配
由于您在声明编号时没有初始化编号,因此它包含一个不确定的值,在本例中为29
C不会对意外输入使用异常-您必须检查scanf
的返回值
int result = scanf( “%d”, &number );
if ( result == 1 )
{
// user entered one or more decimal digits for number
}
else if ( result == 0 )
{
// user entered something that isn’t a decimal digit
}
else // result == EOF
{
// EOF or error detected on input
}
你从哪里读到C有异常?检查那些可能使你的文档失败的函数的返回值,查看
scanf
sho
$ ./bin/scanf_int
Enter an integer: NO!
error: matching or input failure occurred.
Enter an integer: user canceled input.
int result = scanf( “%d”, &number );
if ( result == 1 )
{
// user entered one or more decimal digits for number
}
else if ( result == 0 )
{
// user entered something that isn’t a decimal digit
}
else // result == EOF
{
// EOF or error detected on input
}