C++ 输入输出流:简单地介绍了【输入输出流】、【文件输入输出流】和【字符串输入输出流】。
目录
- STL 输入输出流:整体框架
- A) 输入、输出流
- 1. 简介
- 2. 格式化输出
- 3. 流操纵算子
- 4. cout对象的唯一性
- B) 文件输入、输出流
- 1. 基本使用方法
- 2. 读入常用操作
- C) 字符串输入、输出流
- 1. 简介
- 2. 对象内的 buffer
- 3. 实现类型转换
STL 输入输出流:整体框架
头文件 | 定义在头文件里的类 / 对象 | 补充说明 |
|
|
|
|
|
|
|
|
|
|
| |
|
|
回到顶部
A) 输入、输出流
*** istream
和 ostream
类似,以下以 ostream
展开说明。
1. 简介
ostream
= output stream
- 是所有输出流的基类
- 类内重载了不同基础数据类型的输出流运算符,如:
int
、char
、bool
... - 优势:统一了输出接口,避免输出混乱
- STL 中定义了一个
ostream
类的对象:cout
,将数据送到标准输出流
以下是自定义实现ostream
的方法:
class ostream {
public:
ostream& operator<< (int num) {
printf("%d", num);
return *this;
}
ostream& operator<< (const char* str) {
printf("%s", str);
return *this;
}
...... // 重载需要输出的类型
} cout; // 定义 ostream 类的对象
int main() {
cout << 21 << "happy" ; // 根据输出数据类型,调用不同的输出函数
return 0;
}
以下是在自定义类中重载流运算符的方法:
class MyClass {
public:
friend ostream& operator<< (ostream&, MyClass&);
......
}
ostream& operator<< (ostream& output, MyClass& x) {
output << ... ;
return outpur;
}
注意:第二个参数可以是不同形式,不一定是引用,如:T
、T&
、const T
、const T&
回到顶部
2. 格式化输出
- 常用的格式化输出方式有:
#include <iomanip>
cout << fixed << 3 << " " << 3.14 << " " << 3.14159265;
/* 将小数的小数点固定为 6 位
输出结果:3 3.140000 3.141593 */
cout << setprecision(3) << 3.1415926 << 0.1054;
/* 设置有效数字
输出结果:3.14 0.105 */
cout << fixed << setprecision(2) << 3.1415;
/* fixed 和 setprecision 合用,可以设置小数点数位
输出结果:3.14 */
cout << setw(5) << 921;
/* 设置输出的宽度,一次只对一个输出有效
默认向右对齐 */
for(int i = 8; i <= 12; ++i) {
cout << setw(5) << setfill('*') << i;
}
/* 设置输出的宽度 + 空白处填满指定字符
输出结果:****8****9***10***11***12 */
cout << scientific << 2018.0 << " " << 0.0001;
/* 以科学计数形式输出
输出结果:2.018000e+03 1.000000e-04 */
- 以上的
fixed
、setprecision()
等,包括实现换行的endl
,都是流操纵算子
回到顶部
3. 流操纵算子
- 借助辅助类,设置成员变量的类
- 一些实现方式有在标准中定义,一些没有,不同编译器的实现不同
setprecision
实现的示例:
class setprecision {
private:
int precision;
public:
setprecision(int p): precision(p) {}
friend class ostream;
}
class ostream {
private:
int precision;
public:
ostream& operator<< (const setprecision &m) {
precision = m.precision;
return *this;
}
} cout;
cout << setprecision(2);
// setprecision(2) 会构造一个 setprecision 类的对象,作为参数传入输出流的函数
endl
实现的示例:
class ostream {
......
ostream& endl(ostream& os) {
os.put('\n'); // 输出换行符
os.flush(); // 清空缓冲区
return os;
}
ostream& operator<< (ostream& (*fn)(ostream&)) {
return (*fn)(*this);
}
}
// 换行方法1:调用输出流+流操纵算子
cout << endl;
// 换行方法2:直接使用endl函数
endl(cout);
清空缓冲区的好处:减少外部读写次数、保证内容正确读写到文件
回到顶部
4. cout对象的唯一性
- 定义重载流运算符 / 使用
cout
的方式:
- 所有重载流运算符都会返回引用
ostream&
ostream
类的拷贝构造函数会手动进行删除ostream(const ostream& x) = delete; ostream(ostream&& x);
- 原因:
- 减少复制开销
- 只移动不复制,只使用一个全局对象
cout
进行输出- 多个对象无法同步输出状态
回到顶部
B) 文件输入、输出流
类 | 名 | 功能 | 补充说明 |
| 文件输入流 | 从文件中读取数据 | 是 在编译期间已经解析完毕 性能较好,取代了 ( |
| 文件输出流 | 将数据写入文件中 | 是 |
*** ifstream
和 ofstream
类似,以下以 ifstream
进行说明:
回到顶部
1. 基本使用方法
#include <fstream>
#include <iostream>
using namespace std;
int main() {
// 打开普通文本文件
ifsream input("filename.txt");
// 以二进制形式打开文件
ifstream input("filename.bin", ifstream::binary);
// 确保文件正确打开才进行操作
if(input) {
...
}
// 操作完毕,关闭文件
input.close();
return 0;
}
回到顶部
2. 读入常用操作
- 判断是否到了文末
while(input) {
...
}
- 去除前导空格
input >> ws;
- 检查下一个字符,如果到了文末就停止
int c = input.peek();
if(c == EOF) break;
- 读取
int n;
input >> n;
string str;
input >> str;
getline(cin, str);
...
char sentence[1000];
input.getline(sentence, 1000);
回到顶部
C) 字符串输入、输出流
1. 简介
stringstream
- 是
iostream
的子类 - 在对象内维护一个 buffer,可以实现输入和输出
- 流输出函数:将数据写入 buffer
- 流输入函数:从 buffer 读入数据
- 基本使用方法
#include <sstream>
using namespace std;
int main() {
stringstream ss;
ss << "10"; // 将数据写进 ss 的 buffer
ss << "0 200"; // 会自动连接字符串
int a, b;
ss >> a >> b; // 从 buffer 读取数据,转换成 int
return 0;
}
回到顶部
2. 对象内的 buffer
- 暂存数据的空间,包含已读取和未读取的内容
- 可以用
ss.str()
来返回 buffer 内的内容(返回类型:string)
stringstream ss;
ss << "10"; // buffer内有【10】
ss << "0 200"; // buffer内有【100 200】
int a, b;
ss >> a; // a = 100,buffer内有【100 200】
ss >> b; // b = 200,buffer内有【100 200】
ss.str(""); // 清空 buffer
- 从以上代码可见,buffer 内的内容不会因为被读取而减少
- 有两个指针在维护着:head 和 tail
- head:指向最后一个内容(下一个位置就是写入新内容的位置)
- tail:指向待读取的第一个元素
- 所有 head 在 tail 的后面,head 和 tail 之间是未读取的元素
回到顶部
3. 实现类型转换
template<class outtype, class intype>
outtype convert(intype val) {
static stringstream ss; // 避免重复初始化
ss.str(""); // 清空 buffer
ss.clear(); // 清空状态位
ss << val;
outtype result; // 定义要转换的类型的变量
ss >> result;
return result; // 返回转换后的内容
}
// 使用
string str = convert<string>(921);
int num = convert<int>("122");
回到顶部