getchar()指令

在stdio.h头文件中进行了定义,单次读取一个字符,包括空格、换行符等都能读取。很多时候,在不确定输入长度的情况下,常常使用while循环配合getchar()对字符串进行读取。判断while循环结束的条件需要认真考虑,下面主要分析文件尾条件下getchar()指令对文件尾条件EOF的读取情况。

EOF

EOF是一个宏定义,通常定义在stdio.h文件中(#define EOF -1)。主要用来判断文件的结束。有些操作系统使用内嵌的Ctrl+Z字符来标记,不过现在也有其他选择比如直接记录文件的大小信息来判断是否到结尾。
不论何种方式,在C语言中,用getchar()读取文件检测到文件结尾时便会返回一个特殊值EOF,scanf()函数也一样。

键盘输入模拟文件尾条件的测试

但在日常编程中,有时需要键盘输入模拟文件尾,以Windows为例,不少资料会说键入Crtl+Z可以模拟文件尾EOF。但实际上在运行测试过程中,会发现似乎并不是这么简单。
以一个C++简单程序为例:

//EOF test
#include <iostream>
using namespace std;
int main()
{int testArr[100];  //EOF为-1,char一般实现为无符号,故用int数组存储int i = 0;int count = 0;  //计数器while ((testArr[i++] = getchar()) != EOF) {cout << testArr[i - 1] << " ";count++;}cout <<"arr[i-1]:"<< testArr[i-1] << endl;cout << "Total counts:"<<count;return 0;
}

运行截图如下:(输入为abc+Ctrl+Z)

输入:
a+b+c+Ctrl+Z
输出:
97 98 99 26
预期应该输出 a b c对应的ASCII码,然后输出arr[i-1]:-1;总共循环三次,输出Total counts:3,然后程序结束。
但实际上键入Cttl+Z后,确实立即进行了输出,但并没有如预料的终止循环,程序仍然在等待接下来的输入,同时值得注意的是,已经输出了4个值,前三个分别是a b c对应的ASCII码,这点没有问题,但第四个值26是如何得出的?

暂且先把这个问题留到后面解释,进一步执行,再次输入Ctrl+Z,回车:

此时发现,程序真正地执行结束,而且数组有效读取的最后一个元素确实是-1。

原因分析

从第一次键入Ctrl+Z的结果开始分析,输出了4个值,显然,Ctrl+Z确实被读入了,但对应的并不是-1,而是ASCII码26,网上查到ASCII码表中26对应的是:

进一步查找发现,网上有这样一段描述:
“在微软的DOS和Windows(以及CP/M和许多DEC操作系统)中,读取数据时终端不会产生EOF。此时,应用程序知道数据源是一个终端(或者其它“字符设备”),并将一个已知的保留的字符或序列解释为文件结束的指明;最普遍地说,它是ASCII码中的替换字符(Control-Z,代码26)。一些MS-DOS程序,包括部分微软MS-DOS的shell(COMMAND.COM)和操作系统功能程序(如EDLIN),将文本文档中的Control-Z视为有意义数据的结尾,并且/或者在写入文本文档时将Control-Z添加到文档末尾”1

那么,现在可以明白了,26的来源确实是因为Ctrl+Z模拟的EOF,但此次读取并不会真正地将它理解成-1,而是理解成替换符(对应ASCII码26),同时刷新输入缓存。

相应的,当换行将缓冲区刷新后,第一个遇到就是Ctrl+Z,此时才会真正被理解成EOF(-1),终止循环。验证如下:当连续输入两个Ctrl+Z时也不会终止循环,而且计数仍然何之前一样,而当输入缓存区遇到的第一个是Ctrl+Z时会理解成遇到文件尾,立即结束输入。


在C Primer Plus第六版第8章中有这样一段描述:
“模拟EOF的概念是在使用文本界面的命令行环境中产生的。在这种环境中,用户通过击键与程序交互,由操作系统生成EOF信号。但是在一些实际应用中,却不能很好地转换成图形界面(如Windows和Macintosh),这些用户界面包含更复杂的鼠标移动和按钮点击。程序要模拟EOF的行为依赖于编
译器和项目类型。例如,Ctrl+Z可以结束输入或整个程序,这取决于特定的设置。”

C++ Primer Plus第五版第155页中提到:
“用于PC的Microsoft Visual C++、Borland C++5.5和GNU C++都能够识别行首的Ctrl+Z,但用户必须随后按下回车键。总之,很多PC环境都将Ctrl+Z视为模拟的EOF,但具体细节(必须在行首还是可以在任意位置,是否必须按下回车键等)各不相同”

由此可见,本人Windows10系统的计算机上,在命令窗口的文件尾条件应该是在行首输入Ctrl+Z,但之后不一定立即要按下回车

最后,在Linux系统上进行测试,发现也是需要在行首才能模拟EOF,输入Ctrl+D。输入为: a+b+c+Ctrl+D+Enter+Ctrl+D
输出如下图所示:


不过与Windows不同的地方在于,模拟EOF不在行首的情况下,Linux系统上单纯用Ctrl+D刷新输入缓存,立即向屏幕输出,但不会理解同时成替换字符(ASCII码26)而读取。


  1. https://baike.baidu.com/item/EOF/1017800?fr=aladdin ↩︎

键盘模拟文件尾EOF相关推荐

  1. python判断是否到了文件尾

    1.利用文件对象的seek方法得到文件尾的数值: f = open(filename, 'rb') f.seek(0, 2) #第一个参数表示偏移量(正数表示向后移动,负数表示向前移动), #第二个参 ...

  2. 关于C之文件结尾EOF与二进制文件换行符

    文件结尾: 计算机操作系统要以某种方式判断文件的开始和结束. 检测文件结尾的一种方法是, 在文件末尾放一个特殊的字符标记文件尾. CP/M. IBMDOS和MS-DOS的文本文件曾经用过这种方法. 如 ...

  3. mfc如何判断读到文件尾_C++ 判断读取文件尾

    主要在于eof()不只是读取文件的最后一个字符,它会接着往后读取,如果此函数返回ture时,则此时返回的文件结束符0xFF才是真正的结尾. 具体内容如下: 在使用C/C++读文件的时候,一定都使用过e ...

  4. WinIo64驱动级别的键盘模拟(java)

    最近因为爬虫登录的网站加了密码控件,尝试了很多方法都不能破解(该控件屏蔽了虚拟软键盘),寻找资料中发现了winIo这么工具,十几年前的东西了,它的官网貌似也处于游离状态,使用中也出现了很多问题,便以此 ...

  5. 遇文件尾测试结束c语言,Fortran和C语言测试文件尾的方法

    1. int ch = fgetc(fp); if(ch == EOF)break; 2. fgets返回NULL 3. fread返回0 还有适当的配合文件指针来使用 文件指针从0开始到size-1 ...

  6. C# 是否读到文件尾, 怎么判断

    不是问题的问题, 看样子真成了问题 多年前写都是直接判断 EOF, 现在发现没有这个方法了 对不起, 是写程序过程中的总结, 只是对我做了简单记录一下 StreamReader 判断文件尾 // 读入 ...

  7. 常见文件头,文件尾总结

    图片类 文件类型 后缀 文件头 文件尾 标志 JPEG .jpg .jpeg FFD8FF FFD9 JFIF PNG .png 89504E47 AE426082 PNG IEND IHDR GIF ...

  8. VB 输入超出文件尾(错误62)(转)

    原出处: http://hi.baidu.com/gamevip/blog/item/8c19b7114caba47dcb80c4c3.html 早期的VB是采用单字节处理方式(通常也称为ANSI方式 ...

  9. error C1004 发现意外的文件尾

    error C1004: 发现意外的文件尾 后来发现头文件引用放在类的后面引起的 经过多次测试,发现头文件引用还是放在文件最上面比较好. 放在文件中间或放在函数内部都可能引起问题.

  10. vim设置显示行号,vim跳转到文件头,文件尾

    设置行号: 当前文件有效:vim打开文件,输入:set number 或者 :set nu 开启,输入:set nonumber 或者 :set nonu 取消 系统范围内:终端输入 vim ~/.v ...

最新文章

  1. 面向对象----封装之proprty
  2. centos7删除符号链接_技术|在 Linux 中怎样移除(删除)符号链接
  3. hadoop报错:WARN mapred.JobClient: Error reading task outputNo route to host
  4. 事件时间/处理时间/进入时间(Event Time / Processing Time / Ingestion Time)
  5. hmm 求隐藏序列_结巴分词3--基于汉字成词能力的HMM模型识别未登录词
  6. 80. 删除排序数组中的重复项 II golang
  7. 22种编程语言新年快乐
  8. python process_Python Process/Thread 概念整理
  9. google python代码规范_Python代码这样写才规范优雅! (二)
  10. BigDecimal加减乘除
  11. php 简单日志搜索
  12. 欧几里得算法求最大公约数,最小公倍数
  13. Atitit timer tech定时器技术总结目录1.1. 程序语言timer dbtimer ,os tiemr 11.2. Atitit timer定时框架api 11.3. 相关技术
  14. Linux从入门到放弃(1)教学视频推荐以及一些经验分享
  15. Teamviwer和向日葵使用
  16. 图片 title 和 alt区别:
  17. 电子面单打印平台对接-快递鸟
  18. 全文搜索引擎,索引库
  19. 基本功:线程上下文切换
  20. gets与puts的使用,Str系列字符串的使用

热门文章

  1. 鹏业软件CAD云服务转图纸没反应的说明
  2. [填坑]ubuntu16.04安装腾达U12无线网卡驱动
  3. java聊天室需求分析_java聊天室源程序需求分析2业务需求2.1。与电视聊天
  4. jaxen-1.1-beta-6.jar下载,Dom4j的xpath的使用
  5. alpha-beta 极大极小值剪枝算法
  6. 综述---图像处理中的注意力机制
  7. 用Java写一个随机排序的功能
  8. cad等比例缩放快捷键_cad等比例缩放快捷键
  9. 分享116个PHP源码PHP源码,总有一款适合你
  10. UBNT rocket M5 无线设置的有关笔记