C++Primer 学习笔记 第八章 IO库

//8.1 IO类
//到目前为止,我们已经使用过的IO类型和对象都是操纵char数据的。默认情况下,这些对象都是关联用户的控制台窗口的。
//当然,我们不能限制实际应用程序仅从控制台窗口进行IO操作,应用程序常常需要读写命名文件。而且,使用IO操作处理string
//中的字符会很方便。此外,应用程序还可能读写需要宽字符支持的语言。


//8.1.1 IO对象无拷贝或赋值

//8.1.2条件状态

//查询流的状态
//管理条件状态

//8.1.3管理输出缓冲
//每个输出流都管理一个缓冲区,用来保存程序读写的数据。例如,如果执行下面的代码
//os<<"please enter a value: ";
//文本串可能立即打印出来,但也有可能被操作系统保存在缓冲区中,随后再打印。有了缓冲机制,操作系统就可以将程序的
//多个输出操作组合成单一的系统级写操作。由于设备的写操作可能很耗时,允许系统将多个输出操作组合成单一的系统级写操作。
//导致缓冲刷新的原因有很多。

//1.程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。
//2.缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。
//3.我们可以使用操纵符如endl来显式刷新缓冲区。
//4.再每个输出操作之后,我们可以用操作符unitbuf设置流的内部状态,来清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr
//  的内容都是立即刷新的。
//5.一个输出流可能被关联到另一个流。在这种情况下,当读写被关联的流时,关联到的流的缓冲区会被刷新。例如,默认情况下,cin和cerr都关联到cout。
//因此,读cin或写cerr都会导致cout的缓冲区被刷新。


//刷新输出缓冲区
#include "iostream"
#include"fstream"
#include "vector"
#include"string"
#include "sstream"


using namespace std;
int main81() {
	cout << "hi!" << endl;
	cout << "hi!" << flush;
  	cout << "hi" << ends;
	cout << unitbuf;
	cout << "hi";
	system("pause");
	return 0;
}

//关联输入流和输出流
//当一个输入流被锻炼到一输出流时,任何试图从输入流读取数据的操作都会先刷新关联的输出流。
//标准库将cout和cin关联在一起。
//cin>>ival;

int main82() {
	cin.tie(&cout);//仅仅是用来展示:标准库将cin和cout关联在一起
	//old_tie指向关联到cin的流(如果有的话)
	ostream *old_tie = cin.tie(nullptr);//cin不再与其他流关联
	cin.tie(&cerr);//读取cin会刷新cerr而不是cout
	cin.tie(old_tie);//重建cin和cout间的关联
	return 0;
}

//8.2文件输入输出
//头文件fstream定义了三个类型来智齿文件IO:ifstream从一个给定文件中读取数据,ofstream从一个给定文件中写入数据,以及fstream可以读写给定文件。

//8.2.1使用文件流对象
//当我们想要读写一个文件时,可以定义一个文件流对象,并将对象与文件关联起来,每个文件流都定义了一个名为open的成员函数
//他完成一些系统相关的操作,来定位给定的文件,并视情况打开位读或写模式
//创建文件流对象时,我们可以提供文件名。如果提供了一个文件名,则open会被自动调用。
//ifstream in(ifile);    //构造一个ifstream并打开给定文件
//ofstream out;        //输出文件流并未关联到任何文件

int main83() {
	//ifstream in("F:/FWNfiles/C++回炉/C++重造/io.txt");
	ofstream out("F:/FWNfiles/C++回炉/C++重造/io.txt");
	out << "周六保证不学习,周日学习不保证!";
	out << endl;
	out << "星期六保证不休息,星期天休息不保证!";
	out << endl;
	out << "运行之后就没有了?";
	out << endl;
	ifstream in("1.txt");
	ofstream output("2.txt");
	output << "love" << endl;
	ifstream input("2.txt");
//	system("pause");
	return 0;
}


//8.2.2文件模式
//每个流都有一个关联的文件模式,用来指出如何使用文件。表8.4列出了文件模式和他们的含义

//以out模式打开文件会丢弃已有数据
//默认情况下,当我们打开一个ofstream时,文件的内容会被丢弃。阻止一个ofstream清空给定文件内容的方法是同时指定app模式
int main84() {
	//在这几条语句中,file1都被截断
	ofstream out("file1.txt");//隐含以输出模式打开文件并截断文件
	ofstream out2("file1.txt", ofstream::out);//隐含截断文件
	ofstream out3("file1.txt", ofstream::out | ofstream::trunc);
	out << "1";
	out3 << "3";
	out2 << "2";
	out << "4";
	//为了保留文件内容,我们必须显式指定app模式
	ofstream app("file2.txt", ofstream::app);//隐含为输出模式
	app << "1";
	ofstream app2("file2.txt", ofstream::out | ofstream::app);
	app2 << "2";
	ofstream ate("file2.txt", ofstream::out | ofstream::ate);
	ate << "上山打老虎";

	return 0;
}


//8.3string流
//sstream头文件定义了三个类型来智齿内存IO,这些类型可以向string写入数据,从string读取数据,就香string是一个IO流一样
//isstring从string读取数据,ostringstream向string写入数据,而头文件stringstream既可以从string读数据也可以向string写数据


//8.3.1使用istringstream
//假定又这样一个例子,假定有一个文件,列出了一些人和他们的电话号码。某些人只有一个号码,而另一些人则有多个——家庭电话
//工作电话,移动电话。我们的输入文件看起来可能是这样
//morgan 201552368 8625550123
//derw   9735550130
//iee 6095550132 20155550175 8005550000

//文件中每条记录都是以一个人名开始,后面跟随一个或多个电话号码。
//我们首先定义一个简单的类来描述输入数据:

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


int main85() {
	string line, word;
	vector<PresonInfo> peoole;
	while (getline(cin,line))
	{
		PresonInfo info;
		istringstream record(line);
		record >>info.name;
		while (record>>word)
		{
			info.phones.push_back(word);
			peoole.push_back(info);
		}
	}
	system("pause");
	return 0;
}

//8.3.2使用ostringstream
//当我们逐步构造输出,希望最后一起打印时,ostringstream是很有用的。例如,对上一节的例子,我们可能逐个验证
//电话号码并逐个验证电话并改变其格式。如果所有号码都是有效的,我们希望输出一个新的文件,包含改变格式后的号码。
//对于那些无效的号码,我们不会将他们输出到新文件中,而是打印一条包含人名和无效号码的错误信息。

//由于我们不希望输出有无效电话号码的人,因此对每个人,直到验证完所有电话号码后才可以进行输出操作。但是,我们可以先将输出内容
//写入到一个内存ostringstream中。

int main() {
	string line, word;
	vector<PresonInfo> people;
	while (getline(cin, line))
	{
		PresonInfo info;
		istringstream record(line);
		record >> info.name;
		while (record >> word)
		{
			info.phones.push_back(word);
			people.push_back(info);
		}
	}
	for (const auto& entry:people)
	{
		ostringstream formatted, badNums;//每个循环步创建的对象
		for (const auto& nums:entry.phones)
		{
			//if (!valid(nums))
			{
				badNums << " " << nums;
			}
			//else
			//	(formatted<<" "<<format(nums))
		}
		if (badNums.str().empty())
		{
			//os << entry.name << " " << formatted.str() << endl;
		}
		else
		{
			cerr << "input error: " << entry.name << " invalid number(s)" << badNums.str() << endl;
		}
	}



	system("pause");
	return 0;
}

//在此程序中,我们假定已有两个函数,valid和format,分别完成电话号码验证和改变格式的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值