在运行程序时,有时会出现显示的和想要的输出内容不符,又或者是输入的内容和想要的输入内容不符。这时就应该考虑是不是缓冲区的问题。
缓冲区机制的作用
缓冲区机制可以提高数据的读写速度,并且可以让低速的输入输出设备与高速的CPU之间协调工作。打个比方,使用计算机连接打印机来打印文档。由于打印机是低速设备,如果没有缓冲区的存在,打印机每次从计算机中读取一个数据打印,计算机需要一直等打印机打印结束才能去做其他事情。当有缓冲区以后,计算机可以把数据全放入缓冲区中,打印机只需要从缓冲区中读取数据即可,计算机在此期间可以做其他事情。
输出缓冲区
程序并不会立即把输出的数据显示到屏幕上,而是先存储在输出缓冲区,当满足一定条件时才显示出来。
1、遇到\n
2、程序结束
3、遇到输入语句
4、当缓冲区中内容满了,一般是4K大小;
5、fflush(stdout) 手动刷新
当应该显示的数据未显示时,可以考虑是不是因为输出缓冲区的问题。可以利用上述条件刷新输出缓冲区,让数据显示出来。
输入缓冲区
程序并不会立即获取屏幕上输入的数据,而是按下回车键后程序才从输入缓冲区读取数据。
一般会出现以下几种问题:
1、读取类型和缓冲区类型不匹配
当需要读取的是整型或者浮动型时,而输入缓冲区中是字符或符号时,此时读取会失败。并且数据会残留在输入缓冲区中,影响接下来的所有数据读取。
解决方法:
借助scanf返回值判断是否接收成功,如果失败,继续输入
int a=0,b=0,c=0;
while(scanf("%d%d%d",&a,&b,&c)>3)
{
printf("输入数据的类型有误,请重新输入");
stdin->_IO_read_ptr = stdin_IO_read_end;
}
注意:必须要记得清空输入缓冲区,否则会一直读取错误数据。
2、使用fgets()函数获取超过长度的字符串
fgets()函数可以指定读取size-1个字符,如果有多余的会残留在输入缓冲区中,影响下一次输入。
解决方法:
方法1:
scanf("%*[^\n]");
//表示从缓冲区中接收任意字符并丢弃,只要不是\n就一直进行,遇到\n才停下来。
scanf("%*c");
//丢弃一个任意字符
注意:必须确认输入缓冲区中有垃圾数据时,才能去读取丢弃输入缓冲区的垃圾数据,否则程序会停下来等待缓冲区中有一个\n
改进方法
清空前先判断字符串中是否有换行,如果有换行则表示没有垃圾数据写入缓冲区,不需要清空。
char str[10];
fgets(str,10,stdin);
int len = 0;
while(str[len]!='\0') len++;
if(str[len-1] !="\n")
{
scanf("%*[^\n]");
scanf("%*c");
}
方法2:借助缓冲区的位置指针移动到缓冲区的末尾,实现清理缓冲区的效果
stdin->_IO_read_ptr = stdin->_IO_read_end;
注意:上面的代码只在linux系统下可用
3、字符获取失败
当输入字符前,有输入其他数据时,前一次残留的换行或者空格会影响字符的输入。
解决方法
在输入字符前去除换行或回车
//使用scanf时用空格顶掉换行或回车
scanf("%d %c",%a,&ch);
//用getchar()接收换行或回车
scanf("%d",%a);
getchar();
scanf("%c",&ch);
当输入字符数据时,一定要注意输入缓冲区机制。如果怕出错可以刷新缓冲区来防止获取到错误的字符。
结语
希望这篇文章对你有所帮助