Streams⚓︎
约 763 个字 91 行代码 预计阅读时间 5 分钟
流(stream) 是一种为设备提供的公共逻辑接口,具备顺序 (sequential) 的特征,能够生产或消耗值。
它的优缺点是:
- 优点:提供了更好的类型安全,具备可扩展性,体现更多面向对象的特征
- 缺点:代码更加冗长,执行速度更慢
流的名称:
输入 | 输出 | 头文件 | |
---|---|---|---|
泛型 | istream | ostream | <iostream> |
文件 | ifstream | ofstream | <fstream> |
字符串 | istringstream | ostringstream | <sstream> |
流运算:
- 提取符(extractor):
- 从流中读取值
- 重载运算符
>>
- 插入符(insertor):
- 将值插入到流中
- 重载运算符
<<
- 操纵符(manipulator):改变流的状态
- 其他 ...
流的种类:
- 文本流
- 用于处理 ASCII 文本
- 以行的形式组织
- 执行一些字符转换,比如将新的行转换为真正的 OS 文件
- 包括:文件、字符缓冲区等
- 二进制流
- 用于处理二进制数据
- 没有转换
预定义的流:
cin
:标准输入cout
:标准输出cerr
:未缓存的错误(调试)输出clog
:缓存的错误(调试)输出
预定义的提取符 istream >> lvalue
会忽视前导空白字符,它的定义如下:
其他的输入运算符:
-
int get()
:返回流里面的下一个字符,如果流里没有字符的话则返回EOF
-
istream& get(char &ch)
:讲下一个字符放到参数里,功能和上一个输入运算符类似 istream& getline(istream& is, string& str, char delim = '\n');
:自由函数?ignore(int limit = 1, int delim = EOF)
:跳过limit
个字符以及分隔符-
int gcount()
:返回刚刚读取的字符数 -
void putback(char)
:将单个字符推回到流里面 char peek()
:检查下一个字符,但不读取它
预定义的插入符 ostream << expression
,它的定义如下:
其他的输出运算符:
-
put(char)
:打印单个字符 -
flush()
:强制输出流的内容
使用操纵符进行格式化,修改流的状态
- 导入头文件:
#include<iomanip>
- 各种操纵符:
操纵符 | 效果 | 类型 |
---|---|---|
dec , hex , oct |
设置数值转换 | I, O |
endl |
插入新行并清除流的内容 | O |
flush |
清除流的内容 | O |
setw(int) |
设置字段宽度 | I, O |
setfill(char) |
改变填充字符 | I, O |
setbase(int) |
设置数字的基底 | O |
ws |
跳过空白字符 | I |
setprecision(int) |
设置浮点数精度 | O |
例子
#include <iostream>
#include <iomanip>
int main() {
cout << setprecision(2) << 1000.243 <<endl;
cout << setw(20) << "OK!";
return 0;
}
运行结果:
我们可以自定义操纵符:
// skeleton for an output stream manipulator
ostream& manip(ostream& out) {
...
return out;
}
ostream& tab ( ostream& out ) {
return out << '\t';
}
cout << "Hello" << tab << "World!" << endl;
流标志控制格式:
标志 | 目的(何时设置) |
---|---|
ios::skipws |
跳过前导空白字符 |
ios::left , ios::right |
对齐 |
ios::internal |
在符号和值之间填充 |
ios::dec , ios::hex , ios::oct |
数字格式 |
ios::showbase |
显示数字基底 |
ios::showpoint |
始终显示小数点 |
ios::uppercase |
让基底以大写形式呈现 |
ios::showpos |
显示正数的 + |
设置标志:
- 使用操纵符:
setiosflags(flags)
,resetiosflags(flags)
- 使用
stream
成员变量:setf(flags)
,unsetf(flags)
例子
#include <iostream>
#include <iomanip>
int main() {
cout setf(ios::showpos | ios::scientific);
cout << 123 << " " << 456.78 << endl;
cout << resetiosflags(ios::showpos) << 123;
return 0;
}
运行结果:
流的错误状态:

- 每次操作后都会设置错误状态
clear()
用于重置错误状态为good()
- 状态检查:
good()
:当状态有效时返回true
eof()
:当遇到 EOF 时返回true
fail()
:当出现轻微故障或不良状态时返回true
bad()
:当状态不良时返回true
例子
int n;
cout << "Enter a value for n, then [Enter]" << flush;
while (cin.good()) {
cin >> n;
if (cin) { // input was ok
cin.ignore(INT_MAX, '\n'); // flush newline
break;
}
if (cin.fail()) {
cin.clear(); // clear the error state
cin.ignore(INT_MAX, '\n'); // skip garbage
cout << "No good, try again!" << flush;
}
}
文件流
ifstream
和ofstream
将文件和流连接起来- 需要导入头文件:
#include <fstream>
- 用模式指明如何创建文件:
模式 | 目的 |
---|---|
ios:app |
附加 |
ios:ate |
末尾位置 |
ios:binary |
处理二进制 I/O |
ios:in |
为输入打开文件 |
ios:out |
为输出打开文件 |
例子
#include <iostream>
#include <fstream>
int main(int argc, char *argv[]) {
if (argc != 3) {
cerr << "Usage: copy file1 file2" << endl;
exit(1);
}
ifstream in(argv[1]);
if (!in) {
exit(2);
cerr << "Unable to open file " << argv[1];
}
ofstream out(argv[2]);
if (!out) {
exit(2);
cerr << "Unable to open file " << argv[2];
}
char c;
while (in >> c) {
out << c;
}
}
相关的流操作:
-
open(const char *, int flags, int)
:打开指定文件 -
close()
关闭流
I/O 流缓冲区:
- 每个 I/O 都有一个流缓冲区
- 类
streambuf
定义了这个缓冲区的抽象 - 成员函数
rdbuf()
返回指向流缓冲区的指针 <<
被重载,用于直接连接缓冲区
例子
评论区
如果大家有什么问题或想法,欢迎在下方留言~