关注嵌入式安卓物联网行业及人才培养,每日更新,欢迎订阅及留言讨论~~~

作者:倪键树,嵌入式安卓物联网讲师。

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位去掉了,因此 fgetcfputc 配合能够实现文件复制。到目前为止, 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会在编译时指出这一点。

注:关于charsigned char unsigned char 的区别在哪里?”请看后边解析!

6、为何需要feof?

FILE *fp;

fp 指向一个很复杂的数据结构, feof 是通过这个结构中的标志来判断文件是否结束的。如果文件用 fgetc 读取,刚好把最后一个字符读出时, fp 中的EOF标志不会打开,如果这时用feof判断,将会得到文件尚未结束的结论,fgetc取得最后一个错误的-1。

当fgetc 返回 -1 时,我们仍无法确信文件已经结束,因为可能是读取错误! 这时我们需要 feof 和 ferror。

总结:EOF并不是存在于文件中的,而是一种状态,当读到文件末尾或者读取出错时就会返回这个值。(即使读取错误可能也被认为文件结束,所以就需要用feof 和 ferror来判断是不是真的文件结束了)

7getchar(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的错综复杂关系相关推荐

  1. 【C语言】不能使用 while(fgetc(fp)!=EOF)进行文件复制

    while(fgetc(fp)!=EOF){a = fgetc(fp);printf("%c\t",a);fputc(a,ffp);} 这样是错误的. 因为fgetc函数每调用一次 ...

  2. React,Redux,React-redux的错综复杂关系

    最近了解了一些React的知识,在这里写一些关于React.js,Redux和React-redux的知识,供大家学习 一.React 1.首先要知道React不是mvc框架,它只是一个库,只专注于视 ...

  3. C语言之文件读写探究(二):fputc、fgetc、feof(一次读写一个字符(文本操作))

    相关博文:C语言之文件读写探究(一):fopen.fclose(文件的打开和关闭) 相关博文:C语言之文件读写探究(二):fputc.fgetc.feof(一次读写一个字符(文本操作)) 相关博文:C ...

  4. 文件结束标志EOF及fgetc fgets getc gets getchar函数

    1. EOF(end of file) 大家都知道流(文本流,标准输入流)结束时会返回EOF,那么EOF到底是什么呢? 在stdio.h中我们可以看到相关声明: #define EOF (-1) 很明 ...

  5. [转] linux系统文件流、文件描述符与进程间关系详解

    http://blog.sina.com.cn/s/blog_67b74aea01018ycx.html linux(unix)进程与文件的关系错综复杂,本教程试图详细的阐述这个问题. 包括:     ...

  6. EOF是什么?(转)

    我学习C语言的时候,遇到的一个问题就是EOF. 它是end of file的缩写,表示"文字流"(stream)的结尾.这里的"文字流",可以是文件(file) ...

  7. 关于EOF,转自新浪微博

    本文转自http://blog.sina.com.cn/s/blog_7714171f0101798y.html EOF 是 End Of File 的缩写. 在C语言中,它是在标准库中定义的一个宏. ...

  8. C语言 文件读写 EOF - C语言零基础入门教程

    目录 一.EOF 简介 二.EOF 实战 三.猜你喜欢 零基础 C/C++ 学习路线推荐 : C/C++ 学习目录 >> C 语言基础入门 一.EOF 简介 EOF 是 End Of Fi ...

  9. C语言中fgetc函数返回值为什么是int?

    学习C语言的,文件操作,大都会用到它. 它的函数原型: 这个函数的返回值,是返回读取的一个字节.如果读到文件末尾返回EOF. EOF其实就是一个宏 #define EOF (-1) 表示-1. 既然返 ...

最新文章

  1. VS2015 Qt5
  2. java gui 选项_【Java-GUI】04 菜单
  3. Jmeter启动错误及解决方案
  4. python +java 用socket在局域网进行图片上传给springboot后端并进行前端访问
  5. C# 文件操作详解(一)---------File类
  6. YbtOJ#20066-[NOIP2020模拟赛B组Day4]筹备计划【线段树,树状数组】
  7. 第十二期:常用的几种大数据架构剖析
  8. 快手2021年营收810亿元 经调整净亏损188亿元
  9. Angular 导致公司损失数十亿美元!
  10. webstorm 配置sass
  11. Java不满足的依赖异常_java – 新的缺失/不满足的依赖项WildFly 9中的错误
  12. mysql 5.6 同步_mysql 5.6 半同步主从安装
  13. 学生作业管理系统java源码_基于jsp的学生作业管理-JavaEE实现学生作业管理 - java项目源码...
  14. 华硕服务器主板型号命名规则,详细解读主板厂商命名规则——华硕篇
  15. uniapp进行H5微信支付
  16. 推荐几款好用的编程字体
  17. 两年嵌入式软件开发的工作感想
  18. kubernetes—ConfigMap 与 Secret
  19. Cathy学习Java——线程
  20. maple的Linux安装步骤,Linux下面如何安装maple,mathematica,matlab这类软件?

热门文章

  1. 2021年高考成绩查询衡阳市八中,优秀!衡阳2020年各大高中成绩出炉!
  2. c语言程序40例,C语言程序讲解40例.pdf
  3. java filter加时间戳_java filter加时间戳
  4. 使用DBUnit集成Spring简化测试
  5. Apache Avro 与 Thrift 比较
  6. Linux部署项目的步骤
  7. 初探Thymeleaf模板引擎
  8. 《天天数学》连载00:序言
  9. Python学习笔记:用Python获取数据(本地数据与网络数据)
  10. 【POJ1741】Tree,第一次的点分治