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

 更新时间:2022年10月19日 10:10:35   作者:Peak@  
cin是C++编程语言中的标准输入流对象,即istream类的对象。cin主要用于从标准输入读取数据,这里的标准输入,指的是终端的键盘。此外,cout是流的对象,即ostream类的对象,cerr是标准错误输出流的对象,也是ostream类的对象

前言

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

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

3、以eof结尾:

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

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

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

在代码中用了一个循环输入,提示输入一串整数,在前面四个数都是整数的情况下,而第五个数输入了一个字符,后面两个数仍然是整数,但是当执行时,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;
}

这里只是将上面的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;
}

当在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语言的函数栈帧

    详细理解函C语言的函数栈帧

    这篇文章主要为大家介绍了C语言的函数栈帧,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助,希望能够给你带来帮助
    2021-11-11
  • C语言计算分段函数问题

    C语言计算分段函数问题

    这篇文章主要介绍了C语言计算分段函数问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C语言中结构体与内存对齐实例解析

    C语言中结构体与内存对齐实例解析

    C语言结构体对齐也是老生常谈的话题了,基本上是面试题的必考题,这篇文章主要给大家介绍了关于C语言中结构体与内存对齐的相关资料,需要的朋友可以参考下
    2021-07-07
  • STL区间成员函数及区间算法总结

    STL区间成员函数及区间算法总结

    这篇文章主要汇总介绍了STL区间成员函数及区间算法,有需要的小伙伴可以参考下。
    2015-07-07
  • 详解C++中的inline用法

    详解C++中的inline用法

    在c/c++中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了inline修饰符,表示为内联函数。 栈空间就是指放置程序的局部数据(也就是函数内数据)的内存空间
    2017-09-09
  • C++中的Z字形变换问题

    C++中的Z字形变换问题

    将一个给定字符串 s 根据给定的行数 numRows ,以从上往下、从左到右进行 Z 字形排列,这样一个需求怎么实现呢,下面小编给大家带来了C++中的Z字形变换问题,需要的朋友可以参考下
    2022-07-07
  • 详细总结C++的排序算法

    详细总结C++的排序算法

    趁空闲时间,小编决定把C++的排序算法分析并总结下,以便温故知新。也方便需要的朋友可以参考学习。
    2016-07-07
  • 如何利用最简单的C语言实现AI五子棋

    如何利用最简单的C语言实现AI五子棋

    这篇文章主要给大家介绍了关于如何利用最简单的C语言实现AI五子棋的相关资料,包含了一些五子棋常见的功能,文中也通过详细的实例代码和图片介绍的非常详细,需要的朋友可以参考下
    2021-07-07
  • C语言实现俄罗斯方块的六种模式详程建议收藏

    C语言实现俄罗斯方块的六种模式详程建议收藏

    迟早一定会挂掉的俄罗斯方块,为什么至今仍是世界游戏之王?它是怎么编写的?本文将给大家详细介绍六种模式的实现,对大家的学习或工作具有一定的参考借鉴价值
    2022-02-02
  • C语言 数据结构之链表实现代码

    C语言 数据结构之链表实现代码

    这篇文章主要介绍了C语言 数据结构之链表实现代码的相关资料,需要的朋友可以参考下
    2016-10-10

最新评论