博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于C++ 输入输出流状态控制
阅读量:4648 次
发布时间:2019-06-09

本文共 3786 字,大约阅读时间需要 12 分钟。

关于这一点呢,是在做《C++primer 》关联容器map的一道习题中发现这个蛋疼的问题的。

问题是这样的:

我想要将while循环条件设置为cin,这样就可以不断等待输入,普通的程序可以直接按下ctrl+z中止输入,麻烦在于这里有两层这样的while循环,而ctrl+z会一次性全部退出,导致无法实现想要的目的(在每个外层循环内部,可以输入有限量可中止的内层循环变量,也就是说第一次按下ctrl+z只停止内层的循环,等待进行下一次外层循环,然后再进入内层循环……)

1 #include<iostream> 2 #include<map> 3 #include<string> 4 #include<vector> 5 using namespace std; 6 int main() 7 { 8     map<string, vector<pair<string, string>>> family; 9 string family_name;10 11 while (cin) //输入流状态正常就持续输入,ctrl+z可使其错误而退出 12 { 13 cout << "please input the family name: " << endl;14 cin >> family_name;15 16 vector<pair<string, string>> children; //vector>,用于给family的second赋值17 pair<map<string,vector<pair<string,string>>>::iterator,bool> ret=family.insert(make_pair(family_name, children)); //取insert的返回值18 19 if (!ret.second) //插入失败,表面之前map里面存在此键20 {21 cout << "the family name you give is already exist!" << endl;22 continue;23 }24 25 string child_name, birthday;26 cout << "please input the children name and birthday: " << endl; 27 28 while (cin >> child_name >> birthday) //输入child_name、birthday来初始化vector29 { 30 31 ret.first->second.push_back (make_pair(child_name, birthday) );32 //ret.first为map>>,->second之后表示vector>33 }34 35 cin.clear(); //置流于有效状态,使ctrl+z不会直接退出所有的cin,而只退出上面的cin>>child_name>>birthday36 }37 38 39 map<string, vector<pair<string, string>>>::iterator iter_map = family.begin(); //迭代器遍历,输出key对应的value40 while (iter_map != family.end())41 {42 cout << "family_name: " << iter_map->first << endl;43 44 vector<pair<string, string>> vec = iter_map->second;45 vector<pair<string, string>>::iterator iter_vec = vec.begin();46 47 while (iter_vec != vec.end())48 {49 cout << " ";50 cout << "children name: " << iter_vec->first << endl;51 cout << " ";52 cout << "birthday: " << iter_vec->second << endl;53 ++iter_vec;54 }55 56 ++iter_map;57 }58 59 system("pause");60 return 0;61 }

我们来分析一下面临的问题:

 

将cin >> value (某个变量)放在while的条件中是常见的等待输入的手段,那么如何中止循环呢?

使用ctrl+z组合键,可以中止循环,那么ctrl+z到底是怎么实现的呢?

 

下面是个人的理解和分析:

 

原来,ctlr+z是通过将输入流对象的条件状态设置为failbit来使cin>>value为false的,

输入流对象有badbit、failbit、eofbit以及有效等状态,分别对应于硬件错误导致被破坏的流状态、输入不匹配等造成的错误、文件中止导致流的结束、以及有效的流状态。

 

而通过cin.eof()、cin.fali()、 cin.bad()、 cin.good()的调用可以知道当前流的状态,比如:当前处于failbit状态,则cin.fail()返回true

 

这里还要介绍一个cin.clear()函数,可以将流状态值重置为有效。

 

下面用一段测验代码来说明:

#include<iostream>using namespace std;int main(){    int a;           while (cin >> a)        {            cout << "!" << endl;        }        //cin.clear();               if (cin.bad())            cout << "bad!" << endl;        else if (cin.fail())                //ctrl+z使其fail            cout << "fail!" << endl;        else if (cin.good())            cout <<"good!" << endl;       system("pause");    return 0;}

测验时,在输入几个数字后就按下ctrl+z

若无cin.clear()的调用,输出为fail!

    有cin.clear()的调用时,输出为good!

说明,ctrlz+z使流状态变为failbit,而clear可以重置其为有效状态

 

接下来:

#include<iostream>using namespace std;int main(){    int a, b;    while (cin >> b)    {        cout << "#" << endl;        while (cin >> a)        {            cout << "!" << endl;        }        //cin.clear();                if (cin.bad())            cout << "bad!" << endl;        else if (cin.fail())                           cout << "fail!" << endl;        else if (cin.good())            cout << "good" << endl;    }        if (cin.bad())        cout << "bad!!!!" << endl;    else if (cin.fail())                        cout << "fail!!!!" << endl;    else if (cin.good())        cout << "good!!!" << endl;    system("pause");}

双层while循环嵌套,

这时候,若无cin.clear()

当按下ctrl+z时可以发现,它将直接退出两层循环!

也就是说,ctrl+z可以直接令循环内外的cin的状态均为failbit

而加入cin.clear()代码后

        发现,这时候只退出了内层循环,内层循环是goodbit,程序在等待外层的输入,再次按下ctrl+z,发现此时的外层是failbit

(要将缩进应用于写作当中,哈哈哈!)

 

这样就基本了解清楚了ctrl+z和cin使用的一些内容和注意事项,每次学习遇到这种小细节的时候总是很令人纠结的,但是解决之后会觉得很是神奇,在学习STL 使用的时候解决了一个之前阅读IO 不太仔细的漏洞,这样子解决之后还是很爽的啦!

转载于:https://www.cnblogs.com/gaoduan/p/3819059.html

你可能感兴趣的文章
crawlspider
查看>>
正则表达式及其应用
查看>>
整理90部好看的经典喜剧片
查看>>
美丽的数学家:如果您讨厌数学,这些其实都是人生故事
查看>>
MVC判断用是否登录了平台
查看>>
统计剩余字数(jq版)
查看>>
HDU 4747 Mex【线段树上二分+扫描线】
查看>>
noi.ac NOIP2018 全国热身赛 第四场 T1 tree
查看>>
Apicloud——关于索引列表
查看>>
(转)linux下vi编辑器编写C语言的配置
查看>>
多线程基础知识 转
查看>>
MyBatis generator 使用方式 小结
查看>>
Android小项目之五 splash动画效果
查看>>
JavaScript 第十章总结:first class functions
查看>>
微信公众号发送客服消息【文本、图片】
查看>>
iText简介(转)
查看>>
BZOJ-1922 大陆争霸 多限制、分层图最短路 (堆+dijkstra)
查看>>
vim编辑器学习记录
查看>>
[Cocos2d-html5]关于压缩
查看>>
5-9 c语言之【初识win32编程】
查看>>