c语言putchar作用和用法,转:c语言EOF是什么?(及getchar()和putchar用法)

article/2025/3/9 21:26:00

我学习C语言的时候,遇到的一个问题就是EOF。

它是end of file的缩写,表示"文字流"(stream)的结尾。这里的"文字流",可以是文件(file),也可以是标准输入(stdin)。

比如,下面这段代码就表示,如果不是文件结尾,就把文件的内容复制到屏幕上。

int c;

while ((c = fgetc(fp)) != EOF) {

putchar (c);

}

很自然地,我就以为,每个文件的结尾处,有一个叫做EOF的特殊字符,读取到这个字符,操作系统就认为文件结束了。

但是,后来我发现,EOF不是特殊字符,而是一个定义在头文件stdio.h的常量,一般等于-1。

#define EOF (-1)

于是,我就困惑了。

如果EOF是一个特殊字符,那么假定每个文本文件的结尾都有一个EOF(也就是-1),还是可以做到的,因为文本对应的ASCII码都是正值,不可能有负值。但是,二进制文件怎么办呢?怎么处理文件内部包含的-1呢?

这个问题让我想了很久,后来查了资料才知道,在Linux系统之中,EOF根本不是一个字符,而是当系统读取到文件结尾,所返回的一个信号值(也就是-1)。至于系统怎么知道文件的结尾,资料上说是通过比较文件的长度。

所以,处理文件可以写成下面这样:

int c;

while ((c = fgetc(fp)) != EOF) {

do something

}

这样写有一个问题。fgetc()不仅是遇到文件结尾时返回EOF,而且当发生错误时,也会返回EOF。

(我注:对于二进制文件存在一些问题,因为二进制文件中的数据值可能是‘-1’,为了防止在对二进制文件进行读操作时,误将

数据‘-1’当做文件结束符,ansi c提供了feof函数。如果为1表示文件结束,为0未结束。

#include#include

intmain()

{

FILE*fp;intch;if((fp=fopen("C:\1.txt","r+"))==NULL)

{

printf("cannot open this file");

exit(-1);

}while((ch=fgetc(fp))!=EOF)

{

putchar(ch);

}

fclose(fp);

printf("");return 0;

}

值得注意的是

int fgetc(FILE *fp);

返回的是int。但由于所读取的字符被保存在低字节当中,所以可以复制一个char型变量。

NULL在stdio.h中定义:

/* Define NULL pointer value */

#ifndef NULL

#ifdef __cplusplus

#define NULL 0

#else

#define NULL ((void *)0)

#endif

#endif

)

)

因此,C语言又提供了feof()函数,用来保证确实是到了文件结尾。上面的代码feof()版本的写法就是:

int c;

while (!feof(fp)) {

c = fgetc(fp);

do something;

}

但是,这样写也有问题。fgetc()读取文件的最后一个字符以后,C语言的feof()函数依然返回0,表明没有到达文件结尾;只有当fgetc()向后再读取一个字符(即越过最后一个字符),feof()才会返回一个非零值,表示到达文件结尾。

所以,按照上面这样写法,如果一个文件含有n个字符,那么while循环的内部操作会运行n+1次。所以,最保险的写法是像下面这样:

int c = fgetc(fp);

while (c != EOF) {

do something;

c = fgetc(fp);

}

