getchar与setbuf之经典错误

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

        考虑下面的例子:

#include <stdio.h>
int main()
{
	char c;
	while ((c = getchar()) != EOF){
		putchar(c)
	}
} 

        getchar函数在一般情况下返回的是标准输入文件中的下一个字符,当没有输入时返回EOF。这个程序乍一看似乎是把标准输入复制到标准输出,实则不然。原因在于程序中的变量c被声明为char类型,而不是int类型。这意味着c无法容下所有可能的字符,特别是,可能不发容下EOF。因此,最终结果存在两种可能:第一种可能是某些合法的输入字符在被“截断”后市的c的取值与EOF相同;另一种可能则是,c根本不可能娶到EOF这个值。对于前一种情况,程序将在文件复制的中途终止,对于后一种情况,程序将陷入死循环。

        解决办法:只需要把c声明为int即可。

        再看一个关于setbuf的例子:

        学过c语言的朋友都知道程序员可以自己控制缓冲区是否开启,这种控制能力是通过调用库函数setbuf/setvbuf实现的。如果buf是一个大小合适的字符数组,那么:              

setbuf(stdout, buf);

语句将通知输入/输出库,所有写入到stdout的输出都应该使用buf作为输出缓冲区,知道buf缓冲区被写满或者程序员直接调用fflush函数刷新缓冲区,buf缓冲区的内容才实际写到stdout中。缓冲区的大小由系统头文件<stdio.h>中的BUFSIZE定义。那么,请看例子:

#include <stdio.h>
int main()
{
	int c;
	char buf[BUFSIZE];
	setbuf(stdout, buf);
	while ((c = getchar()) != EOF){
		putch(c);
	}
}

        你找出这个错误了吗?很细微是吧?程序中对库函数setbuf的调用通知了输入/输出库所有字符的标准输出应该首先缓存在buf中。要找到这个错误出自哪里,我们不妨思考一下buf缓冲区最后一次被清空是在什么时候?答案是在main函数结束之后,作为程序交回控制给操作系统之前,C运行时库必须进行的清理工作的一部分。但是,在此之前buf字符数组已经被释放了!

        第一种解决办法:将缓冲数组定义为静态数组: static char  buf[BUFSIZE];

        第二种解决办法:动态分配缓冲区,在程序中并不主动释放分配的缓冲区。由于缓冲区是动态分配的,所以main函数结束时,并不会释放该缓冲区,这样C运行时库进行清理工作时就不会发生缓冲区已经释放的情况: 

char  *malloc();           
setbuf(stdout, malloc(BUFSIZE));


 

          

 


 

《C陷阱缺陷》----第五章 库函数 阅读详情

相关推荐

标准输出引起的重定向文件失败问题

由于输出很少,程序又不是正常结束(通过ctrl+c结束), 导致标准输出重定向到文件的内容为空 原因在于标准输出的缓冲模式 标准输出(stdout)的缓冲原理 缓冲类型分为三种: 无缓冲 行缓冲 全缓冲 stderr默认缓冲就是无缓冲。而stdout的缓冲类型输出介质有关: 屏幕或者终端:行缓冲 重定向文件、管道:全缓冲 为什么和输出介质有关,这很可能是shell重定向时候dup2的设置 解...

woai110120130的专栏 1418

Linux进程的创建结束类系统调用总结

-

zorchp 953

setbuf、setvbuf 标准I/O---学习笔记

setbuf、setvbuf 的功能使用和例子

qq_53383284的博客 829

Unix/Linux编程:fork()进程详解

理论 进程 问: 什么是进程 一个程序的执行称为一个进程,所有的代码都是在进程中执行的。 进程也是操作系统进程资源分片的基本单位 问: 进程是怎么产生的 Linux中,除了内核启动进程之外,其他的进程都是由它的父进程产生的。【通过调用fork函数】 问:操作系统是怎么识别各个进程的 操心系统通过进程ID(pid)来识别,pid 是进程在操作系统中的唯一标志 pid是可以重复使用的,比如说前一个为pid=11的进程死掉了,那么pid=11的这个进程就可以分配给其他进程使用了:当pid达

OceanStar的博客 4795

C语言之清空缓存区

文章浏览阅读9.2w次,点赞134次,收藏461次。本文详细解释了C语言中缓存区的概念及其重要性

2601_95164343的博客 251

