C++:关于cin输入ctrl+Z之后不能再用问题的原因

哈哈哈,我又来了。

今天写一个需要两次循环输入的程序的时候,出现了一个问题。先贴代码:

#include<iostream>
#include<string>
#include<vector>
#include<stdexcept>

using std::cout;
using std::cin;
using std::endl;
using std::cerr;
using std::string;
using std::vector;
using std::out_of_range;


int CalcInt(vector<string> vecStr)
{
    int i,sum;
    for(i = 0,sum = 0;i!=vecStr.size();++i)
    {
        sum += stoi(vecStr.at(i));
    }
    return sum;
}
double CalcDou(vector<string> vecStr)
{
    int i;
    double sum = 0.0;
    for(i = 0;i != vecStr.size();++i)
    {
        sum += stod(vecStr.at(i));
    }
    return sum;
}
int main()
{
    vector<string> vecStr;
    string str;
    while(cin>>str)
    {
        vecStr.push_back(str);
    }
    try{
        cout<<CalcInt(vecStr)<<endl;
    }
    catch(out_of_range err)
    {
        cout<<err.what()<<endl;
        cout<<"转换整型失败!"<<endl;
    }
    
    vecStr.clear();
    
    while(cin>>str)
    {
        vecStr.push_back(str);
    }
    try{
        cout<<CalcDou(vecStr)<<endl;
    }
    catch(out_of_range err)
    {
        cout<<err.what()<<endl;
        cout<<"转换整型失败!"<<endl;
    }
    
    return 0;
}

代码执行如下:

在我敲完Ctrl+Z并键下回车后,直接出现270和0。然而有代码可知我本来的意思并非如此,本意是想要在输出一次之后,在进行一次输出。

可是好像第二次的输入直接失败了,还不等我有任何的输入。

思考了一下,猜想是否是cin的状态位被置为0,导致cin不能输入,强行输入强掳灰飞烟灭,导致输入失败。所以在后面的while输入循环前,加了个cin.clear();对cin标志位进行复位。

代码如下:

#include<iostream>
#include<string>
#include<vector>
#include<stdexcept>

using std::cout;
using std::cin;
using std::endl;
using std::cerr;
using std::string;
using std::vector;
using std::out_of_range;


int CalcInt(vector<string> vecStr)
{
    int i,sum;
    for(i = 0,sum = 0;i!=vecStr.size();++i)
    {
        sum += stoi(vecStr.at(i));
    }
    return sum;
}
double CalcDou(vector<string> vecStr)
{
    int i;
    double sum = 0.0;
    for(i = 0;i != vecStr.size();++i)
    {
        sum += stod(vecStr.at(i));
    }
    return sum;
}
int main()
{
    vector<string> vecStr;
    string str;
    while(cin>>str)
    {
        vecStr.push_back(str);
    }
    try{
        cout<<CalcInt(vecStr)<<endl;
    }
    catch(out_of_range err)
    {
        cout<<err.what()<<endl;
        cout<<"转换整型失败!"<<endl;
    }
    
    vecStr.clear();
    cin.clear();
    while(cin>>str)
    {
        vecStr.push_back(str);
    }
    try{
        cout<<CalcDou(vecStr)<<endl;
    }
    catch(out_of_range err)
    {
        cout<<err.what()<<endl;
        cout<<"转换整型失败!"<<endl;
    }
    
    return 0;
}

其结果如下:

成功了!

既然这样了,仔细解释一下原理:

其实在《C++Primer5E》8.1.2中对IO条件状态有着仔细地解释,但是书上讲的多,而且有些东西讲的比较分散,所以有些东西我总结在这里:

1.IO操作一个与生俱来的问题就是可能发生错误。一些错误可恢复,而其他错误发生在系统深处,超出应用程序可以修正的范围。故而IO类有定义一些函数和标志,可以帮助我们访问和操纵流的条件状态。具体条件状态可以百度查看。

2.cin中的条件状态表示主要有四个标志位,badbit,failbit,eofbit,goodbit。其中,badbit在流崩溃的情况下被置位,failbit在IO操作失败的情况下被置位,eofbit在流达到文件结束的时候被置位,goodbit为0表示流未处于错误状态,当goodbit为0时流为有效状态,而另外三个标志位任何一个被置位都将导致流错误。clear()函数将流复位,状态置为有效。

3.Ctrl+Z表示文件结束符,当cin读到时,则eofbit和failbit都被置位。此时流处于无效状态。

4.一个流一旦发生错误,其上的后续的IO操作都会失败。

以上就是原理的概述。

posted @ 2018-04-09 17:34  泛未分晨  阅读(402)  评论(0编辑  收藏  举报