使用 cin::fail() 从 stdin 进行无限循环读取

Infinite loop reading from stdin using cin::fail()

本文关键字:无限循环 stdin 读取 cin fail 使用      更新时间:2023-10-16

我正在努力解决向量push_back函数。目标是拥有一个函数,该函数可以推送 n 个元素,直到您决定停止。所以我对"停止"的想法是cin.fail()。

故障功能是

void pushbackVector(vector<double> &data)
{
    double input;
    cin >> input;
    for (int i = 0; i < 100; i++)
    {
        if (cin.fail())
        {
            cout << "Ending input.n";
            return;
        }
        else
        {
            data.push_back(input);
        }
    }

问题是,当我尝试使用它时,我进入了一个无限循环。

我还没有按ASC顺序对第一个向量进行排序,按

DESC顺序对第二个向量进行排序,并将第一个和第二个向量连接到第三个向量中。但是,我相信我可以自己管理这个问题。无论如何,整个代码....

#include<iostream>
#include<vector>
#include<algorithm>
#include<cctype>
using namespace std;
// function prototypes
void menu();
void printVector(const vector<double> &data);
void pushbackVector(vector<double> &data);
void sortVector (vector<double> &data);
int main()
{
    menu();
    vector<double> row1;
    vector<double> row2;
    /* not yet used
    vector<double> row3;
    */
    int input;
    cin >> input;
    bool exit = 0;
    while (!exit)
    {
        switch (input)
        {
            case 1:
                pushbackVector(row1);
                break;
            case 2:
                pushbackVector(row2);
                break;
            case 3:
                printVector(row1);
                break;
            case 4:
                printVector(row2);
                break;
            case 5:
                cout << "Printing out the contents of row 1n";
                printVector(row1);
                cout << "Printing out the contents of row 2n";
                printVector(row2);
                cout << "Printing out the contents of row 3n";
                // printVector(row3);
                break;
            case 6:
                cout << "Exittingn";
                exit = 1;
                break;
            default:
                cout << "Invalid choicen";
        }
    }

    return 0;
}
void menu()
{
    cout << "Choose an optionn";
    cout << "1) Enter first vectorn";
    cout << "2) Enter second vectorn";
    cout << "3) Print out the first vectorn";
    cout << "4) Print out the second vectorn";
    cout << "5) Print out all three vectorosn";
    cout << "6) Exitting the programn";
}
void printVector(const vector<double> &data)
{
    for(int i = 0; i < data.size(); i++)
    {
        cout << data[i] << ", ";
    }
    cout << "n";
}
void pushbackVector(vector<double> &data)
{
    double input;
    cin >> input;
    for (int i = 0; i < 100; i++)
    {
        if (cin.fail())
        {
            cout << "Ending input.n";
            return;
        }
        else
        {
            data.push_back(input);
        }
    }
}
void sortVector (vector<double> &data)
{
    cout << "Sorting your vector n";
    sort(data.begin(), data.end());
}

你只读取一次,在循环内移动读取:

void pushbackVector(vector<double> &data)
{
    double input;
    // cin >> input;   --------------
                                    //
    for (int i = 0; i < 100; i++)   //
    {                               //
        cin >> input;   // <---------
        if (cin.fail())
        {
            cout << "Ending input.n";
            return;
        }
        else
        {
            data.push_back(input);
        }
    }

这将确保您实际获得输入。现在,如果您不打算输入 100 个值,则需要以某种方式通知流。这是通过在其中插入"EOF 字符"来完成的。在窗口上按 CTRL+Z,在 unix 终端上按 CTRL+D。

当从流中读取时,它会进入fail(和eof)状态,除非您在适当的时候通过调用cin.clear()来清除错误标志,否则它将保持这种状态。

你也犯了同样的错误。在while循环之前,您只读取一次,因此input保留您初始输入的值并继续输入相同的选项。我认为这就是你所说的无限循环。要修复此问题,请将 read 语句移到switch 之前。

希望有帮助。


另外,这就是我编写函数的方式:

double input;
for (int i = 0; (cin >> input) && i < 100; ++i) {
     data.push_back(input);
}
cout << "Ending input.n";

流可以在布尔表达式中使用 - 它们转换为!fail()的结果 - 这是控制循环的一种方便且惯用的方法。

无限循环是由您正在阅读的事实引起的:

cin >> input;

一次,然后进入一个while循环(在你的main中),它将永远持续下去(除非输入最初等于6)。

改变:

cin >> input;
bool exit = 0;
while (!exit)
{
    // ...

自:

bool exit = 0;
while (!exit)
{
    cin >> input;
    // ...

根据您的逻辑,在以下位置的pushbackVector函数中也会发生同样的情况:

double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
    // ...

您可能希望将其更改为:

double input;
for (int i = 0; i < 100; i++)
{
    cin >> input;
    // ...

改为执行以下操作:

void pushbackVector(vector<double> &data)
{
    double input;
    while (cin >> input) //will return true when there's valid input, otherwise false
    {
        if (input == -1)
        {
            cout << "Ending input.n";
            return;
        }
        else
        {
            data.push_back(input);
        }
    }

这将读取输入,直到您输入 -1 或输入无效输入。

我认为依靠cin.fail()不是一个好主意。 链接中解释了使用fail()的正确方法。 这不是你所期望的。

撇开放错位置的读数不谈,如果您输入了不应该输入的内容,则需要清除输入。

如果

cin.clear(); 
cin.ignore( numeric_limits<streamsize>::max(), 'n' );

我会按以下方式编写函数

void pushbackVector( std::vector<double> &data )
{
    cin.clear(); 
    cin.ignore( std::numeric_limits<streamsize>::max(), 'n' );
    data.insert( data.end(), std::istream_iterator<double>( std::cin ), std::istream_iterator<double>() ); 
}

几天前我完成了,但我忘了发布我的答案。谁知道我可以说如果 cin 失败,停止输入但不结束程序,哈哈。

    #include<iostream>
    #include<vector>
    #include<algorithm> // for sort algorithms
    #include<iomanip>  // for setprecision
    using namespace std;
    // function prototypes
    void menu();
    void printVector(const vector<double> &data);
    void pushbackVector(vector<double> &data);
    void sortVector (vector<double> &data);
    int main()
    {
        vector<double> row1;
        vector<double> row2;
        vector<double> row3;
        int input;
        bool exit = false;
        while(!exit)
        {
            menu();
            cin >> input;
            switch (input)
            {
                case 1:
                    cout << "Entering vector 1n";
                    pushbackVector(row1);
                    sortVector(row1);
                    cout << "n";
                    break;
                case 2:
                    cout << "Entering vector 2n";
                    pushbackVector(row2);
                    sortVector(row2);
                    reverse(row2.begin(), row2.end());
                    cout << "n";
                    break;
                case 3:
                    cout << "Printing out vector 1n";
                    printVector(row1);
                    cout << "n";
                    break;
                case 4:
                    cout << "Printing out vector 2n";
                    printVector(row2);
                    cout << "n";
                    break;
                case 5:
                    // reserve enough space for all of row1's and row2's elements
                    row3.reserve(row1.size() + row2.size());
                    // insert row1's elements at the end of row3
                    row3.insert(row3.end(), row1.begin(), row1.end());
                    // insert row2's elements at the end of row3
                    row3.insert(row3.end(), row2.begin(), row2.end());

                    cout << "Printing out the contents of vector 1n";
                    printVector(row1);
                    cout << "Printing out the contents of vector 2n";
                    printVector(row2);
                    cout << "Printing out the contents of vector 3n";
                    printVector(row3);

                    cout << "n";
                    break;
                case 6:
                    cout << "Exittingn";
                    exit = true;
                    break;
                default:
                    cout << "Invalid choicen";
            }
        }

        return 0;
    }
    void menu()
    {
        cout << "Choose an optionn";
        cout << "1) Enter first vectorn";
        cout << "2) Enter second vectorn";
        cout << "3) Print out the first vectorn";
        cout << "4) Print out the second vectorn";
        cout << "5) Print out all three vectorosn";
        cout << "6) Exitting the programn";
    }

    void printVector(const vector<double> &data)
    {
        for(int i = 0; i < data.size(); i++)
        {
            cout << setprecision(4) << data[i] << " ";
        }
        cout << "n";
    }
    void pushbackVector(vector<double> &data)
    {
        double input;
        int numOfItems;
        cout << "How many items you want to add into vector?: ";
        cin >> numOfItems;
        for (int i = 0; i < numOfItems; i++)
        {
            cin >> input;
            if (cin.fail())
            {
                cout << "Ending input.n";
                return;
            }
            else
            {
                data.push_back(input);
            }
        }
    }
    void sortVector(vector<double> &data)
    {
        cout << "Sorting your vector n";
        sort(data.begin(), data.end());
    }