从文本中读取字符——feof函数问题
踩坑一:feof函数
函数原型:int feof( FILE *stream );
函数功能:如果读取操作尝试读取超过文件末尾的位置,feof函数返回非0,否则返回0(函数 feof 只用于检测流文件)
微软官方文档中关于feof描述:

部分翻译:当超过文件末尾时,读取操作返回文件结束指示符,直到流关闭或调用rewind,fsetpos,fseek或clearerr为止。例如,如果文件包含10个字节,你从文件中读取了10个字节,feof会返回0,
因为虽然文件指针在文件的末尾,但是你没有尝试读取超过文件的末尾,只有在你尝试读取第11个字节之后feof函数才会返回非零值
换个说法就是:当文件内部位置指针指向文件末尾时,并未立即置位 FILE 结构中的文件结束标记,只有再执行一次读文件操作,才会置位结束标志,此后调用 feof 才会返回为真请读者注意下这句话:“只有再执行一次读文件操作,才会置位结束标志”
下面用断点调试来测试feof的返回值:
测试代码:

测试文本文件:

测试结果和运行结果:


从上面的测试结果可以看出,文本文件中只有三个数字,但循环却执行了四次,在第三次循环时读取了第三个数字后,文件内部的位置指针指向了文件末尾,但是此时用feof函数判断的结果仍然为0,并不会跳出循环,
只有当第四次循环中再用fscanf_s读取一次文件内容之后(此时fscanf_s的返回值是-1,也就是说读取是失败的,这也就是为什么第四次循环的ch的值没有变化),再用feof判断才会返回EOF(-1)
按照上面这种“先判断、再读取”写法,如果一个文件含有n个字符,那么while循环的内部操作会运行n+1次,如果不想多循环一次那么需要在while循环内部增加判断语句或者改成“先读取、再判断”
改法一:(while内部增加判断)

改法二:(while内部增加判断)

改法三:(先读取再判断)

踩坑二:ftell函数
函数原型:long ftell(FILE *fp);
函数功能:若函数调用成功,则返回文件位置指针当前位置相对于文件首的偏移字节数,否则返回-1L,(对于文本文件来说ftell的返回值是当前位置指针相对于文件起始位置的字节偏移量)
问题一:如果以追加读写的方式打开一个文本文件(文件内容为123),不进行任何I/O操作然后用ftell取得当前文件指针位置,请问ftell返回值为多少?
在微软的官方文档中有这样一段话:

红框中句子的意思:(当以追加的方式打开文件,在发生任何写入操作前文件指针移动到文件的末尾),如果以追加的方式打开文件且没有发生任何I/O操作,则文件指针在文件的开头,鉴于本人英语水平有限没怎么读懂这句话
,感觉有点矛盾,下面就用断点调试来解答问题一
文本文件:

打开方式:


调试结果:

从上面的调试结果可以看出,当以追加读写的方式打开文件时,在未发生任何I/O操作时ftell的返回值为0,意思是文件指针在文件开头,这个在文件开头的指针是下一次读取的位置,而不是下一次写入的位置(写入的位置在文件的末尾),意思是如果是用fscanf_s读取字符,那么读取的字符就是第一个字符,如果是写入字符那么就是在文件的最后一个字符的后一位写入(就是文件的末尾),下面放一张图方便理解

再回到上面那句话, (当以追加的方式打开文件,在发生任何写入操作前文件指针移动到文件的末尾),如果以追加的方式打开文件且没有发生任何I/O操作,则文件指针在文件的开头,这句话的前半句说的在文件末尾的
文件指针指的是写入的指针,而在文件开头的指针是读取的指针(并不是说读取和写入用的两个不同的指针,是同一个指针,如果是两个不同的指针的话那么无法确定ftell是返回的读指针还是写指针的位置)
意思是如果以追加读写的方式打开文件
,如果发生读操作那么读取的是第一个字符,如果发生写操作那么写入的位置是文件的末尾(也就是最后一个字符的后一位)
补充:如果以上面为前提发生了一次写入操作,此时ftell的返回值为多少?
测试文件:

测试代码:

断点调试结果:



从上面断点调试的结果可以看出,ftell在发生I/O操作前返回值是0,也就是下一次读取的位置,在发生一次写入操作后,ftell的返回值是4,也就是一下次写入的位置,如下图

