fgetc与EOF的错综复杂关系
关注嵌入式安卓物联网行业及人才培养,每日更新,欢迎订阅及留言讨论~~~
作者:倪键树,嵌入式安卓物联网讲师。
fgetc与EOF的错综复杂关系
1、fgetc对字节的读取
在正常的情况下,fgetc 以 unsigned char 的方式读取文件流,扩展为一个整数,并返回。换言之,fgetc 从文件流中取一个字节,并加上24个零,成为一个小于256的整数,然后返回。
int c;
while ((c = fgetc(rfp))!= -1) // -1就是 EOF
fputc (c,wfp);
解析:上面 fputc 中的 c 虽然是整数,但在 fputc将其写入文件流之前,又把整数的高24位去掉了,因此 fgetc,fputc 配合能够实现文件复制。到目前为止,把 c 定义为char仍然是可行的,但下面我们将看到,把 c 定义为 int 是为了能正确判段文件是否结束的,而char则不能判断文件是否结束。
2、判断文件结束
多数人认为文件中有一个EOF,用于表示文件的结尾。但这个观点实际上是错误的,在文件所包含的数据中,并没有什么文件结束符。对fgetc 而言,如果不能从文件中读取,则返回一个整数 -1,这就是所谓的EOF。返回 EOF 无非是出现了两种情况,一是文件已经读完; 二是文件读取出错,反正是读不下去了。
注意:在正常读取的情况下,返回的整数均小于256,即0x0~0xFF。而读不出返回的是(-1)0xFFFFFFFF。但是假如你用fputc把 0xFFFFFFFF 往文件里头写,高24位被屏蔽,写入的将是 0xFF。
3、将c定义 int读取0xFF 会使我们误判为结束吗?
不会,前提是接收返回值的 c 要按原型定义为 int。
如果下一个读取的字符将为 0xFF,则
int c;
c = fgetc (rfp);//本来读取为0xFF,自动扩展为c = 0x000000FF;
if (c != -1) // 当然不相等, -1 是 0xFFFFFFFF
fputc (wfp); //所以即使读取了OXFF 复制也成功!
字符0xFF,其本身并不是EOF。
4、将c定义 char,若读取为0xFF,复制将失败。
假定下一个读取的字符为 0xFF 则:
char c;
c = fgetc (rfp);// fgetc(rfp)的值扩展为 0x000000FF,强转char型变为c = 0xFF
if (c != -1) // 字符0xFF与整数-1比较,c 被扩展为0xFFFFFFFF(即-1),所以,条件成立,文件复制提前退出。
C被扩展为0xFFFFFFFF,由下面代码可以验证:
#include <stdio.h>
int main()
{
char c;
c = -1;
printf("%x",c);
return 0;
}
得到的结果为ffffffff。
while((c=fgetc(rfp))!=EOF) 中的判别条件成立,文件复制结束! 意外中止,复制失败!
5、将c定义为 unsigned char;
当读到文件末尾,返回 EOF也就是-1时,
unsigned char c;
c = fgetc (rfp);// fgetc (rfp)的值为EOF,即-1,即0xFFFFFFFF,降格为字节, c=0xFF
if ( c!= -1) // c 被扩展为 0x000000FF(即255),永远不会等于 0xFFFFFFFF
所以这次虽然能正确复制 0xFF,但却不能判断文件结束。事实上,在 c为unsigned char时,c != -1 是永远成立的,一个高质量的编译器,比如 gcc会在编译时指出这一点。
注:“关于char、signed char 和 unsigned char 的区别在哪里?”请看后边解析!
6、为何需要feof?
FILE *fp;
fp 指向一个很复杂的数据结构, feof 是通过这个结构中的标志来判断文件是否结束的。如果文件用 fgetc 读取,刚好把最后一个字符读出时, fp 中的EOF标志不会打开,如果这时用feof判断,将会得到文件尚未结束的结论,fgetc取得最后一个错误的-1。
当fgetc 返回 -1 时,我们仍无法确信文件已经结束,因为可能是读取错误! 这时我们需要 feof 和 ferror。
总结:EOF并不是存在于文件中的,而是一种状态,当读到文件末尾或者读取出错时就会返回这个值。(即使读取错误可能也被认为文件结束,所以就需要用feof 和 ferror来判断是不是真的文件结束了)
7、getchar(c)的使用
当用getchar(c)时,即使c定义成字符型,也可以结束,主要是c与-1比较时,c会从char转换为整型值,同c定义为int。
char、signedchar 和unsigned char 的区别在哪里???
ANSI C 提供了3种字符类型,分别是char、signed char、unsigned char。char相当于signed char或者unsigned char,但是这取决于编译器!!!这三种字符类型都是按照1个字节存储的,可以保存256个不同的值:
signedchar取值范围是 -128 到 127
unsigned char 取值范围是 0 到 255
但是char究竟相当于signed char呢还是相当于unsigned char呢??对于int类型的有: int==signed int,但是char不能简单以为char==signed char。要确定char究竟等同什么要基于不同的编译器做测试。
大多数机器使用补码来存储整数,在这些机器中按照整数类型存储的-1的所有位均是1,假设我的机器也是如此存储,就能据此判断char究竟是等于signed char还是unsigned char:
程序如下:
据此可以判断在我的机器上char==signed char
但是绝对不能武断认为char==signed char就像int==signed int一样天经地义,大部分人还是单纯认为char==signed char的,其实换位思考一下就清楚了,c规定了九种不同的×××其中有char和signed char 和 unsihned char,但是只有int 没有 signed int(二者相等),如果简单认为char就是等同于signed char的话那8种不就完事了???
如果编译器支持unsigned char和char的相等同,设置这个选项就会发现char==unsigned char。下面是对这种相等的设置。
-funsigned-char
-fno-signed-char
这两个编译时设定的参数是对char类型进行设置,决定将char类型设置成-unsigned char
-fsigned-char
-fno-unsigned-char
这两个编译时设定的参数是对char类型进行设置,决定将char类型设置成signed char。
如此 char就等同于unsigned char了
总结:小小的char类型,竟然有如此的玄机,你看明白了吗?!要时刻谨记fgetc的用法,和EOF的理解,写出严谨的程序。
转载于:https://blog.51cto.com/wodesteve/1306629
fgetc与EOF的错综复杂关系相关推荐
- 【C语言】不能使用 while(fgetc(fp)!=EOF)进行文件复制
while(fgetc(fp)!=EOF){a = fgetc(fp);printf("%c\t",a);fputc(a,ffp);} 这样是错误的. 因为fgetc函数每调用一次 ...
- React,Redux,React-redux的错综复杂关系
最近了解了一些React的知识,在这里写一些关于React.js,Redux和React-redux的知识,供大家学习 一.React 1.首先要知道React不是mvc框架,它只是一个库,只专注于视 ...
- C语言之文件读写探究(二):fputc、fgetc、feof(一次读写一个字符(文本操作))
相关博文:C语言之文件读写探究(一):fopen.fclose(文件的打开和关闭) 相关博文:C语言之文件读写探究(二):fputc.fgetc.feof(一次读写一个字符(文本操作)) 相关博文:C ...
- 文件结束标志EOF及fgetc fgets getc gets getchar函数
1. EOF(end of file) 大家都知道流(文本流,标准输入流)结束时会返回EOF,那么EOF到底是什么呢? 在stdio.h中我们可以看到相关声明: #define EOF (-1) 很明 ...
- [转] linux系统文件流、文件描述符与进程间关系详解
http://blog.sina.com.cn/s/blog_67b74aea01018ycx.html linux(unix)进程与文件的关系错综复杂,本教程试图详细的阐述这个问题. 包括: ...
- EOF是什么?(转)
我学习C语言的时候,遇到的一个问题就是EOF. 它是end of file的缩写,表示"文字流"(stream)的结尾.这里的"文字流",可以是文件(file) ...
- 关于EOF,转自新浪微博
本文转自http://blog.sina.com.cn/s/blog_7714171f0101798y.html EOF 是 End Of File 的缩写. 在C语言中,它是在标准库中定义的一个宏. ...
- C语言 文件读写 EOF - C语言零基础入门教程
目录 一.EOF 简介 二.EOF 实战 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.EOF 简介 EOF 是 End Of Fi ...
- C语言中fgetc函数返回值为什么是int?
学习C语言的,文件操作,大都会用到它. 它的函数原型: 这个函数的返回值,是返回读取的一个字节.如果读到文件末尾返回EOF. EOF其实就是一个宏 #define EOF (-1) 表示-1. 既然返 ...
最新文章
- VS2015 Qt5
- java gui 选项_【Java-GUI】04 菜单
- Jmeter启动错误及解决方案
- python +java 用socket在局域网进行图片上传给springboot后端并进行前端访问
- C# 文件操作详解(一)---------File类
- YbtOJ#20066-[NOIP2020模拟赛B组Day4]筹备计划【线段树,树状数组】
- 第十二期:常用的几种大数据架构剖析
- 快手2021年营收810亿元 经调整净亏损188亿元
- Angular 导致公司损失数十亿美元!
- webstorm 配置sass
- Java不满足的依赖异常_java – 新的缺失/不满足的依赖项WildFly 9中的错误
- mysql 5.6 同步_mysql 5.6 半同步主从安装
- 学生作业管理系统java源码_基于jsp的学生作业管理-JavaEE实现学生作业管理 - java项目源码...
- 华硕服务器主板型号命名规则,详细解读主板厂商命名规则——华硕篇
- uniapp进行H5微信支付
- 推荐几款好用的编程字体
- 两年嵌入式软件开发的工作感想
- kubernetes—ConfigMap 与 Secret
- Cathy学习Java——线程
- maple的Linux安装步骤,Linux下面如何安装maple,mathematica,matlab这类软件?