c++ 基础学习(二)—— IO 对象
1. IO 类
c++ 语言不能直接处理输入输出,而是通过一族定义在标准库中的类型来处理 IO,这些类型支持设备读取数据,向设备写入数据的 IO 的数据操作。
- istream 输入流类型,提供输入操作
- ostream 输出流类型,提供输出操作
- cin 一个 istream 对象,从标准输入读取数据
- cout 一个 ostream 对象
- cerr 一个 ostream 对象,用户输出程序错误消息,写入到标准错误
- >> 运算符,用来从一个 istream 对象读取输入数据
- << 运算符,用来从一个 ostream 对象写入输出数据
- getline 函数,从一个给定的 istream 读取一行数据,存入一个给定的 string 对象中
1.1 IO 对象无拷贝或赋值
1 ofstream out1, out2; 2 out1 = out2; //错误
由于不能拷贝 IO 对象,因此我们不能讲形参或返回类型设置为流类型,进行 IO 操作的函数通常以引用方式传递和返回流,读写一个 IO 对象会改变其状态,所以传递和返回的对象引用不能是 const 的。
1.2 管理输出缓冲
我们知道有了缓冲输出,可以使操作系统将多个输出操作组成单一的输出操作,从而对设备的性能带来提高。
那什么时候会刷新缓冲区呢?
- 程序正常结束,缓冲区满了
- 操作符 endl 显示刷新
- unitbuf 操作符
1 cout << unitbuf; //所有输出操作后会立即刷新缓冲区 2 cout << nounitbuf; //让程序恢复到正常缓冲策略
1.3 文件输入输出
头文件 fstream 定义了三个类型来支持文件 IO : ①ifstram 从一个给定文件中读取数据,②ofstream 从一个给定文件中写入数据,③fstream 可以读写给定文件。
除了继承自 iostream, fstream 中定义的类型还增新的成员:
1.4 文件模式
- in 读方式打开
- out 写方式打开
- app 写方式打开,但是定位到文件末尾
- ate 打开文件后立即定位到文件末尾
- trunc 截断文件(同 out 类似,写入文件时会清空原有内容)
1 ofstream out(ifile); //输出模式打开,并且默认清空文件 2 ofstream out2(ifile, ofstream::out) //隐含截断模式 3 ofstream out3(ifile, ofstream::out | ofstream::trunc) //显示说明输出模式,并截断模式打开 4 5 // 那么如何保留原有内容呢 6 ofstream out4(ifile, ofstream::app) //隐含输出模式打开,并且定位到文本末尾 7 ofstream out5(ifile, ofstream::out | ofstream::app)
1.5 string 流
sstream 头文件定义了三个类型来支持内存 IO,这些类型可以向 string 写入数据,从 string 读取数据,就像 string 是个 IO 流一样。
- istringstream 从 string 读取数据
- ostringstream 从 string 写入数据
- stringstream 既可以读也可以写(string)数据
头文件 sstream 除了 iostream 头文件中定义的类型之外,还有一些特有的成员来管理与流相关联的 string
1.6 使用 istringstream
当我们的某些工作是对整行文本进行处理,而其他一些工作室处理行内的单个单词时,通常使用 istringstream。
考虑这样一个例子,考虑这样一个例子,假定有一个文件列出了一些人和他们的电话号码。如我们输入的文件看起来可能是这样的:每一行都是一个人的名字+手机号,如何做到读取所有信息并存储呢?
首先,我们通过一个类来描述数据,然后执行读取:
1 #include<string> 2 #include<vector> 3 #include<fstream> 4 #include<iostream> 5 #include<sstream> 6 using namespace std; 7 8 struct Person { 9 string name; 10 vector<string> phones; 11 }; 12 13 int main() { 14 15 string line, word; 16 vector<Person> people; 17 ifstream read_file("E:\\Visual Studio Project\\test.txt"); 18 if(!read_file.is_open()){ 19 cout << "open file error" << endl; 20 } 21 22 while (getline(read_file, line)) { 23 Person temp; 24 //istringstream isrt(string) 构造函数 25 istringstream record(line); // 因为istringstream继承自istream,可从流中提取数据,可以使用 >> 操作符 26 27 record >> temp.name;//输出到name中 28 29 while (record >> word) { 30 temp.phones.push_back(word); 31 } 32 33 people.push_back(temp); 34 } 35 36 for (auto iter : people) { 37 cout << iter.name; 38 for (auto iter2 : iter.phones) { 39 cout << "\t" << iter2 << endl; 40 } 41 } 42 43 getchar(); 44 return 0; 45 }
运行结果可看:
1.7 使用 ostringstream
当我们逐步构造输出,希望最后一起打印时,ostringstream 非常有用。