C语言清空输入缓冲区

先来看一段代码:     #include &lt;stdio.h&gt; int main() { int num; char ch ; scanf("%d", &amp;num); scanf("%c", &amp;ch); printf("hello world\n"); system("pause...

我是小超斌 534

【c语言】清空缓存 的问题

【c语言】清空缓存 的问题 清空stdin中的缓存 int c; while((c = getchar()) != EOF && c != '\n'); 会把缓存清空,但是会遗留下'\n'  (10) 读取时,可以使用 scanf("%[^\n]",c);来空过\n。 或 scanf("\n%d",c);     失败的解决方案: 1, while(!feof(stdin

DaisyChioa的专栏 783

c语言清空scanf缓存,C语言清空输入缓冲区

来源:http://blog.csdn.net/guanyasu/article/details/53153705https://zhidao.baidu.com/question/5241738.htmlC语言中如何清空输入输出缓冲区上述描述似乎能够解决问题了,但是,fflush( )并不是标准C语言库函数,只是部分编译器自己实现的函数,是对标准C的扩展。先来看一段代码:#include int...

weixin_35804761的博客 3969

C语言清空输入缓冲区的N种方法对比

C语言中有几个基本输入函数: //获取字符系列int fgetc(FILE *stream);int getc(FILE *stream);int getchar(void);//获取行系列char

linjcai的博客 365

C陷阱缺陷--读书笔记5 库函数

第五章 一、知识点 1、对于一个例子: #include <stdio.h> main(){ char c; while((c = getchar()) !=EOF) putchar(c); } getchar函数在一般情况下返回的是标准输入文件中的下一个字符,当没有输入时返回EOF。这依程序乍一看似乎是把标准输入复...

weixin_30387799的博客 132

C语言标准输入缓存区清理方法列表

1. scanf("%*[^\n]%*c"); 2. while((ch = getchar()) != '\n' && ch != EOF); 3. setbuf(stdin, NULL); 验证平台: CPU: AMD Athlon(tm) II X2 250 Processor OS: ubuntu 8.10 compile: gcc 4.3.2 关于scanf 的

rex,nie的专栏 1208

【fflush】Linux环境下清空标准输入缓冲区 fflush(stdin) 无效

文章目录一、误区二、问题描述三、解决方法四、原因 一、误区 不论从 字面意思 还是 某些技术文档 中,都可以看到 fflush(stdin) 是对标准输入缓冲区清空的标准方案; 然而,并不是! 深入了解一下 fflush(stdin) 之后,才发现这个锅得自己背,怪自己喜欢拿来就用,不去深入了解某些重要细节,给自己上了生动一课; 二、问题描述 环境:Ubuntu18.04 编译器:gcc v...

问题不大 5911

文件内容操作C库函数

c库 文件内容操作 函数

qq_39906608的博客 1016

scanf()函数获取到换行字符‘\n’,分析及解决

我们在控制台给scanf()输入完后要按下回车键确认以继续执行, 然而这个回车键也会留在输入缓存区, 当scanf()把指定的字符取走后就会留下'\n'字符。 如果程序继续往下执行到下一个scanf()或getchar()时,就有可能获取到‘\n’字符, 之所以所“有可能”,是因为当scanf()想要获取%c时会获取‘\n’换行字符, 而如果是'%s'、‘%d’、‘%f’等非字符格式想要获取时,就会忽略无效的字符,‘\n就会被忽略掉了。 所以只有scanf("%c", &c)..

qq_33911037的博客 3862

文件内容操作篇

文件内容操作篇

oligaga的博客 1272

c++ 清空控制台_C 语言清空输入缓冲区的几个手段

先观察如下代码和运行情况:按照控制台提示,输入 value 的值之后,本该能够按照提示继续输入 choice 的值。但是你会发现程序直接跳过了 choice 的输入。而且 choice 原本的值是 'a',最后变成了换行符(即'n')。造成这种现象的原因是 C 语言的输入缓冲区的机制。什么是 C 语言的输入缓冲区呢?输入分为两种,一种称为无缓冲输入(或直接输入),即你每输入一个字符,程序就读一个字...

weixin_39830175的博客 1275
上一篇: C语言与字符串相关的查找函数
下一篇: win7下配置apache + mos_wsgi + web.py服务器
红桃Ace
博客等级 码龄15年 5粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值