如何解决控制台I / O:未按预期顺序出现printf和scanf
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void eat() // clears stdin upto and including \n OR EOF
{
int eat;while ((eat = getchar()) != '\n' && eat != EOF);
}
int main(){
printf("\n COMMAND : "); char cmd[21]=""; scanf("%20s",cmd);
if(strcmp(cmd,"shell")==0||strcmp(cmd,"sh")==0)
{
getchar(); // absorb whitespace char separating 'shell' and the command,say 'ls'
while(1)
{
printf("\n sh >>> "); // print prompt
char shellcmd[1024]=""; // str to store command
scanf("%1023[^\n]",shellcmd); eat(); // take input of command and clear stdin
if(strcmp("close",shellcmd)==0||strcmp("x",shellcmd)==0)
break;
else
system(shellcmd);
}
}
}
在代码中,发生了一些我无法捕捉到的异常行为。
输入sh ls
并按[ENTER]
后,预期响应为:
- 第一个
scanf()
将sh
存储在cmd[]
中,并将ls\n
保留在stdin
中。 -
getchar()
占用 -
printf()
将\n sh >>>
打印到终端机 - 第二
scanf()
将ls
存储在shellcmd[]
中,将\n
保留在stdin中 -
eat()
从标准输入读取\n
,将其留空 -
system("ls")
被执行
即结果应该是这样的:
COMMAND : sh ls
sh >>>
file1 file 2 file3 ...
sh >>> | (cursor)
但是
我得到的是
COMMAND : sh ls
file1 file2 file3 ...
sh >>>
sh >>> |
显然,第二个scanf()
和shell()
正在之前 printf()
执行,或者至少是我的假设。 >
什么不对?
使用cc -Wall -Wextra -pedantic
在Clang和GCC上进行了编译,并在MacOS和Linux上的bash上进行了测试
解决方法
在man page中可以找到:
如果流指向终端(如stdout通常那样),则它是行缓冲的
因此,当printf
所打印的消息不包含换行符时,您可能会遇到延迟。另一方面,发送下一个printf
的前导换行符后,就会显示previos消息。
解决方案:
-
在您的消息
的末尾添加换行符printf("\n sh >>> \n");
-
通过调用
flush()
函数(fflush(stdout)
)强制即使没有换行符也要显示当前缓冲区 -
使用
setvbuf()
函数更改当前的 stdout 缓冲行为setvbuf(stdout,NULL,_IONBF,0);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。