EOF \n \0 NULL 之间的区别
它是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。因此,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("\n End of file reached.");
} else {
printf("\n Something went wrong.");
}
除了表示文件结尾,EOF还可以表示标准输入的结尾。
int c;
while ((c = getchar()) != EOF) {
putchar(c);
}
解决重复出现两次的办法就是不用feof,而是使用fgetc().
但是,标准输入与文件不一样,无法事先知道输入的长度,必须手动输入一个字符,表示到达EOF。
Linux中,在新的一行的开头,按下Ctrl-D,就代表EOF(如果在一行的中间按下Ctrl-D,则表示输出"标准输入"的缓存区,所以这时必须按两次Ctrl-D);Windows中,Ctrl-Z表示EOF。(顺便提一句,Linux中按下Ctrl-Z,表示将该进程中断,在后台挂起,用fg命令可以重新切回到前台;按下Ctrl-C表示终止该进程。)//如果在一行的中间按下Ctrl-D,则表示输出"标准输入"的缓存区,所以这时必须按两次Ctrl-D,这句话存疑,应该是错的,不区分是中间输入的还是开头输入的,都是一样的,都代表eof
那么,如果真的想输入Ctrl-D怎么办?这时必须先按下Ctrl-V,然后就可以输入Ctrl-D,系统就不会认为这是EOF信号。Ctrl-V表示按"字面含义"解读下一个输入,要是想按"字面含义"输入Ctrl-V,连续输入两次就行了。
getchar()-----读取输入的字符(%c)
它能读取任何 字符(只要是在ACSII上的)如回车(ACSII码值:10)、换行(13)、null(\0)都可以,所以我要做的是判断,而和gets(直至接受到换行符或EOF,换行符不作为读取串的内容,读取的换行符被转换为null值,并由此来结束字符串)和scanf(tab,空格,换行,回车都作为结束符)都不同
feof()函数用来检测当前文件流上的文件结束标识,判断是否读到了文件结尾,其原型为:
int feof(FILE * stream);
【参数】stream为文件流指针。
【返回值】检测到文件结束标识返回1,否则返回0。
文件结束标识一般由上次的读写操作来设置,当然也可以手动设置。
当文件内部的位置指针指向文件结束时,并不会立即设置FILE结构中的文件结束标识,只有再执行一次读文件操作,才会设置结束标志,此后调用feof()才会返回为真。
文件结束标识可以由 clearerr()、rewind()、fseek()、fsetpos() 和 freopen() 函数清除;如果这时位置指针未被重置,那么将在下次 I/O 操作时进行设置。
更多信心请参考:C语言FILE结构体
注意,feof()与EOF不同:feof()是函数,用来检测文件的结束;EOF是 End Of File 的缩写,是C语言中标准库中定义的宏,定义为:#define EOF (-1)。
EOF的值为-1,是 int 类型数据,在32位系统中,可以表示为0xFFFFFFFF;EOF 不是一个字符,也不是文件中实际存在的内容。EOF不但能表示读文件到了结尾这一状态,它还能表示 I/O 操作中的读、写错误(可以用 ferror() 来检测)以及其它一些关联操作的错误状态。
fgetc() 或getc() 等函数返回EOF并不一定表示文件结束,当读取文件出错时也会返回EOF,仅凭返回 -1 就认为文件结束是错误的;正因为如此,我们需要feof()来判断文件是否结束,当然用feof()来判断文件结束时也需要判断读取操作是否出错,这时可以用ferror()来判断,当其为真时表示有错误发生。在实际的程序中,应该每执行一次文件操作,就用用ferror()函数检测是否出错。
例如,有一个文件指针fp,文件中有字符串“hello world”:
- int c=0;
- while( !feof(fp) )
- {
- int c=fgetc(fp);
- printf("%c: %x \n", c, c);
- }
上面的代码除了输出 hello 外,还会输出一个结束字符EOF(EOF是fgetc函数的返回值,并不是文件中存在EOF)。其原因就是当内部位置指针指向结尾时,还要执行一次读操作,文件结束标识才会被设置。
对上面代码进行更改:
- int c;
- c=fgetc(fp);
- while( !feof(fp) )
- {
- printf("%c: %x \n", c, c);
- c=fgetc(fp);
- }
上面的代码只输出“hello”不输出文件结束符EOF。当文件内部位置指针指向结束位置时,先执行一次读操作,设置文件结束标识,while循环立即结束。
【实例】读取一个文件直到结束,然后回到开头重新读取。
- #include<iostream.h>
- #include<stdio.h>
- void main(void)
- {
- FILE* stream;
- long l;
- float fp;
- char s[81];
- char c;
- stream = fopen("fscanf.txt","w+");
- if(stream == NULL) /*打开文件失败*/
- {
- printf("the file is opeaned error!\n");
- }
- else
- {
- fprintf(stream,"%s %ld %f %c","a_string",6500,3.1415,'x');
- fseek(stream,0L,SEEK_SET); /*定位读写指针*/
- fscanf(stream,"%s",s);
- printf("%ld\n",ftell(stream));
- fscanf(stream,"%ld",&l);
- printf("%ld\n",ftell(stream));
- fscanf(stream,"%f",&fp);
- printf("%ld\n",ftell(stream));
- fscanf(stream," %c",&c);
- printf("%ld\n",ftell(stream));
- fgetc(stream); /*使指针到结尾*/
- if(!ferror(stream))
- {
- if(feof(stream)) /*如果不是结束*/
- {
- printf("We have reached end-of-file\n");
- rewind(stream);
- fscanf(stream,"%s",s);
- printf("%s\n",s);
- }
- }
- fclose(stream);
- }
- }
运行结果:
8
13
22
24
We have reached end-of-file
a_string
程序先创建一个文件,写入4个类型的数据,然 后把读/写指针定位到文件开头逐个读取并输出当前指针的位置, 如果到了文件结尾则提示已经到达文件结尾,重新定位文件到开头并读取一个字符串。
EOF \n \0 NULL 之间的区别的更多相关文章
- C#中string.Empty、""和null 之间的区别
1.C#中string.Empty.""和null 之间的区别 (http://blog.csdn.net/henulwj/article/details/7830615)
- C# DBNULL与NULL之间的区别【转】
null是.net中无效的对象引用.DBNull是一个类.DBNull.Value是它唯一的实例.它指数据库中数据为空(<NULL>)时,在.net中的值.null表示一个对象的指向无效, ...
- localhost与127.0.0.1之间的区别
Localhost的意思是本地服务器,而127.0.0.1是本机地址,他们的关系是通过操 作系统中的hosts文件,将Localhost解析为127.0.0.1.而实际工作中,Localhost是不经 ...
- localhost和本机IP和127.0.0.1之间的区别
参考出处:https://www.zhihu.com/question/23940717 localhost 是个域名,不是地址,它可以被配置为任意的 IP 地址,不过通常情况下都指向 127.0.0 ...
- ToString(“N2”)和ToString(“0.00”)之间的区别
看来N会包含数千个分隔符,而0.00则不会. N2将以500.00的方式工作,但是当您有5000.00时,N2将显示为 5,000.00 代替 5000.00 If you do this inste ...
- [转发]Oauth 1.0 1.0a 和 2.0 的之间的区别有哪些?
原文地址:http://www.zhihu.com/question/19851243
- '0','\0',NULL,EOF的区别
要看是不是一个东西,打印一下即可 printf("%d %d %d %d\n",'0','\0',NULL,EOF); 输出: 48 0 0 -1 结论: '\0'与NULL 都是 ...
- 深入理解 '0' "0" '\0' 0 之间的区别
看来基础还是很重要的,基础不扎实就难以学好c语言,就别说写出高质量的c语言代码了.今天,我就被这个问题折磨的不行了,哈哈,不过现在终于明白了‘\0’ ,‘0’, “0” 之间的区别了.困惑和快乐与你分 ...
- php中0," ",null和false的区别
php中很多还不懂php中0,"",null和false之间的区别,这些区别有时会影响到数据判断的正确性和安全性,给程序的测试运行造成很多麻烦.先看一个例子: <? $str ...
随机推荐
- BZOJ3523[Poi2014]Bricks——贪心+堆
题目描述 有n种颜色的砖块,第i种颜色的砖块有a[i]个,你需要把他们放成一排,使得相邻两个砖块的颜色不相同,限定第一个砖块的颜色是start,最后一个砖块的颜色是end,请构造出一种合法的方案或判断 ...
- Scout YYF I POJ - 3744(概率dp + 矩阵快速幂)
题意: 一条路上有n个地雷,你从1开始走,单位时间内有p的概率走一步,1-p的概率走两步,问安全通过这条路的概率 解析: 很容易想到 dp[i] = p * dp[i-1] + (1 - p) * d ...
- xslt格式化日期的方法
数据:<PK_SEND_DATE>2007-9-28 0:00:00</PK_SEND_DATE> 通过截取:<xsl:value-of select="sub ...
- 值得Python小白学习的书 简单推荐几本吧
于我个人而言,我很喜欢Python,当然我也有很多的理由推荐你去学python.我只说两点.一是简单,二是写python薪资高.我觉得这俩理由就够了,对不对.买本书,装上pycharm,把书上面的例子 ...
- 架构师成长之路6.6 DNS服务器搭建(构建企业级DNS)
点击返回架构师成长之路 架构师成长之路6.6 DNS服务器搭建(构建企业级DNS) 采用LVS-DR模式负载均衡,多IDC,多套DNS集群,通过master-slave技术保证dns配置的一致性. 1 ...
- [算法进阶0x10]基本数据结构A作业总结
在线题目\(oj\)评测地址:https://xoj.red/contests/show/1237 T1-Editor(hdu4699) 题目描述 维护一个整数序列的编辑器,有以下5种操作,操作总数不 ...
- 【洛谷P1091】合唱队列
题目大意:给定一个有 N 个正整数的序列,从其中拿走一些数,使得剩下的数满足严格单峰性,即先严格递增后严格递减,允许单调增和单调减,求最少需要拿走多少数. 题解:先考虑严格单调的情况,最少需要拿走多少 ...
- MyEclipse添加模板注释
只有两个步骤: 1.设置模板 Windows—Preference—Java—Code Style—Code Templates 图中, Configure generated code and co ...
- php 字符串截取函数
php自带的一个截取字符串的函数,只能处理英文,数字的不能截取中文混排的哦,有需要的朋友可以参考,后面的比较好用,第一个主要是给初学者学学用的. php //构造字符串 $str = "AB ...
- Python自定义Module中__init__.py文件介绍
./pyModuleTest/├── addutil│ ├── add.py│ ├── add.pyc│ ├── __init__.py│ ├── __init__.pyc│ └─ ...