if (feof(fp)) {

printf("

End of file reached.");

} else {

printf("

Something went wrong.");

}

除了表示文件结尾,EOF还可以表示标准输入的结尾。

int c;

while ((c = getchar()) != EOF) {

putchar(c);

}

但是,标准输入与文件不一样,无法事先知道输入的长度,必须手动输入一个字符,表示到达EOF。

Linux中,在新的一行的开头,按下Ctrl-D,就代表EOF(如果在一行的中间按下Ctrl-D,则表示输出"标准输入"的缓存区,所以这时必须按两次Ctrl-D);Windows中,Ctrl-Z表示EOF。(顺便提一句,Linux中按下Ctrl-Z,表示将该进程中断,在后台挂起,用fg命令可以重新切回到前台;按下Ctrl-C表示终止该进程。)

那么,如果真的想输入Ctrl-D怎么办?这时必须先按下Ctrl-V,然后就可以输入Ctrl-D,系统就不会认为这是EOF信号。Ctrl-V表示按"字面含义"解读下一个输入,要是想按"字面含义"输入Ctrl-V,连续输入两次就行了。

(完)

另外一篇文章:

在阮一峰的网络日志里,阮先生写了一篇关于EOF的文章(http://www.ruanyifeng.com/blog/2011/11/eof.html);该文描述了EOF不是文件的结束符,而是fgetc函数读取文件,到达文件结尾的时候返回一个标志。 在宏定义里,EOF=-1。 Q: 于是有网友问如果文件中有个-1怎么办?

首先看看fgetc的说明:

在linux控制台中,执行命令

man 3 fgetc

“fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, or EOF on end of file or error.”

上面说明的意思是“fgetc()每次读取一个unsigned char字符的字符,然后转型为int型返回,如果到达文件的结束或者出错就返回EOF”.

思考:

既然是读取一个unsigned char类型的字符,为什么不返回unsigned char而是int呢?我们知道一个int就是32个bit,而一个char就是16个bit,由于int存储空间比char大,所以一个unsigned char转型为int不可能有负数的情况出现。于是fgetc函数返回int,使得可以用一个负数来表示 EOF 或其它情况。注意:一个unsigned char不可能转型为负数的int值,并不是说signed char也不是转型为负数的int值。请看如下代码

48304ba5e6f9fe08f3fa1abda7d326ab.png

#include

int main(void){int i = -1;

signedchar sc = 0xff;

unsignedchar usc = 0xff;

printf("转成16进制后i是 %x, sc是 %x",i,sc);if (i ==sc){

puts("i == sc");

}else{

puts("i != sc");

}

putchar('');

printf("转成16进制后i是 %x, usc是 %x", i, usc);if (i ==usc){

puts("i == usc");

}else{

puts("i != usc");

}return 0;

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

假如,我们有一个文件echo "this is my file" > myfile.txt

然后通过ghex编辑二进制文件,于是把this is my file的改成十六进制的表示, 使得十六进制文件包含0xff 0xff0x74 0x68 0x69 0x73 0xff 0xff 0x73 0x20 0x6d 0x79 0x20 0x66 0x69 0x6c 0x65 0x0a

fgetc每次读一个unsigned char, 于是读的顺序为0x74 0x68 0x69 0x73 0xff 0xff 0x73 0x20 0x6d 0x79 0x20 0x66 0x69 0x6c 0x65 0x0a

用程序验证一下

48304ba5e6f9fe08f3fa1abda7d326ab.png

#include #include

int main(void){

FILE*fp;intc;if ((fp = fopen("myfile.txt", "rb")) ==NULL){

perror("myfile.tx");return 0;

}char buffer[33];while((c = fgetc(fp)) !=EOF){//printf("%0x ",c);//itoa(c, buffer, 16);

sprintf(buffer, "%#x", c);

printf("%s", buffer);

}

printf("");

fclose(fp);return 0;

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

从上面程序的运行结果来看,fgetc并没有把文件中的0xffff误当做EOF。如果fgetc每次读取的是一个int,也就是32个bit,那么它可能读到0xffff,有符号的int,就等于-1, 但是这种情况不会出现,因为fgetc每次读的是一个unsigned char。

类型转换

我们再来看看十进制整数-1,在不同存储空间和不同的类型下值分别是什么?

十进制

十六进制(int)

十六进制(char)

-1

ffff

ff

接着看char型从8位的值,补充为32位的值,在不同类型补充的值不同

十进制

十六进制char

由unsigned char补充为int的值

由signed char补充为int的值

-1

ff

00ff

ffff

于是根据上面的转型规则,一个陷阱出现了。

一个陷阱

单单从函数名上推测,很多人会认为fgetc返回一个是个16位的char类型的字符,所以程序上会写成

48304ba5e6f9fe08f3fa1abda7d326ab.png

#include

int main(void)

{

FILE*fp;

unsignedcharc;if ((fp = fopen("myfile.txt", "rb")) ==NULL)

{

perror ("myfile.txt");return 0;

}while ((c = fgetc(fp)) !=EOF)

{

putchar (c);

}

fclose(fp);return 0;

}

48304ba5e6f9fe08f3fa1abda7d326ab.png

文件结束时fgetc函数返回0xffff,但是被以上的程序变成了unsigned char了,于是根据类型把c补全到32位,变成了0x00ff。

由于0x00ff != 0xffff, 所以以上程序会出现一个死循环。。

总结:

fgetc函数每次读一个16位的unsigned char,但是转型为32位的int返回,遇到文件结束返回0xffff,由于int的长度比char长,所以不可能读到负数。


http://chatgpt.dhexx.cn/article/s9Vw57L5.shtml

相关文章

getchar与putchar用法

#include<stdio.h>main(){int i;igetchar();//相当于char i;scanf("%c",&i); putchar(i);//相当于printf("%c",i); 需要i是字符才能输出不能是变量printf("\n");printf("%d",i);}输出结果一致 #include<stdio.h>main…

拼多多无货源店群项目

在当下,单纯的工资收入难以支撑起飞升的物价时,额外收入成了绝大部分人用来对抗生活压力的最好帮手,这话是没错,我身边也有很多斜杠青年也确实因为副业做得好,生活衣食无忧,惬意潇洒。现在随着电商行业的发展,越来越多的人会选择拼多多开店,选择做无货源模式。 其实拼多…

拼多多无货源模式新玩法(采集淘宝天猫京东等平台商品上传拼多多店铺)

给大家展示一个全新的拼多多电商模式&#xff0c;别眨眼&#xff0c;别浪费时间&#xff0c;看完还不明白来打我&#xff01; &#xff01; &#xff01; 1&#xff1a;无货源业务模式及收入介绍 开店后&#xff0c;我们将经营店铺。 我们做的是无货源模式。 我们不需要预付钱…

2022年拼多多无货源店群系列课,怎么做拼多多无货源店铺

2022年拼多多无货源店群系列课&#xff0c;新手怎么做拼多多无货源店铺 2022年拼多多无货源店群系列课 ├┈1.拼多多店群系列课介绍.mp4 ├┈10.拼多多店群怎么避免违规.mp4 ├┈11.拼多多店群当下流行的方法全面解析.mp4 ├┈12.拼多多店群精细化玩法.mp4 ├┈13.拼多多店…

做拼多多店群有哪些需要注意的地方?经验分享

拼多多无货源店群 无货源店群这是一种新型的电商玩法。 无货源并不是真的没有货源,如果真的按照字面意思去理解,那就大错特错了!只是我们不用再为货源的事情去操心。 所有的商品都是采集自全网的爆款商品,不用自己囤货,当然也省去了囤货的资金。 传统电商卖家关注的流…

尚呈电商:拼多多店群玩法怎么操作?

大家都知道店群一说&#xff0c;因为现在店群也是被平台打败的&#xff0c;就那种老式的店群玩法就比较难玩了&#xff0c;很多新手都想知道具体是怎么操作的&#xff0c;下面就和尚呈电商一起来看看吧! 你是利用平台对于这种新品流量扶持&#xff0c;比如说你上一个新品&#…

拼多多店群被割N次韭菜,终于测试出一个接近100%成功率的起店方法,日出百单!

距离我上次发表关于拼多多店群的文章已经是两年多了&#xff0c;目前来说拼多多店群的热度已经褪去了&#xff0c;许多做网赚割韭菜的培训机构也转向其他项目&#xff0c;但仍然还存在许多割韭菜的团队&#xff0c;这也导致了提起拼多多店群大家都觉得是韭菜项目的原因。 在这…

关于 Pycharm 2019.2 版本出现等宽字体对不齐的问题的解决方法

我使用的是更纱黑体 (Sarasa Term SC Medium). 从 Pycharm Community 2019.1 升级到 2019.2.3 后出现了如下图问题: 解决方法如下: 打开 Pycharm 设置中心, 切换到 “Appearance & Behavior > Appearance”, 将 “Antialiasing” (抗锯齿) Editor 选项改为 “Greysca…

cmd字体推荐-更纱黑体

网上看到的可应用于cmd/powershell的字体&#xff0c;用了后无法自拔&#xff0c;推荐一下&#xff0c;效果如图 下载链接&#xff1a;更纱黑体

命令行字体推荐-更纱黑体

网上看到的可应用于powershell的字体&#xff0c;用了后无法自拔&#xff0c;推荐一下&#xff0c;效果如图 链接&#xff1a;更纱黑体 https://github.com/be5invis/Sarasa-Gothic cmd上应用字体好像有点问题&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&am…

linux比windows丑,告别 Windows 难看难用,教你打造体验不输 macOS 和 Linux 的终端

终端&#xff0c;是用户与操作系统进行交互的最原始的输入输出环境&#xff0c;也是执行一些高级系统操作的必要工具。而 Windows 的终端「小黑框」&#xff0c;一直给大家一种「难看难用」的印象。接下来&#xff0c;我将介绍一些小方法&#xff0c;来对 Windows 的终端环境进…

PowerShell、CMD 和 Windows Terminal 的美化配置方法

PowerShell、CMD 和 Windows Terminal 的美化配置方法 众所周知&#xff0c;Windows 10 自带的 PowerShell 和 CMD 默认界面有点不忍直视&#xff0c;且显示中文时会发生乱码现象。现分享一下 PowerShell、CMD 的美化方法&#xff0c;以及替代方案 Windows Terminal 的配置方法…

linux终端字体放大_5 个 PowerShell 主题,让你的 Windows 终端更好看

在上一篇文章中&#xff0c;我们介绍了如何将 PowerShell 的终端变得漂亮起来。在这一篇文章中&#xff0c;我将为大家介绍如何定制 PowerShell 中的 Prompt 单元&#xff0c;并推荐 5 个赏心悦目的 Prompt&#xff08;命令提示符&#xff09;主题。 推荐阅读&#xff1a;告别 …

【操作系统实践】深度操作系统

——Linux is free,if your time is free. 目录 一、前言二、deepin操作系统实践大纲1、硬件设备保障2、系统使用及美化3、软件应用安装落地4、进一步开发 三、深度操作系统deepin四、基于vmware的安装及双系统安装五、硬件设备保障1、网卡问题2、声卡问题及更普适的驱动问题 六…

c++调用powershell_告别 Windows 终端的难看难用,从改造 PowerShell 的外观开始

终端&#xff0c;是用户与操作系统进行交互的最原始的输入输出环境&#xff0c;也是执行一些高级系统操作的必要工具。而 Windows 的终端「小黑框」&#xff0c;一直给大家一种「难看难用」的印象。接下来&#xff0c;我将介绍一些小方法&#xff0c;来对 Windows 的终端环境进…

个性化-字体

本文具有极强的主观性&#xff0c;但也希望可以给大家提供些许帮助 1. 字体选择标准 用于代码的字体&#xff1a;可以区分明确区分 1lI 和 0Oo具有明确的开源许可协议&#xff08;一般为 SIL Open Font License 1.1 或 IPA Font License 1.0&#xff09;听闻部分字体会对特定像…

你可能用得上的 N 款免费/开源中文字体

除了电脑中那些默认的千篇一律的字体以外&#xff0c;你还知道什么字体&#xff1f;有好用的吗&#xff1f;在网上下载的字体&#xff0c;怕不怕一不小心就侵权了&#xff1f; 现在不用怕了&#xff0c;本文收集了一些免费/开源的中文字体&#xff0c;都是个人免费使用的&#…

linux安装完windows字体以后 特别难看,告别 Windows 终端的难看难用,从改造 PowerShell 的外观开始...

原标题&#xff1a;告别 Windows 终端的难看难用&#xff0c;从改造 PowerShell 的外观开始 终端&#xff0c;是用户与操作系统进行交互的最原始的输入输出环境&#xff0c;也是执行一些高级系统操作的必要工具。而 Windows 的终端「小黑框」&#xff0c;一直给大家一种「难看难…

超级强大服务器终端,告别 XShell 打造强大的Windows 终端

不同于mac OS及Linux的终端&#xff0c;window的cmd想来很难用&#xff0c;为了连接服务器&#xff0c;很多人首先都会用xshell&#xff0c;但是第一界面就很难看&#xff0c;而且试用期过了后很麻烦&#xff0c;这里我找到一款很不错的工具。 Console、Terminal 和 Shell 的区…

Typora 中文字体深度修改

本文的 “深度修改” 将涉及以下方面: Typora 界面元素的字体 Typora 某个主题或所有主题的字体 针对 Markdown Codeblock 区域字体失效现象, 本文也做了修正 (如下图所示) 正文 第一步 打开用户配置文件 (C:\Users\{YourName}\AppData\Roaming\Typora\conf\conf.user.j…