printf函数使用了行缓冲,只有输出了换行符才刷新输出。但如果需要读取用户输入,同样会刷新stdout的输出缓冲,而不论是否有换行。
// 输入整数 a,输出a的平方
#include <stdio.h>
int main(void){
int a;
printf("input a:");
scanf("%d", &a);
printf("%d*%d=%d\n", a, a, a*a);
}
# gcc编译生成windows原生程序;mintty 下运行
$ gcc -dumpmachine
x86_64-w64-mingw32
$ make test3
gcc --std=c11 -Wall -O2 -c -o test3.o test3.c
gcc test3.o -o test3
$ ./test3
12
input a:12*12=144
在cmd下运行就可以
F:\test>test3.exe
input a:13
13*13=169
在printf()
后添加一条fflush()
语句刷新输出可以解决问题;
手动关闭标准输出的缓冲setvbuf(stdout, NULL)
也可以解决问题;
经过试验,是 mintty 这个模拟终端在运行Windows本地应用时,标准输出的行缓冲变成了全缓冲(即使用setvbuf
函数设置为行缓冲也仍然是全缓冲;为什么会这样,我也不知道)。
为了验证,使用无缓冲io直接向标准输出打印数据,结果表明确实是输出被缓冲了。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define N 32000
char buf[N];
int main(void)
{
// setvbuf(stdout, NULL, N, _IOLBF);
// setbuf(stdin, NULL);
// windows 程序在 MSYS 下是全缓冲的;标准输入和标准输出都是全缓冲
for (int i = 0;i<5 && fgets(buf, N, stdin);i++){
write(STDOUT_FILENO, "==>", 3);
write(STDOUT_FILENO, buf, strlen(buf));
write(STDOUT_FILENO, " ", 1);
printf("->");
fputs(buf, stdout); //
}
}
$ ./test
a
==>a
b
==>b
3
==>3
4
==>4
5 hhh
==>5 hhh
->a
->b
->3
->4
->5 hhh
这个试验表明,标准输出功能正常,是行缓冲;但标准输入却成了全缓冲。
windows的终端和Linux的终端使用不同的方式处理输入输出,所以在mintty运行windows本地程序时的时候会把程序的输入输出接到管道中,做一遍过滤。副作用就是会使本地windows程序对当前终端环境产生误判。解决方案是使用winpty命令执行windows程序。
$ pacmsn -S msys/winpty
$ winpty ./test3
input a:123
123*123=15129
世界终于清静了。
PS:winpty也有点小瑕疵,比如彩色字符会搞乱输出。
参考: https://github.com/msys2/msys2/wiki/Porting