cout
对象的唯一性头文件 | 定义在头文件里的类 / 对象 | 补充说明 |
---|---|---|
<istream> |
istream 类、 iostream 类 |
istream 类是所有输入流的基类 |
<ostream> |
ostream 类 |
ostream 类是所有输出流的基类 |
<iostream> |
cin 对象、 cout 对象 |
cin 是 istream 类的对象;cout 是 ostream 类的对象 |
<fstream> |
ifsream 类、 ofstream 类、 fstream 类 |
|
<sstream> |
istringstream 类、 ostringstream 类、 stringstream 类 |
回到顶部
*** istream
和 ostream
类似,以下以 ostream
展开说明。
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&
回到顶部
常用的格式化输出方式有:
#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
,都是流操纵算子
回到顶部
借助辅助类,设置成员变量的类
一些实现方式有在标准中定义,一些没有,不同编译器的实现不同
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);
清空缓冲区的好处:减少外部读写次数、保证内容正确读写到文件
回到顶部
cout
对象的唯一性定义重载流运算符 / 使用 cout
的方式:
所有重载流运算符都会返回引用
ostream&
ostream
类的拷贝构造函数会手动进行删除ostream(const ostream& x) = delete; ostream(ostream&& x);
原因:
- 减少复制开销
- 只移动不复制,只使用一个全局对象
cout
进行输出- 多个对象无法同步输出状态
回到顶部
类 | 名 | 功能 | 补充说明 |
---|---|---|---|
ifstream |
文件输入流 | 从文件中读取数据 | 是 istream 的子类在编译期间已经解析完毕 性能较好,取代了 scanf ( scanf 是有写入非法内存的风险) |
ofstream |
文件输出流 | 将数据写入文件中 | 是 ostream 的子类 |
*** ifstream
和 ofstream
类似,以下以 ifstream
进行说明:
回到顶部
#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; }
回到顶部
判断是否到了文末
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);
回到顶部
stringstream
iostream
的子类基本使用方法
#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; }
回到顶部
暂存数据的空间,包含已读取和未读取的内容
可以用 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 内的内容不会因为被读取而减少
回到顶部
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");
回到顶部