当前位置:主页 > c/c++教程 > C++ cin

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

发布:2023-03-05 14:00:02 59


给网友朋友们带来一篇相关的编程文章,网友蓟韶丽根据主题投稿了本篇教程内容,涉及到C++、cin、C++、cin状态、C++ cin相关内容,已被494网友关注,内容中涉及的知识点可以在下方直接下载获取。

C++ cin

前言

在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 
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、输入正确且类型匹配的情况:

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

3、以eof结尾:

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

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

#include 
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;
}

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

#include 
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;
}

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

#include 
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;
}

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

总结

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

参考书籍:Accelerated C++和Cpp_Primer_5

到此这篇关于C++ cin不同状态详细讲解的文章就介绍到这了,更多相关C++ cin内容请搜索码农之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持码农之家!


参考资料

相关文章

  • C++中调用复制(拷贝)函数的三种情况总结

    发布:2023-03-09

    这篇文章主要介绍了C++中调用复制(拷贝)函数的三种情况总结,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教


  • C++ Boost.Range与Adapters库使用详解

    发布:2023-03-07

    这篇文章主要介绍了C++ Boost.Range与Adapters库使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧


  • C++之值传递&指针传递&引用传递的示例详解

    发布:2023-03-06

    这篇文章主要为大家详细介绍了C++中值传递、指针传递和引用传递的定义与使用,文中的示例代码讲解详细,对我们学习C++有一定帮助,需要的可以参考一下


  • c++11&14-多线程要点汇总

    发布:2022-04-08

    这篇文章主要介绍了c++11&14-多线程的使用方法,文中代码非常详细,方便大家更好的参考和学习,感兴趣的朋友快来了解下


  • C++ 格式化日志输出实现代码

    发布:2022-04-24

    这篇文章主要介绍了C++ 格式化日志输出实现代码,需要的朋友可以参考下


  • C++如何去除cpp文件的注释详解

    发布:2023-03-03

    在日常工作中,我们会给c/c++代码写上一些注释,但是往往为了保持最终的代码尽可能小,我们需要删除注释,手动删除太缓慢了,下面这篇文章主要给大家介绍了关于C++如何去除cpp文件注释的相关资料,需要的朋友可以参考下


  • 浅谈C++函数声明后面加throw()的作用(必看)

    发布:2022-04-14

    下面小编就为大家带来一篇浅谈C++函数声明后面加throw()的作用(必看)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧


  • C++ Boost MultiArray简化使用多维数组库

    发布:2023-03-08

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称


网友讨论