IO相关1(io类/流状态)
IO类:
iostream 定义了用于读写流的基本类型,fstream 定义了读写命名文件的类型,sstream 定义了读写内存 string 对象的类型。
IO 库类型和头文件:
头文件 类型
iostream istream,wistream 从流读取数据
ostream,wostream 向流写入数据
iostream,wiostream 读写流
fstream ifstream,wifstream 从文件读取数据
ofstream,wofstream 向文件写入数据
fstream,wfstream 读写文件
sstream istringstream,wistringstream 从 string 读取数据
ostringstream,wostringstream 向 string 写入数据
stringstream,wstringstream 读写 string
其中前面加了 w 的是宽字符版本的
为了支持使用宽字符的语言,标准库定义了一组类型和对象来操纵 wchar_t 类型的数据。宽字符版本的类型和函数的名字以一个 w 开始。例如:wcin,wcout,wcerr 是分别对应 cin,cout,cerr 的宽字符版对象。宽字符的类型和对象与其对应的普通 char 版本的类型定义在同一个头文件中。例如:头文件 fstream 定义了 ifstream 和 wifstream 类型。
IO类型间的关系:
标准库通过继承机制使我们能忽略不同类型的流之间的差异。利用模板,我们可以使用具有继承关系的类,而不必了解继承机制如何工作的细节。我们通常可以将一个派生类对象当作其基类对象类使用。
类型 ifstream 和 istringstream 都继承自 istream。因此,我们可以像使用 istream 对象一样来使用 ifstream 和 istringstream 对象。也就是说我们是如何使用 cin 的,就可以同样地使用这些类型的对象。例如:可以对一个 ifstream 或者 istringstream 对象调用 getline,也可以使用 >> 从一个 ifstream 或 istringstream 对象中读取数据。类似的,类型 ofstream 和 ostringstream 都继承自 ostream。因此,我们可以如何使用 cout 的,就可以同样地使用这些类型的对象。
IO对象无拷贝或赋值:
ofstream out1, out2;
out1 = out2;//错误,不能对流对象赋值
ofstream frint(ofstream);//错误,不能初始化ofstream参数
out2 = print(out2);//错误,不能拷贝流对象
由于不能拷贝IO对象,因此我们也不能将形参或返回类型设置为流类型。进行IO操作的函数通常以引用方式传递和返回流。读写一个流会改变其状态,因此传递和返回的引用不能是 const 的。
IO的条件状态:
strm::iostate strm是指一种IO类型,iostate是一种机器相关的类型,提供表达条件状态的完整功能。
strm::badbit 标志流已崩溃,致命的输入/输出错误,无法挽回
strm::failbit 标志IO操作失败了,非致命的输入/输出错误,可挽回
strm::eofbit 标志达到文件结尾
strm::goodbit 流未出现错误状态,此值保证为0
s.eof() 若流s的eofbit置位,则返回true
s.fail() 若流s的failbit或badbit置位,则返回true
s.bad() 若流s的badbit置位,则返回true
s.good() 若流s处于有效状态,则返回true
s.clear() 将流的所有条件复位,状态设置为有效,返回void
s.clear(flags) 根据flags标志位,将s中对应条件状态复位,flags类型为strm::iostate。返回void
s.setstate(flags) 根据flags标志位,将s中对应条件状态置位,flags类型为strm::iostate。返回void
s.rdstate() 返回流的当前条件状态,返回类型为strm::iostate
注意:
badbit是系统级错误,如不可恢复的读写错误;一般badbit置位了流就无法继续使用。
failbit是可恢复错误,例如希望读取数值,却读取了一个字符,这种错误可以修正,流还可以继续使用。
如果达到文件结束位置,eofbit和failbit都会被置位。
googbit表示流未发生错误,值为0。
只要badbit、failbit、eofbit任意一个被置位,检查流的状态的条件会失败。
管理条件状态:
流对象的 rdstate 成员返回一个 iostate 值,对应流的当前状态。setstate 操作将给定条件位置位,表示发生了对应错误。cleat 成员是一个重载成员:他有一个不接受参数版本,而另一个版本接受一个 iostate 类型的参数。clear 不接受参数的版本清除所有错误标志位。执行 clear() 后调用 good 会返回 true:
auto old_state = cin.rdstate();//记住cin当前的状态
cin.clear();//使cin有效
process_input(cin);//使用cin
cin.setstate(old_state);//将cin置为原有状态
带参数的 clear 版本接受一个 iostate 值,表示流的新状态。为了复位单一的条件状态,我们首先使用 rdstate 读出当前条件状态,然后用位操作将所需复位来生成新的状态。如:cin.clear(cin.rdstate()& ~cin.failbit & ~cin.badbit);//只复位failbit和badbit,但保持eofbit不变
检查输入流的当前状态:
#include <iostream>
using namespace std; int main(void){
int a;
cin >> a;
cout << cin.rdstate() << endl;
if(cin.rdstate() == ios::goodbit) cout << "the input is true" << endl; std::wcout.imbue(locale(locale(), "", LC_CTYPE));
if(cin.rdstate() == ios::failbit) wcout << L"输入数据类型错误,非致命错误,可清除输入缓冲区挽回!" << endl; return ;
}
通过 clear 使 cin 有效:
#include <iostream>
using namespace std; int main(void){
int a;
cin >> a;
cout << cin.rdstate() << endl;
cin.clear(ios::goodbit);//使cin有效
cout << cin.rdstate() << endl;
return ;
}
通常当我们发现输入有错又需要改正的时候,使用 clear() 更改标记为正确后,同时也需要使用 get() 成员函数清除输入缓冲区,以达到重复输入的目的:
#include <iostream>
using namespace std; int main(void){
int a;
while(){
cin >> a;
if(cin.fail()){
cout << "error! please input agin!" << endl;
cin.clear();
cin.get();
}else{
cout << a;
break;
}
}
return ;
}
管理输出缓冲:
每个输出流都管理一个缓冲区,用来保存程序读写的数据:
os << "please enter a value: ";
文本串可能立即打印出来,也有可能被操作系统保存在缓冲区,随后再打印。
会导致刷新缓冲区的原因:
- 程序正常结束,作为 main 函数的 return 的一部分,缓冲刷新被执行。
- 缓冲区满,需要刷新缓冲区,而后新的数据才能写入。
- 使用操纵符:endl 来显示刷新缓冲区。
- 每个输出操作后,可以用操作符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,cerr 是设置 unitbuf 的,因此写到 cerr 中的数据都是立即刷新的。
- 一个输出流被关联到另一个流,此时,当读写被关联的流时,关联到流的缓冲区会被刷新。默认cin 和 cerr 都关联到 cout,因此读 cin 或写 cerr 都会导致 cout 的缓冲区被刷新。
endl 换行并刷新缓冲区;
ends 插入一个空字符并刷新缓冲区;
flush 仅刷新缓冲区;
unibuf 操纵符:
cout << unitbuf;//所有输出操作后都会立即刷新缓冲区
//任何输出都立即刷新,无缓冲
cout << nounitbuf;//回到正常的缓冲方式
注意:如果程序异常终止,输出缓冲区是不会被刷新的。当一个程序崩溃后,它所输出的数据很可能停留在输出缓冲区中等待打印。
关联输入和输出流:
当一个输入流关联到一个输出流时,任何试图从输入流读取数据的操纵都会先刷新关联的输出流。标准库将 cout 和 cin 关联到一起,因此:
cin >> val;
导致 cout 的缓冲区被刷新。
tie:
tie 有两个重载版本:一个版本不带参数,返回指向输出流的指针。如果本对象关联到一个输出流,则返回的就是指向这个流的指针,如果对象未关联到流,则返回空指针。tie 的第二个版本接受一个指向 ostream 的指针,将自己关联到 ostream。即,x.tie(&o) 将流 x 关联到输出流 o。
我们既可以将一个 istream 对象关联到另一个 ostream,也可以将一个 ostream 关联到另一个 ostream:
cin.tie(&cerr);//直接将cin由和cout关联改成和cerr关联
cin.tie(&cout);//将输入流cin关联到输出流cout
ostream *old_tie = cin.tie(nullptr);//cin不再与其他流关联
cin.tie(&cerr);//将cin关联到cerr,读取cin会刷新cerr而非cout
cin.tie(old_tie);//重建cin和cout之间的关联
注意:每个流同时最多关联到一个流,但多个流可以同时关联到一个 ostream。
IO相关1(io类/流状态)的更多相关文章
- 关于golang中IO相关的Buffer类浅析
io重要的接口 在介绍buffer之前,先来认识两个重要的接口,如下边所示: type Reader interface { Read(p []byte) (n int, err error) } t ...
- 从零开始学C++之IO流类库(二):文件流(fstream, ifstream, ofstream)的打开关闭、流状态
一.文件流 ofstream,由ostream派生而来,用于写文件 ifstream,由istream派生而来, 用于读文件 fstream,由iostream派生而来,用于读写文件 二.打开文件 说 ...
- 文件IO 相关的包:java.io文件——API
文件IO 相关的包:java.io文件——API 1.Java.io.File类的使用(1)两种路径绝对路径:相对于当前路径:当前为 “工程名”(2)File类创建,对象为一个文件/目录,可能存在或不 ...
- Java之IO(十四)IO包中其它类
转载请注明出处:http://www.cnblogs.com/lighten/p/7267553.html 1.前言 此章介绍IO包中剩余未介绍的几个流和工具类,包括LineNumberReader. ...
- spring源码分析-core.io包里面的类
前些日子看<深入理解javaweb开发>时,看到第一章java的io流,发觉自己对io流真的不是很熟悉.然后看了下JDK1.7中io包的一点点代码,又看了org.springframewo ...
- Properties -IO相关的双列集合类
IO相关的集合类 java.util.Properties集合 extends hashtable(淘汰) Properties类表示了一个持久的属性集.Properties可保存流中或从流中加载 P ...
- java.io 包下的类有哪些 + 面试题
java.io 包下的类有哪些 + 面试题 IO 介绍 IO 是 Input/Output 的缩写,它是基于流模型实现的,比如操作文件时使用输入流和输出流来写入和读取文件等. IO 分类 传统的 IO ...
- Java IO相关使用
date: 2020-06-14 14:42:22 updated: 2020-08-21 17:35:45 Java IO相关使用 1. 文件 创建 File 对象的三种方式 一个路径名:File( ...
- JAVA基础知识之IO——Java IO体系及常用类
Java IO体系 个人觉得可以用"字节流操作类和字符流操作类组成了Java IO体系"来高度概括Java IO体系. 借用几张网络图片来说明(图片来自 http://blog.c ...
随机推荐
- web项目目录结构
eclipse web项目目录结构 按照 Java EE 规范的规定,一个典型的 Web 应用程序有四个部分: 1. 公开目录 ; 2. WEB-INF/web.xml 文件,发布描述符(必选) ; ...
- Roslyn研究随笔
Roslyn概述: http://blogs.ejb.cc/archives/7604/dotnet-compile-platform-roslyn-overview 使用Microsoft Rosl ...
- mybatis学习 十二 多表查询
Mybatis 实现多表查询方式: (1)业务装配.对两个表编写单表查询语句,在业务(Service)把查询的两个结果进行关联. (2)使用Auto Mapping特性,在实现两表联合查询时通过别名完 ...
- CentOS下利用mysqlbinlog恢复MySQL数据库
如果不小心对数据库进行误操作,而又没有及时备份怎么办?这恐怕是广大的coder经常遇到的一类问题.我今天就因为不小心删除了某个数据库,但最后的备份是1个礼拜前的,唯一能解决的办法就是通过mysqlbi ...
- 2019.01.21 bzoj2441: [中山市选2011]小W的问题(树状数组+权值线段树)
传送门 数据结构优化计数菜题. 题意简述:给nnn个点问有多少个www型. www型的定义: 由5个不同的点组成,满足x1<x2<x3<x4<x5,x3>x1>x2 ...
- 2019.01.14 codeforces685B. Kay and Snowflake(树形dp)
传送门 题意简述:给出一棵树,求每个子树的重心. 首先通过画图可以观察出一个性质,我们从叶子结点向根节点递推重心的话重心的位置是不会下降的. 然后由于一个点的重心要么是自己,要么在重儿子子树内,因此如 ...
- lepus部署
lepus部署 lepus安装 cd /usr/local/src/lepus_v3.7/ cd python/ sh install.sh mysql配置 mysql -uroot -p'zaBBi ...
- 学以致用一 安装centos7.2虚拟机
5说来惭愧,也是很久没来博客园了.距离上次写的已经快一年,只能说时间过的真的很快. 而如果这一年一直在坚持认真学习的话,收获肯定很多.然而我确又浪费了很多光阴,不得不恨这人生苦短. 在这一年里,小孩还 ...
- Shell编程-11-子Shell和Shell嵌套
目录 什么是子Shell 子Shell产生的途径 Shell脚本调用模式 什么是子Shell 子Shell的概念其实是贯穿整个Shell的,如果想要更好的理解和写Shell脚本则必须要了解子S ...
- python标准库及其它应用
一: sys模块的介绍: 程序如下: #coding:utf-8import sysprint sys.argv[0]print sys.argv[1]print sys.argv[2] 打开cmd窗 ...