C++ 处理文件结束符的两种不同方式

首先来看一下下面这小段代码:

#include<iostream>
#include<cstdlib>
#include<string>

int main()
{
  std::string str = 0;
  while (std::cin >> str);
  system("pause");
  return 0;
}

  里面while一直检查输入流的状态,知道接收到文件结束符(在windows上面是Ctrl+Z 在Linux/unix上面是Ctrl+D)或错误输入,但是当输完多个字符再加上一个文件结束符再按Enter的时候,发现输入流并没有停止请求输入,而是一直等待用户继续输入:
这里写图片描述
直到在按下Ctrl+Z之前没有任何字符输入程序才会结束。

把string换成char,结果也一样:

char ch;
while(std::cin >> ch);

这里写图片描述

而再把类型换成int:

int ival = 0;
while(std::cin >> ival);

这里写图片描述

  结果则不一样,在输入数字1后直接Ctrl+Z,程序就结束了,把int换成其它的整形、浮点型结果都是一样的。

这就说明,输入流处理文件结束符的方法对字符字符串和算术类型的还是不一样的。


在网上找到了一点原因分析:

  当从键盘输入一串字符并按回车后,这些字符会首先被送到输入缓冲区中存储。每当按下回车键后,cin.get()就会检测输入缓冲区中是否有了可读的数据。cin.get()还会对键盘上是否有流结束标识的Ctrl-z或者ctrl-d键按下做出检查,其检查的方式有两种,阻塞式以及非阻塞式。

  windows系统一般采用阻塞式检查ctrl-z,Unix/Linux系统下一般采用非阻塞式的检查ctrl-d.

  阻塞式检查方式是指只有在回车键按下之后才对此前是否有ctrl-z组合键按下进行检查。另外,如果输入缓冲区中有可读的数据则不会检测ctrl-z,因为有可读数据,说明还未到流的末尾。需要注意的时,ctrl-z产生的不是一个普通的ascii字符,因此ctrl-z不会跟其它从键盘输入的字符一样能够存放在输入缓冲区中。因此,若要使ctrl-z产生作用,输入ctrl-z之前不应输入任何字符,即输入回车键把之前输入的字符全部送入缓冲区中后,紧接着应输入ctrl-z,然后输入回车键,告知系统检测流结束符ctrl-z.

  非阻塞式是指按下ctrl-d之后立即响应的方式。如果在ctrl-d输入之前已经从键盘输入了字符,则ctrl-d相当于回车,即把这些字符送到了输入缓冲区供读取使用,此时ctrl+d不再起流结束符的作用。若ctrl-d输入之前没有任何键盘输入,则ctrl-d就是流结束的信号。

windows 下ctrl-z使用举例说明如下:

  从键盘上输入abcd^z 再输入回车键后,系统处理如下:因为回车的作用,前面的abcd等字符被送到输入缓冲区中,而^z不会产生字符,因此不会存储到缓冲区中。这时,cin.get()检测到输入缓冲区中已经有数据存在,就不会检测有无^z存在,cin.get()从缓冲中读取相应的数据,如果读取完了,则输入缓冲区重新变为空,cin.get()等待新的输入,可见尽管有ctrl-z输入,但是之前有其它字符,系统并未监测到流结束符。
  因此输入流结束符的条件就是:^z之前不能有任何字符输入(回车键除外),然后再用回车键通知系统做流结束符检测。
  而对于处理算术类型的,任何情况下,只要把文件结束符送到缓冲区,输入流就会检测到并结束接收输入。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值