翻译《有关编程、重构及其他的终极问题?》——21.正确的检查文件的结尾符(EOF)
来源:互联网 发布:二维码点餐软件 编辑:程序博客网 时间:2024/04/19 07:55
翻译《有关编程、重构及其他的终极问题?》——21.正确的检查文件的结尾符(EOF)
标签(空格分隔): 翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2017年03月01日
21.正确的检查文件的结尾符(EOF)
让我们继续文件处理的话题,深入了解一下EOF。但这次我们会说说关于完全不同类型造成的bug,这通常会在部本地化版本的软件中发现。
下面这段代码来自Computational Network Toolkit。PVS-Studio诊断的错误说明为:V739 EOF should not be compared with a value of the ‘char’ type. The ‘c’ should be of the ‘int’ type(译者注:大意是EOF不能和char类型的值比较,应该和int类型比较)。
string fgetstring(FILE* f){ string res; for (;;) { char c = (char) fgetc(f); if (c == EOF) RuntimeError("error reading .... 0: %s", strerror(errno)); if (c == 0) break; res.push_back(c); } return res;}
解释
让我们看看EOF是如何被声明的:
#define EOF (-1)
如你所见,EOF只不过是一个值为-1的整型。fgetc()函数返回一个整型的值,也就是说,它可以返回值为0到255(或-1)的数字。在上面的代码中这个值被转换为char类型,因此值为0xFF(255)就转为值为-1了(译者注:如果不明白,回去复习基础的二进制表达正数、负数的基本知识),所以-1也就作为了文件的结尾符进行处理(EOF)。
如果用户使用了扩展的ASCII码,当程序没有正确处理字母表中某一个符号时,也就会有遇到一个错误。
比如Windows 1251 code页,在俄文字母表中的最后一个字母值就是0xFF,因此,就被程序解释为文件的结尾符号。
正确的代码
for (;;){ int c = fgetc(f); if (c == EOF) RuntimeError("error reading .... 0: %s", strerror(errno)); if (c == 0) break; res.push_back(static_cast<char>(c));}
建议
其实我这里没有特别的建议,至于谈到EOF,我只是想展示一个比较有趣的错误的变化,因为部分人可能从来没有意识到。
记住,如果函数返回的是整型类型,不要马上把它转换为char类型,请停下来并确认相关代码都没有问题。顺便说一下,我们其实已经谈到过类似的问题,即在第二篇中讨论的memcmp()函数——“比0大的并不意味着就只是1”(其中的代码涉及到了MySQL)
- 翻译《有关编程、重构及其他的终极问题?》——21.正确的检查文件的结尾符(EOF)
- 翻译《有关编程、重构及其他的终极问题?》——20.光对文件做EOF检查可能还不够
- 翻译《有关编程、重构及其他的终极问题?》——9.使用'-0'符号作为结尾标记
- 翻译《有关编程、重构及其他的终极问题?》——26.潜伏的VARIANT_BOOL
- 翻译《有关编程、重构及其他的终极问题?》——前言
- 翻译《有关编程、重构及其他的终极问题?》——6.当把一个指针明确的转换为整型时,请检查所有相关代码
- 翻译《有关编程、重构及其他的终极问题?》——5.使用工具去分析你的代码
- 翻译《有关编程、重构及其他的终极问题?》——10.避免使用多个小的#ifdef块
- 翻译《有关编程、重构及其他的终极问题?》——13.表格化的格式化
- 翻译《有关编程、重构及其他的终极问题?》——17.使用专门的函数清除专有数据
- 翻译《有关编程、重构及其他的终极问题?》——23.自动获取字符串的长度
- 翻译《有关编程、重构及其他的终极问题?》——27.狡猾的BSTR字符串
- 翻译《有关编程、重构及其他的终极问题?》——7.不要在循环中调用alloca()函数
- 翻译《有关编程、重构及其他的终极问题?》——22.不要使用#pragram warning(default-X)
- 翻译《有关编程、重构及其他的终极问题?》——30.Visual C++和wprintf()函数
- 电子书《有关编程、重构及其他的终极问题?》的翻译
- 翻译《有关编程、重构及其他的终极问题?》——11.不要试图把尽量多的操作符放到一行代码里
- 翻译《有关编程、重构及其他的终极问题?》——4.小心--操作符,请把表达式放在括号中
- Gradle实现多渠道打包
- OpenCv 4----(正式篇)opencv的简介 /* 不断更新 */
- 小抄:UDTF&UDAF示例
- 游戏设计模式
- Android Studio引入so库
- 翻译《有关编程、重构及其他的终极问题?》——21.正确的检查文件的结尾符(EOF)
- js 优化方面
- python 判断是不是中文字
- java再复习——泛型使用语法上的一些坑
- servlet中使用HttpServletResponseWrapper截获返回的页面内容
- java 企业网站源码模版 有前后台 springmvc SSM 生成静态化
- Vulkan编程指南翻译 第四章 队列和命令 第3节 清空和填充图像
- 反编译工具的使用
- 插桩