从文本中读取字符——feof函数问题的更多相关文章
- 【Linux】替换文本中的字符
替换单个文本中的字符,有两种方法,如下详解 VIM替换 打开文件 vim test.txt 替换 :%s/原字符串/替换字符串/gg 直接替换 sed -i 's/原字符串/替换字符串/g' `ls ...
- 从文件中读取字符-多次调用read characters from file multiple calls
[抄题]: 接口:int read4(char * buf)一次从文件中读取 4 个字符.返回值是实际读取的字符数. 例如,如果文件中只剩下 3 个字符,则返回 3.通过使用read4 接口,实现从文 ...
- iOS 中基础字符判断函数收集(如判断大小写、数字等)
函数:isdigit 用法:#include 功能:判断字符c是否为数字 说明:当c为数字0-9时,返回非零值,否则返回零. 函数:islower 用法:#include 功能:判断字符c是否为小写英 ...
- .NET 中字符文本中的字符太多 错误处理
错误截图 问题描述 在ASP.NET中使用多层引号,要引起注意,引号使用不当会引起“字符文本中字段太多”编译错误!今天我就遇到了这个错误,整理于此! “字符文本中字段太多”错误提示过 ...
- PHP实现删除字符串中任何字符的函数
function delStr($start, $end, $orgenStr) { //读取要删除字符位置的前一部分字符串,并赋值给$temp //strpos读取字符第一次出现的位置 //subs ...
- 从文本中读取内容并把读取到的内容转化成二进制保存的形式(包含十进制数如何转换成二进制数dtob函数)
#include<stdio.h> #include<string.h> #include<stdlib.h> #include<malloc.h> d ...
- @MySQL中length字符长度函数使用方法
MySQL里面的length函数是一个用来获取字符串长度的内置函数,一个汉字是算三个字符,中文的标点符号也是算三个字符,一个数字或字母算一个字符.具体用法示例如下: 1.查看某字符串的长度 SELEC ...
- C++ 从txt文本中读取map
由于存入文本文件的内容都为文本格式,所以在读取内容时需要将文本格式的内容遍历到map内存中,因此在读取时需要将文本进行切分(切分成key和value) 环境gcc #include<iostre ...
- C# Split 字符文本中的字符太多
问题: ] { '<h1>', '</h1>' }); 原因: Split()里面是用char类型不是string字符串类型,所以只能用一个字符,必须先把多个字符替换成一个字符 ...
随机推荐
- PHP对接微信支付采坑
第一次做PHP商城项目对接微信支付接口,踩了N次坑,这也不对,那也不对,搞了很久,查了一些资料,终于实现了支付功能,小小总结一下,万一下次遇到就不用到处找资料了. 微信扫码支付 前期准备: 1.微信公 ...
- MySQL的show profile(已过时)简介以及该功能在MySQL 5.7中performance_schema中的替代
本文出处:http://www.cnblogs.com/wy123/p/6979499.html show profile 命令用于跟踪执行过的sql语句的资源消耗信息,可以帮助查看sql语句的执行情 ...
- Could not find a package,configuration file provided by "G2O" ,G2OConfig.cmake,g2o-config.cmake
因为项目需要使用到g2o,所以自己从git上面clone下来, git clone https://github.com/RainerKuemmerle/g2o.git 然后: cd g2o mkdi ...
- Could not find a package configuration file provided by "Sophus",SophusConfig.cmake
CMake Error at CMakeLists.txt:5 (find_package): By not providing "FindSophus.cmake" in CMA ...
- 今天花了好长的时间终于把SecureCRT安装成功了 现在分享给大家 安装的步骤, 希望对大家用帮助
转载地址:https://www.cnblogs.com/lianghe01/p/6618651.html 今天花了好长的时间终于把SecureCRT安装成功了 现在分享给大家 安装的步骤, 希望对大 ...
- 2018面向对象程序设计(Java)第18周学习指导及要求
2018面向对象程序设计(Java) 第18周学习指导及要求(2018.12.27-2018.12.30) 学习目标 (1) 综合掌握java基本程序结构: (2) 综合掌握java面向对象程序设 ...
- Spark SQL例子
综合案例分析 现有数据集 department.json与employee.json,以部门名称和员工性别为粒度,试计算每个部门分性别平均年龄与平均薪资. department.json如下: {&q ...
- Java虚拟机 内存区域划分
(图片来自https://www.cnblogs.com/whgk/p/6138522.html) 先从线程私有区开始介绍 虚拟机栈 Java虚拟机栈是由一个个栈帧组成的,当一个方法被调用时,代表这个 ...
- 简单了解pytorch的forward
import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torch.autogra ...
- 【python-dict】dict的使用及实现原理
以下内容是针对:python源码剖析中的第五章——python中Dict对象 的读书笔记(针对书中讲到的内容进行了自己的整理,并且针对部分内容根据自己的需求进行了扩展) 一.Dict的用法 Dict的 ...