C++ Primer阅读笔记[Part 4]

IO流


C++中的IO类主要有3种:

  • iostream头文件 主要控制读写流
  1. istream 读流类型

  2. ostream 写流类型

  3. iostream 读写流类型

  • fstream头文件 主要用于文件读写
  1. ifstream 读文件类型
  2. ofstream 写文件类型
  3. fstream 读写文件类型
  • sstream头文件 主要用于读写内存中的string对象
  1. istringstream 读string类型
  2. ostringstream 写string类型
  3. stringstream 读写string类型

其继承关系如下:

注意IO对象是无法被拷贝的,所以IO操作的函数通常以引用方式传递IO对象,由于读写IO对象会导致变化所以不能是底层const。

文件IO流


文件IO是由fstream头文件控制的。首先来看一下fstream含有的方法,其中包含了ifstream, ofstream与fstream三种类型

其步骤一般都是:

  1. 打开文件(直接通过构造函数或open方法)
  2. 读写文件
  3. 关闭文件(通过close方法)

来看一个实例:

void FileRead(const string &strFileName) {
        // ifstream in(strFileName); 也可以通过构造来打开文件
	ifstream in;
	in.open(strFileName); // 通过open打开文件

	if (!in.is_open()) { // is_open方法判断打开是否成功
		cout << "打开失败" << endl;
		return;
	}
	string strLine;
	while (!in.eof()) { // 用eof()方法来判断ios_base::eofbit标志位是否置位,代表是否读到文件末尾
		getline(in, strLine); // 从ifstream流中逐行读取
		cout << strLine << endl; // 输出到标准输出中
	}
	in.close(); // 关闭ifstream流
}

实际上在并不需要调用in.close()来关闭文件,因为在FileRead结束后,其ifstream对象被销毁导致析构函数被调用,其中会自动帮我们调用in.close()来关闭文件。

对文件对象进行操作时还可以指定特定的文件模式,来看一下有哪些模式:

ifstream默认是以ios::in方式打开的,ofstream则是ios::out方式打开,并其默认会清空文件内所有内容相当于带上了ios::trunc标志进来。如果不想写入文件时文件被截断清空就带上app标志,表示是往文件末尾增加内容, 来看一下:

ofstream out("filename", ios::out | ios::app);

这样就可以做到打开文件后不清空文件内容了, ios::ate和ios::binary可以用于任何类型的文件流对象也可以与in, out, app...等模式合用

string流


string流由sstream头文件控制,其包含了sstringstream, istringstream, ostringstream类型。可以把string对象绑定到这三种类型上进行内存上的string对象操作。

绑定方法可以通过构造函数, 即sstream strm(s)或者调用str(string)方法来进行,下面给一个实例:

struct PersonInfo {
	string name;
	vector<string> phones;
};


void istringstreamTest(vector<PersonInfo> &people) {
	string line, word;
	istringstream record;
	while (getline(cin, line)) {
		PersonInfo info;
		record.clear();
		record.str(line); // 通过str()方法来绑定string对象
		record >> info.name;
		while (record >> word)
			info.phones.push_back(word);
		people.push_back(info);
	}
	for (auto& k : people) {
		cout << k.name << " ";
		for (auto& k : k.phones)
			cout << k;
		cout << endl;
	}
}

这段代码中由于istringstream对象为局部中的全局变量,所以每次使用str()进行绑定的时候要清空里面已经绑定的内容。

下面给出如何通过构造方法绑定string对象的代码:

void istringstreamExec() {
	string str;

	getline(cin, str);
	istringstream ins(str); // 通过构造方法来绑定string对象

	while (ins >> str) {
		cout << str << "\n";
	}
}

接下去使用一个比较符合的例子来看一下如何使用ostringstream对象,来看代码:

struct PersonInfo {
	string name;
	vector<string> phones;
};

void istringstreamTest(vector<PersonInfo> &people) {
	string line, word;
	istringstream record;
	while (getline(cin, line)) {
		PersonInfo info;
		record.clear();
		record.str(line);
		record >> info.name;
		while (record >> word)
			info.phones.push_back(word);
		people.push_back(info);
	}
}

bool valid(const string &str) {
	for (auto& k : str) 
		if (k < '0' || k > '9') 
			return(false);
	return(true);
}

// 如果输入的号码中有非数字成员则提示错误否则按照正常方式输出
void ostringstreamTest(ostream &os) {
	vector<PersonInfo> v;
	istringstreamTest(v);

	for (const auto& entry : v) {
		ostringstream formatted, badNums;
		for (const auto& nums : entry.phones) {
			if (!valid(nums)) 
				badNums << " " << nums;
			else
				formatted << " " << nums;
		}
		if (badNums.str().empty())
			os << entry.name << " " << formatted.str() << endl;
		else
			cerr << "input error: " << entry.name << " invalid numbers " << badNums.str() << endl;
	}
}

上面的代码把之前istringstream的例子也用上了。首先从标准输入中获取姓名与电话并存入一个vector<string>容器中保存。接下去通过ostringstream对象来分别保存全是数字的电话和非纯数字的电话并分别输出出来。

最后来看一下sstream头文件中的类型能够执行的操作吧

IO流的标志位


IO对象的读写可能有失败,成功,错误等等....的状态,C++为了让我们判断状态特定提供了如下的条件状态函数和标志:

s.eof()方法会判断strm::eofbit是否被置位,是返回true否则false

s.fail() 方法会判断strm::failbit是否被置位, 是返回true否则false

s.good(), s.bad()控制着badbit与goodbit, 具体同上

s.clear()会清除所有IO对象状态, 变成初始状态

来看一个实例, 该实例类似于一个栈操作:

void process_read(istream &s) {
	int iNum;
	cout << "输入一个数字:";
	s >> iNum;
}

void bitTest() {
	ios_base::iostate old_state = cin.rdstate(); // 获取现在的标志情况
	cin.clear(); // 清空现有标志
	process_read(cin);
	cin.setstate(old_state); // 回复之前的标志情况
}

看一下如何对IO标志进行复位

void ResetTest() {
	ios_base::iostate st = cin.rdstate();
	cin.setstate(st & ~cin.failbit & ~cin.badbit & ~cin.eofbit | cin.goodbit);
}

上面是让一切存在问题的标志位复位而成功标志位置位的代码段

(完)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值