C++ iostream 输入输出流
作者:互联网
目录
4.
STL 输入输出流:整体框架
头文件 | 定义在头文件里的类 / 对象 | 补充说明 |
---|---|---|
<istream> |
istream 类、 iostream 类 |
istream 类是所有输入流的基类 |
<ostream> |
ostream 类 |
ostream 类是所有输出流的基类 |
<iostream> |
cin 对象、 cout 对象 |
cin 是 istream 类的对象;cout 是 ostream 类的对象 |
<fstream> |
ifsream 类、 ofstream 类、 fstream 类 |
|
<sstream> |
istringstream 类、 ostringstream 类、 stringstream 类 |
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 |
文件输入流 | 从文件中读取数据 | 是 istream 的子类在编译期间已经解析完毕 性能较好,取代了 scanf ( scanf 是有写入非法内存的风险) |
ofstream |
文件输出流 | 将数据写入文件中 | 是 ostream 的子类 |
*** 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");
标签:输出,iostream,ss,输入输出,C++,buffer,int,ostream,input 来源: https://www.cnblogs.com/bljw-02/p/16323674.html