IO类
IO对象无拷贝和赋值
IO对象的状态
接下来的表格中假设存在流s,可以想象成cin
IO库条件状态 | 解释 |
---|---|
strm::iostate | 是一种IO状态,提供表达状态的完整功能。 |
strm::badbit | 系统级错误导致流崩溃,崩溃返回true |
strm::failbit | 用来指出IO操作失败,失败返回true |
strm::goodbit | 用来表示流正常,正常返回true |
strm::eofbit | 用来提示流是否到达结束,到达文件结束返回true |
s.rdstate() | 获取当前流状态,包含上述四个状态。 |
s.clear() | 使流恢复到正常状态,四个状态分别为0 0 1 0 |
s.setstate(flag) | 其中flag为std::ios_base::iostate,用来设置流的状态 |
流的状态failbit为true的原因为badbit为true或者eofbit为true,badbit为true的情况下failbit一定为true,但是failbit为true的情况下badbit不一定为true,eofbit也是同样的。
通常情况下我们使用
while(cin >> val) ....
的时候,while检测cin的状态,如果为有效状态返回true否则返回false。
输出缓冲
每个输出流管理一个缓冲区,为了防止一个一个的读写效率比较底下,引入了缓冲区,首先程序会把数据保存到缓冲区内,然后通过缓冲区来挂起打印,这样的话就会把许多单一的操作变成一个单一的缓冲区打印操作,大大的提升了输出的效率。输出结束后缓冲区被清空,也就是缓冲区被刷新。
导致缓冲区被刷新的原因有很多,下面进行列举:
- 程序结束,main函数接收到return的操作。
- 缓冲区已经满了,需要进行清空刷新,然后新的数据才能够写入。
- 通过endl,ends,flush进行显示刷新。
- 同unitbuf对每次输出进行强制刷新
我们尝试分析第三种和第四种方法对缓冲区清空的影响。
首先通过endl, ends, flush的影响。
endl | 输出换行符号并清空缓冲区 |
---|---|
ends | 输出一个空格然后再清空缓冲区,但是我本地并没有输出空格(这里希望能在评论解释一下)。 |
flush | 什么也不干然后刷新缓冲区 |
三种方法对应的使用方法为
cout << endl;
cout << ends;
cout << flush;
第四种方法为改变流的内部状态,每次执行流的之后都要进行一个flush操作
cout << unitbuf;
cin流绑定了cout流,c++规定任何与输入流绑定的输出流,在输入流进行输入的时候将会去刷新输出流,所以在cin每次输入的时候都会去刷新cout缓冲区。
tie函数由两个重载版本,一个为不带参数的用来返回与输入流绑定的输出流指针,如果为空则返回nullptr,第二个为接受一个输出流指针,将自己与对应的输出流进行绑定。
文件输入输出
c++中拥有文件流fstream和ifstream以及ofstream分别问文件流,读文件流,写文件流。文件流同样有相应的流状态,可以通过 ‘>>’, '<<'运算符进行操作,可以通过open来绑定相应的文件。
下面进行演示。
#include <iostream>
#include <fstream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main() {
int val;
std::ifstream data_in;
std::ofstream data_out;
string path = "...";
data_in.open(path + "data.in");
data_out.open(path + "data.out");
while(data_in >> val) {
data_out << val << endl;
}
data_in.close();
data_out.close();
return 0;
}
文件状态
状态 | 作用 |
---|---|
in | 仅可以用来设置输入流状态,以读的方式打开 |
out | 仅可以用来设置输出流状态,以写的方式打开 |
app | 每次写操作均指向文件末尾,以追加的方式进行写入 |
ate | 打开文件后立即定位到文件末尾 |
trunc | 截断文件 |
binary | 以二进制的方式操作文件 |
iofstream默认为in状态,ofstream默认为out状态,以out状态打开的文件会清空原文件的内容,但是以app状态打开则会追加到文件最后。
下面进行演示:
#include <iostream>
#include <fstream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::ends;
using std::flush;
using std::string;
int main() {
string val;
std::ifstream data_in;
std::ofstream data_out;
string path = "...";
data_in.open(path + "data.in", std::ifstream::binary);
data_out.open(path + "data.out", std::ofstream::app);
while(data_in >> val) {
data_out << val << endl;
}
return 0;
}
如果有多个状态需要设置那么使用或(|)运算符即可,因为状态之间可以叠加,有点状态压缩的感觉。
string流
同样有三个形式stringstream可以从string中读数据也可以向string写数据,istringstream则只可以从string中读数据,ostringstream只可以向string中写数据。
string流中有str()进行转化为可输出的字符串。
我们现在考虑把一个含有空格的字符串中所有的单词给分离出来,那么我们可以使用istringstream来实现,ostringstream则进行格式化输出。下面进行代码演示:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::ends;
using std::flush;
using std::string;
using std::istringstream;
using std::ostringstream;
int main() {
string val, text;
getline(cin, val);
istringstream strstream(val);
ostringstream format;
format.clear();
while(strstream >> text) {
format << text << " ";
}
cout << format.str() << endl;
return 0;
}