2022-04-03 关于C++中标准输入cin失效的问题

cin的用法很简单,但是一不小心就会出问题,考虑下面的情况:

    double test;
    std::cout << "请输入double数字,结束请输入'q':" << std::endl;
    while (std::cin >> test)
    {
        std::cout << test << std::endl;
    }
    int test2;
    while (std::cin >> test2)
    {
        std::cout << test2 << std::endl;
    }

test循环完成后,用户按了’q’,之后还会进入第二个test2循环么?

不会,因为cin的状态已经是错误状态了,需要重新恢复为可用状态,也就是通过 “ cin.clear() ” 进行重置,但重置后就能进入么?

还是不行,为什么?

因为缓冲中还有一个字符 ‘q’ ,如果不解决这个问题,那么cin仍然会变为错误状态,此时就需要引入另外一个函数 “cin.ignore()" 去除最后输入的字母 ‘q’ ,之后cin会自动跳过换行符,进行数据输入。

以为这就结束了?请问如果用户输入的是 “quit” 这个单词会怎样?

cin仍会置错,因为缓冲区没有清空,且不是int类型,所以需要再进一步,用 “ cin.ignore(10, ‘\n’) ” 来解决问题,这个用法的意思是,去除缓冲区10个以内的字符,直到遇到换行符。

如果不是碰到比较疯狂的用户,疯狂乱输入,基本问题就解决了。

但是,程序员只能做到自己能做到的,用户端是无法把控的,不要轻视程序使用者的脑洞,所谓完美的程序,需要对的人使用。

另外,如果程序设计的比较完善,通常会设计不必破坏流状态的代码,如:

    double test;
    std::cout << "请输入double数字,结束请输入 0 :" << std::endl;
    while (std::cin >> test)
    {
        if(test==0) { break; }
        std::cout << test << std::endl;
    }
   if (cin.fail())
    {
        cin.clear();
        cin.ignore(10, '\n');
    }

按照一般指示,输入0即可退出,但是就算输入字母也有后序的判断,清理状态。

不要以为这就完了。还有什么问题呢?

如果一个用户使用文件流进行输入,又多了一种状态,叫文件结尾,文件结尾也会令流退出,如果此时再强制清空流状态企图恢复,也会产生问题。

所以,我们只需要复位除文件末尾的其他错误状态:

    if (cin.fail())
    {
        cin.clear(cin.rdstate() & ~std::istream::failbit & ~std::istream::badbit);
        cin.ignore(10, '\n');
    }

上面代码设计位操作,将cin的状态进行 “位与 ”,“位求反fail状态”,“位与”,“位求反bad状态”.

假设目前cin状态为0100,即fail状态,恢复过程用二进制表示:

0100 & ~0100 & ~ 0001

结果为 0000,如果cin的状态为eof结尾状态,0010,则上述位运算结果仍是0010,就可以退出了。

写道最后,好像是C++流操作的劝退文,没关系,当初我看流状态这章的时候也是懵逼的,经过程序拷打几回,自然就会研究,掌握了。

你可能感兴趣的:(笔记,c++,cin)