C++ cin不同状态详细讲解

来自:网络
时间:2023-01-01
阅读:
目录

前言

在C++中std::cin>>x,这是一条从std::cin中读取输入到x中的语句。而>>操作数是从标准输入中读取一个字符串,并把它保存在x对象中。

读取操作包括:

1、从输入流缓冲区缓存的输入字节快中提取对应于右操作数数据类型的字节字块。如果缓存为空,则等待输入设备提交字节块。

2、再将字节子块转换为右操作数对应类型的编码存放在右操作数中。

对于cin之类的流对象有good和not good两种状态,cin>>x读取数据成功时,会返回good状态;cin>>x读取数据失败时,会返回not goot状态。注意good状态的流才能读/写流缓冲区的数据;not good状态的流会忽略即不执行读/写操作。

反过来,流的读/写操作也会影响流的状态,成功的读/写操作会使流保持good状态;失败的读/写操作会设置流的状态变量的错误标志,表示流在读/写操作后处于某种错误(not good)的状态。

流的错误状态可以分为failbit、eofbit和badbit三种错误状态。

常量failbiteofbitbadbit转为10进制
ios::failbit1004
ios::eofbit0102
ios::badbit0011
ios::goodbit0000

基本读取状态的函数rdstate(),其余状态读取函数是good()、fail()、eof()、bad()等。

三种错误状态:

  • fail():读取值与期望接受值的类型不兼容即错误格式,状态变量的failbit被置位,fail()为真,进入fail状态。这种错误是可恢复的,可重新设置流为good状态,继续读取数据,但需要丢弃前面输入的数据。
  • eof():读取值为文件结束标记eof,此时cin会记录该标记,状态变量的eodbit和failbit被同时置位,eof()为真,进入eof状态。
  • bad():由于输入设备故障导致的数据丢失,状态变量的badbit和failbit被置位,bad()为真,进入bad状态,这种错误不可恢复,流对象将不可再用。

注意:当流处于错误状态时,状态变量的failbit总是被置位(true),因此有时候也可以将表达式!fail()作为判断流是否为good的条件来使用。

介绍一下cin的三个函数:

  • cin.clear():是用来更改cin的状态标识符的,将cin的所有状态值重设为有效值。
  • cin.sync():是用来清除缓存区的数据流的。
  • cin.ignore(n,ch):从输入流中提取字符,提取的字符被忽略,不被使用,每抛弃一个字符,它都要计数和比较字符,如果计数值达到n或者被抛弃的字符是ch,则cin.ignore()函数执行终止,否则继续等待。

注意:当cin出错时,先要用cin.clear()重置cin状态值后,后面两个函数才能起到作用,但cin.ignore()要比cin.sync()更加灵活。

一、下面给几个案例

#include <iostream>
using namespace std;
int main()
{
    int x;
    cout << "请输入一个整数:";
    cin >> x;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    return 0;
}

1、输入正确且类型匹配的情况:

C++ cin不同状态详细讲解

2、输入一个字符时,类型不匹配的情况:

C++ cin不同状态详细讲解

3、以eof结尾:

(在Windows下是输入Ctrl+z,Linux下是输入Ctrl+d,都要进行换行后再输入)

C++ cin不同状态详细讲解

二、当我们对这个程序进行改进后

#include <iostream>
using namespace std;
int main()
{
    int x;
    int sum = 0;
    cout << "请输入一串整数:";
    while (cin>>x)
    {
        sum += x;
    }
    cout <<"sum = " << sum << endl;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    cout << endl;
    cin.clear();
    char y;
    cin >> y;
    int z;
    cin>>z;
    cout <<"y = " << y << endl;
    cout <<"z = " << z << endl;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    return 0;
}

C++ cin不同状态详细讲解

在代码中用了一个循环输入,提示输入一串整数,在前面四个数都是整数的情况下,而第五个数输入了一个字符,后面两个数仍然是整数,但是当执行时,sum的值却是14,也就是说x成功保存了四个数,这就是上面说的fail错误状态,x不能再读出流缓冲区的数据,这是因为第五个数是字符类型的,与x类型不匹配,再用clear()函数重置cin状态,由于y是char类型,z是int类型,后面的cin>>y和cin>>z又可以继续读出流缓冲区里的数据。

#include <iostream>
using namespace std;
int main()
{
    int x;
    int sum = 0;
    cout << "请输入一串整数:";
    while (cin>>x)
    {
        sum += x;
    }
    cout <<"sum = " << sum << endl;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    cout << endl;
    cin.clear();
    cout << " clear后:" << endl;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    cout << endl;
    int y;
    cin >> y;
    int z;
    cin>>z;
    cout <<"y = " << y << endl;
    cout <<"z = " << z << endl;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    return 0;
}

C++ cin不同状态详细讲解

这里只是将上面的char y改成了int y,可以看运行结果的不同,此时的cin.clear()虽然起作用,但由于流缓冲区里还有数据,y和z会尝试去读取里面的数据,而y的类型不匹配再次让流的状态变成fail状态,y和z就都不能读取数据了,输入y和z的值是程序自动初始化的。

#include <iostream>
using namespace std;
int main()
{
    int x;
    int sum = 0;
    cout << "请输入一串整数:";
    while (cin>>x)
    {
        sum += x;
    }
    cout <<"sum = " << sum << endl;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    cout << endl;
    cin.clear();
    cin.sync();
    int y;
    cin >> y;
    int z;
    cin>>z;
    cout <<"y = " << y << endl;
    cout <<"z = " << z << endl;
    cout << " cin.good(): " << cin.good() << endl;
    cout << " cin.rdstste(): " << cin.rdstate() << endl;
    cout << " cin.fail(): " << cin.fail() << endl;
    cout << " cin.eof(): " << cin.eof() << endl;
    cout << " cin.bad(): " << cin.bad() << endl;
    return 0;
}

C++ cin不同状态详细讲解

当在cin.clear()后面加上cin.sync()函数后,sync()函数会清除缓存区的数据,此时缓存区里面就没有数据了,对于cin>>y和cin>>z,就需要我们自己输入数据了。

总结

对于cin的错误状态,我们可以用cin的其他几个函数将其恢复成good状态,cin.clear()一般和cin.sync()一起使用。

参考书籍:Accelerated C++和Cpp_Primer_5

返回顶部
顶部