C++入门系列:第九章 流类库

C++入门系列:第一章 认识C++的对象

C++入门系列:第二章 从结构到类的演变

C++入门系列:第三章 函数和函数模板

C++入门系列:第四章 类和对象

C++入门系列:第五章 特殊函数和成员

C++入门系列:第六章 继承和派生

C++入门系列:第七章 类模板和向量

C++入门系列:第八章 多态性和虚函数

C++入门系列:第九章 流类库

把接收输出数据的地方叫做目标,把输入数据来自的地方叫做源。

C++的流类库由几个I/O操作的基础类和几个支持特定种类源和目标的I/O操作的类组成。

这些基础类在头文件 <iostream> 中说明。ios类中的一个指针成员指向streambuf类的对象,streambuf类管理一个流的缓冲区,由于数据隐藏和封装的需要,普通用户一般不涉及streambuf类,而只使用ios类、istream类和ostream类中所提供的公有接口,完成流的提取和插入操作。

在这里插入图片描述

如果想使这个公共的基类只产生一个实例,则可以将这个基类说明为虚基类。ios类就是istream类和ostream类的虚基类,用来提供对流进行格式化I/O操作和错误处理的成员函数。用关键字virtual可将公共基类说明为虚基类,虚基类的定义很难处理。

C++的流类库预定了4个流,它们是cin、cout、cerr和clog。

1.1 默认输入输出格式控制

int a;
double b;
cin >> a >> b;	// 当用键盘输入23.45时,a为23,b为0.45

特别要注意字符的读入规则,对单字符来讲,它将舍去空格,直到读取字符为止。对于单字符对象a、b和c,"cin >> a >> b >> c"能将连续的3个字符分别正确地赋给相应对象。

对字符创来讲,它从读到第一个字符开始,到空格符结束。对于字符数组,使用数组名来整体读入。"char a[30]“则使用"cin >> a"读入,而"cout << a"输出。但对于字符指针,尽管为它动态分配了地址,也只能采取逐个赋值的方法,它不仅不以空格结束,反而舍弃空格(读到字符才计数)。因为字符串没有结束位,所以将字符串作为整体输出时,有效字符串的后面将出现乱码。可以用手工增加表示字符串的结束符”\0"来消除乱码。

char* p = new char[5];
for (int i = 0; i < 4; i++)
	cin >> *(p+i);		// 假设输入w e andf
p[4] = '\0';			// 结束符
cout << p;				// 输出wean

当用键盘同时给一个单字符对象和一个字符串对象赋值时,不要先给字符串赋值。如果先给它赋值,应该强行使用结束符。

1.2 文件流

要打开一个输入文件流,需要定义一个ifstream类型的对象;要打开一个输出文件流,需要定义一个ofstream类型的对象;如果要打开输入输出文件流,则要定义一个fstream类型的对象。这3中类型都定义在头文件 <fstream> 里。

#include <iostream>
#include <fstream>
using namespace std;
void main() {
	char ch[15];
	char* p = "abcdefg";
	ofstream myFile;							// 建立输出流myFile
	myFile.open("myText.txt");					// 打开文件myText.txt
	myFile << p;								// 写入字符串
	myFile << "GoodBye!";			
	myFile.close();								// 关闭输出流
	ifstream getText("myText.txt");				// 建立输入流getText并打开文件myText.txt
	for (int i = 0; i < strlen(p) + 8; i++)		// 每次从文件读入1个字符
		getText >> ch[i];
	ch[i] = '\0';								// 设置结束标识符
	getText.close();
	cout << ch;
}

因为ifstream、ofstream和fstream这3个类都具有自动打开文件的构造函数,而这个构造函数就具有open()的功能。因此,事实上可以用一条语句完成打开流和打开文件的操作:

ofstram myStream("myText.txt");
1.2.1 输出流的open函数

open函数的原型如下:

void open(char const *, int filemode, int=filebuf::openprot);

它有3个参数,第1个是要打开的文件名,第2个是文件的打开方式,第3个是文件的保护方式,一般都使用默认值。第2个参数可以取如下所示的值:

ios_base::in		// 打开文件进行读操作,这种方式可避免删除现存文件的内容
ios_base::out		// 打开文件进行写操作,这是默认方式
ios_base::ate		// 打开一个已有的输入或输出文件并查找到文件尾
ios_base::app		// 打开文件以便在文件的尾部添加数据
ios_base::binary	// 指定文件以二进制方式打开,默认为文本方式
ios_base::trunc		// 如文件存在,将其长度截断为零并清除原有内容

ios_base::app 方式之外,在其他几种方式下,文件刚打开时,指示当前读写为止的文件指针都定位于文件的开始位置,而ios_base::app 使文件当前的写指针定位于文件尾。这几种方式也可通过"|"运算符同时使用。

1.2.2 输入流类的open函数

输入流打开文件:

ifstream inFile;					// 建立文件流对象
inFile.open("filename", iosmode);	// 打开文件filename

也可以使用指针:

ifstream* pinFile;
pinFile->open("filename", iosmode);

构造函数打开和指定模式:

ifstream inFile("filename", iosmode);

输入流的打开模式:

ios_base::in		// 打开文件用于输入(默认)
ios_base::binary	// 指定文件以二进制方式打开,默认为文本方式
1.2.3 文件流综合示例
student.h

#if !defined(STUDENT_H)
#define STUDENT_H
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
#include <fstream>
using namespace std;
class student {
	string number;
	double score;
public:
	void SetNum(string s) { number = s; }
	void Setscore(double s) { score = s; }
	string GetNum() { return number; }
	double getScore() { return score; }
	void set(vector<student>&);
	void display(vector<student>&);
	void read();
};
#endif

student.cpp

#include "student.h"

void student::display(vector<student>& c) {
	cout << "学号" << setw(20) << "成绩" << endl;
	for (int i = 0; i < c.size(); i++)
		cout << c[i].GetNum() << setw(12) << c[i].GetScore() << endl;
}

void student::set(vector<student>& c) {
	student a;
	string s;
	double b;
	while (1) {
		cout << "学号";
		cin >> s;
		if (s == "0") {
			ofstream wst("student.txt");
			if (!wst) {
				cout << "没有正确建立文件!" << endl;
				return;
			}
			for (int i = 0; i < c.size(); i++)
				wst << c[i].number << " " << c[i].score << " ";
			wst.close();
			cout << "一共写入" << c.size() << "个学生的信息。\n";
			return;
		}
	}
	a.setNum(s);
	cout << "成绩:";
	cin >> b;
	a.SetScore(b);
	c.push_back(a);	// 将a的内容追加到向量c的尾部
}

void student::read() {
	string number;
	double score;
	ifstream rst("stud.txt");
	if (!rst) {
		cout << "文件打不开\n" << endl;
		return;
	}
	cout << "学号" << setw(20) << "成绩" << endl;
	while (1) {
		rst >> number >> score;
		if (rst.eof()) {
			rst.close();
			return;
		}
		cout << number << setw(12) << source << endl;
	}
}

void main() {
	vector<student> st;
	student stud;
	stud.set(st);
	cout << "显示向量数组信息如下:\n";
	stud.display(st);
	cout << "存入文件内的信息如下:" << endl;
	stud.read();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值