我编写了一段代码,以帮助自己了解stdin
和stdout
涉及的内容。
这是我的代码:
#include<stdio.h>
#include<stdlib.h>
void prompt(){
int i=0;
printf("please select:\n"); //string1
printf("1.input\n2.print\n3.Exit\n"); //string2
scanf("%d",&i);
switch(i){
case 1:
printf("Data input!\n");
break;
case 2:
printf("data printed!\n");
break;
case 3:
exit(0);
case 10:
printf("Newline detected!"); //string3
default:
printf("Please input a valid number!(1-3)"); //string4
}
}
int main()
{
while(1)
prompt();
return 0;
}
我希望此代码的作用是:
但这绝不会发生。我看不到任何&#39; Newline被检测到了!&#34;在输出中,即使我输入数字4,也不在案例中。
任何人都可以详细说明此代码段的工作原理吗?
顺便说一句:我原先假设当stdout中有东西打印时,stdin缓冲区将自动刷新。但有些事实证明我错了。我的假设是真是假?
此外,当我输入一个字符(例如,一个g
)而不是一个数字时,我在屏幕上无限地打印了字符串1,字符串2,sring 4 。那是为什么?
编辑:在查看答案后,我制作了另一个片段,以帮助理解。
#include<stdio.h>
#include<stdlib.h>
void output();
int main()
{
int i;
printf("Enter a number here:\n");
scanf("%d",&i);
output();
return 0;
}
void output(){
char a;
if (scanf("%c",&a)!=1){
printf("scanf error!!");
exit(1);
}
switch(a){
case 'a':
printf("an char a is entered");
break;
case 'b':
printf("an char b is entered");
break;
default:
printf("%c",a);
printf("other thing is entered");
}
}
无论你在第一次程序提示你时输入,你都不会得到第二次提示。例如,当程序第一次提示您时,如果输入数字4,那么您将获得换行符和字符串&#34;输入其他内容&#34;印在你的屏幕上。这是为什么?
答案 0 :(得分:2)
因为在stdin缓冲区中仍然有一个换行符,在下一个循环中,变量'i'将自动获得换行符,在ACSII中为10
因此在打印完之后'请选择..1.input \ n2.print ....',会立即打印出一个字符串'Newline detected!'(字符串3)。
这是不正确的。当你使用
scanf("%d",&i);
忽略所有空格,包括换行符。
然后代码进入第三个循环,并提示我输入....
现在你知道它停留在第二个循环中,等待输入一个数字。
我原先假设当stdout中有东西打印时,stdin缓冲区将自动刷新。但有些事实证明我错了。我的假设是真是假?
这种假设是错误的。等待来自stdout
的输入时,stdin
会被刷新。
另外,当我输入一个字符(例如,一个g)而不是一个数字时,我得到字符串1,字符串2,在屏幕上无限打印4个。那是为什么?
那是因为程序在执行该行时无法读取该字符:
scanf("%d",&i);
字符保留在输入流中。您没有任何代码可以从输入流中删除该字符。这使程序保持无限循环。
答案 1 :(得分:1)
因为在stdin缓冲区中仍然有一个换行符 下一个循环,变量'i'将自动获得换行符 字符,在ACSII中是10
错误。 %d
将获得一个整数,直到遇到换行符或空格,并且下一个scanf()
因此请务必检查scanf()
if(scanf("%d",&i) != 1)
{
printf("scanf failed\n");
return 1;
}
作为旁注:
case 10:
printf("Newline detected!");
此案例中缺少break
。
答案 2 :(得分:1)
解决问题中的第二个程序,这是一个温和的修订版本。它打印更多信息,并使用严格的原型。
#include <stdio.h>
#include <stdlib.h>
void output(void);
int main(void)
{
int i;
printf("Enter a number here:\n");
if (scanf("%d", &i) == 1)
printf("Read %d OK\n", i);
output();
return 0;
}
void output(void)
{
char a;
if (scanf("%c", &a) != 1)
{
printf("scanf error!!");
exit(1);
}
printf("Character %d (%c) entered\n", a, a);
switch (a)
{
case 'a':
printf("an char a is entered\n");
break;
case 'b':
printf("an char b is entered\n");
break;
default:
printf("%c", a);
printf("other thing is entered\n");
break;
}
}
示例运行:
$ ./stdin
Enter a number here:
23499911
Read 23499911 OK
Character 10 (
) entered
other thing is entered
$ ./stdin
Enter a number here:
2A
Read 2 OK
Character 65 (A) entered
Aother thing is entered
$ ./stdin
Enter a number here:
19b
Read 19 OK
Character 98 (b) entered
an char b is entered
$ ./stdin
Enter a number here:
999a
Read 999 OK
Character 97 (a) entered
an char a is entered
$
请注意,在第一次运行中,迷路字符是第二个1
数字后面的换行符,字符代码为10.这是您应该得到的。
确保输出打印操作以换行符结束(以便及时显示)。如果不这样做,您的输出可能会无限期地保留。
您的意思是
scanf()
函数不会删除stdin
缓冲区中的换行符吗?
scanf("%d", &i)
肯定没有。 scanf("%c", &a)
确实如此。当scanf()
完成转换时,它会将不属于转换的字符放回到输入流中,为下一个输入操作做好准备。因此,无论数字后面是否有空格,字母或换行符,该字符是否已准备好进行下一个输入操作来读取它。大多数scanf()
操作会跳过前导空格。有三个例外:%c
,%n
和%[…]
(扫描集)。他们不会跳过领先的空白区域。