这个问题源于《c++Primer第五版》p15的一个程序。我在codeblocks里键入源程序,并测试输入样例,得到的结果和书上的不一样。源代码如下:
#include<iostream>
using namespace std;
int main(){
//currVal是我们正在统计的数;我们将读入的新值存入val
int currVal=0,val=0;
//读取第一个数,并确保确实有数据可以处理
if(cin>>currVal){
int cnt=1; //保存我们正在处理的当前值的个数
while(cin>>val){ //读取剩余的数
if(val==currVal) //如果值相同
++cnt; //将cnt加1
else { //否则,打印前一个值得个数
cout<<currVal<<" occurs "
<<cnt<<" times"<<endl;
currVal=val; //记住新值
cnt=1; //重置计数器
}
}//while循环在这里结束
//记住打印文件中最后一个值的个数
cout<<currVal<<" occurs "
<<cnt<<" times"<<endl;
}//最外层的if语句在这里结束
return 0;
}
输入样例为:
42 42 42 42 42 55 55 62 100 100 100
输出应该是:
42 occurs 5 times
55 occurs 2 times
62 occurs 1 times
100 occurs 3 times
而事实上,输入测试样例之后,按回车键输出的结果为:
显然输出结果不尽如人意,而且本应该结束的while(cin>>val)循环也还没有结束,那么究竟是什么原因呢?
原来当我们使用一个istream对象(cin)作为条件时,其效果是检测流的状态。如果流是有效的,即流未遇到错误,那么检测成功。当遇到文件结束符(end of file),或遇到一个无效输入(例如输入的值不是一个整数),istream对象的状态就会变为无效。处于无效状态的istream对象就会使条件变为假。
所以光有回车键是不行的,要有文件结束符,那怎么从键盘输入文件结束符呢?
当从键盘向程序输入数据时,对于如何指出文件结束,不同操作系统有不同的约定。在Windows操作系统中,输入文件结束符是敲Ctrl+Z,然后按Enter或Return键。在UNIX系统中,包括MacOS X系统中,文件结束符输入是用Ctrl+D。
于是我用Ctrl+Z+Enter来结束循环:
果然如此。
我仿照例程写了一个程序,没想到又发现了一个新的问题:
string str,currStr;
if(cin>>currStr){
while(cin>>str){
cout<<currStr<<endl;
currStr=str;
}
cout<<currStr;
}
return 0;
用Ctrl+Z+Enter来结束循环:
可是循环并没有结束,这是为什么呢?
我在这篇博文《C++处理文件结束符的两种不同方式》里找到了答案:例程用的是int类型,而我的程序是string类型,所以例程可以用Ctrl+z+enter结束输入,而我的不能。
因为我的是字符串或字符对象。
只能像借鉴博文那样用enter+Ctrl+z+enter来结束循环。
这就说明,输入流处理文件结束符的方法对字符字符串和算术类型还是不一样的。