C++Primer15 IO库

第14讲对标准库做了一些简单的介绍,从这一讲开始依次对各个标准库进行详解。这一讲是IO库

IO库

为了支持不同种类的IO处理操作,C++定义了多种IO类型。

iostream定义了用于读写流的基本类型。

  1. istream 从流读取数据
  2. ostream 向流写入数据

fstream定义了读写命名文件的类型。

  1. ifstream 从文件读取数据
  2. ofstream 向文件写入数据

sstream定义了读写内存string对象的类型。

  1. istringstream 从string读取数据
  2. ostringstream 向string写入数据

类型fstream和sstream都继承自iostream,我们如何使用iostream就如何使用前两个。也就是我们如何使用cin和cout就如何使用前两个。

需要注意一点:IO对象不能拷贝不能赋值,所以将IO对象作为参数或返回值类型时,需要用引用,同时,不能用const。

流的状态大概就这一点有用:
当我们输入文件结束符时,cin会进入错误状态。s.clear()将流s中所有条件状态位复位,将流的状态设置为有效。

管理输出缓冲

每个输出流都管理一个缓冲区,用来保存程序读写的数据。如果执行os<<“lalalalalla” 文本串可能会打印出来,但也有可能保存到了操作系统的缓冲区中,随后再打印。

导致缓冲刷新(数据被打印出来)几个常见原因:

  1. 程序正常结束,作为return操作的一部分
  2. endl
  3. 缓冲区满

除了endl可以刷新缓冲区,还有两个。

cout<<"hi"<<endl; //输出hi和换行符,然后刷新缓冲区
cout<<"hi"<<flush;//输出hi,然后刷新缓冲区,不附加任何额外字符
cout<<"hi"<<ends;//输出hi和一个空字符,然后刷新缓冲区

如果想在每次输出操作后都刷新缓冲区,我们可以使用unitbuf操作符。
它告诉流接下来每次写操作后都进行一次flush操作。而nounitbuf则重置流,恢复原先的缓冲机制。

cout<<unitbuf;
cout<<nounitbuf;

文件输入输出

ifstream从一个给定文件读取数据,ofstream向一个给定文件写入数据。使用它们跟使用cin和cout一样。

fstream定义了一些新的操作,我们可以对fstream,ifstream,ofstream调用这些操作。

fstream fstrm;
fstream fstrm(s);//创建fstream,打开名为s的文件,s可以是字符串
fstream fstrm(s,mode);//以mode方式打开
fstrm.open(s);//打开s文件
fstrm.close();
fstrm.is_open();//返回bool,文件是否成功打开且尚未关闭

因为上面说了,fstream和sstream都继承自iostream。因此在需要istream&的地方,可以使用ifstream对象(这不就是派生与继承那块儿的虚函数嘛)。

比如之前的Sales_data类,我们不传入cin而是传入ifstream。

int main()
{
	ifstream in("Sales_data_text_in.txt");
	ofstream out("Sales_data_text_out.txt");
	Sales_data total;
	if (read(in, total))
	{
		Sales_data trans;
		while (read(in, trans))
		{
			if (total.isbn() == trans.isbn())
			{
				total.combine(trans);
			}
			else
			{
				print(out, total);
				total = trans;
			}
		}
		print(out, total);
	}
	else
	{
		out << "No data\n";
	}
}	

程序可以正常运行,并写入到Sales_data_text_out.txt文件中。

上面我们用到的是以构造函数的方式打开,我们也可以使用open函数打开。

ofstream out;
out.open("cuinan.text");
if(out)
{}

这样打开最好进行一个检验。如果打开失败,out条件会为 假。
当我们想用out绑定另一个文件时,必须先关闭此文件

out.close();
out.open("lalala.text");
if(out)
{}

还有一句话:当一个fstream对象被销毁时,close会自动被调用。

一个小练习:
将文件的内容读入到一个vector中。

int main()
{
	ifstream ifstr("test_fstream.txt");
	vector<string> vec;
	string str;
	if (ifstr)
	{
		while (getline(ifstr,str))
		{
			vec.push_back(str);
		}
		cout << "读取完成" << endl;
		for (auto s : vec)
		{
			cout << s << endl;
		}
	}
	else
	{
		cout << "加载失败" << endl;
	}
}

在这里插入图片描述
在这里插入图片描述
注意看这两个程序有什么区别

int main()
{
	ifstream ifstr("test_fstream.txt");
	vector<string> vec;
	string str;
	if (ifstr)
	{
		while (ifstr>>str)
		{
			vec.push_back(str);
		}
		cout << "读取完成" << endl;
		for (auto s : vec)
		{
			cout << s << endl;
		}
	}
	else
	{
		cout << "加载失败" << endl;
	}
}

文件还是那个文件
在这里插入图片描述

文件模式

app模式:每次写操作前均定位到文件末尾

默认情况下,当我们打开一个ofstream,文件的内容会被丢弃,阻止一个ofstream清空给定文件内容的方法是同时指定app模式。

ofstream app("file2",ofstream::app);
	ofstream out("test_fstream.txt",ofstream::app);
	if (out)
	{
		out << "lalala";
	}
	else
	{
		cout << "加载失败" << endl;
	}
	//当然,也可以这样 out.open("test_fstream.txt",ofstream::app)

以追加方式打开。

.

string读写流

sstream头文件定义了三个类型来支持内存IO

istringstream:从string读数据
ostringstream:向string写数据
stringstream:既可读数据又可写数据

stringstream有几个特异性操作

sstream strm;
sstream strm(s); //保存s的一个拷贝
strm.str(); //返回strm所保存的string的拷贝
strm.str(s); //将s拷贝到strm中

.
istringstream的使用
.
当我们的某些工作是对整行文本进行处理,其他一些工作是处理行内的一些单词时,经常会使用到istringstream。
比如下面这个例子

在这里插入图片描述
将这些存入到一个vector中。

下面是程序

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

int main()
{
	ifstream ifstr("test_sstream.txt");
	vector<PersonInfo> people;
	if (ifstr)
	{
		string str;
		while (getline(ifstr, str))
		{
			PersonInfo temp;
			string phoneNum;
			istringstream istr(str);
			istr >> temp.name;
			while (istr >> phoneNum)//当字符串读完后,会触发文件结束符
			{
				temp.phone.push_back(phoneNum);
			}
			people.push_back(temp);
		}
	}
	else
	{
		cout << "加载失败" << endl;
	}
	for (auto s : people)
	{
		cout << s.name << " ";
		for (auto s1 : s.phone)
		{
			cout << s1 << " ";
		}
		cout << endl;
	}
}

在这里插入图片描述
可以看出,对于一个字符串,如果我们希望挨个处理里面的每个单词,那istringstream是最好的选择。

再来一个小练习:

将文件中的一行一行字符串保存到vector中,然后用istringstream读取每一行中的各个单词。

int main()
{
	vector<string> vec;
	ifstream ifstr("test_sstream_2.txt");
	if (ifstr)
	{
		string str;
		while (getline(ifstr, str))
		{
			vec.push_back(str);
		}
		for (auto s : vec)
		{
			istringstream isstr(s);
			string temp;
			while (isstr >> temp)
			{
				cout << temp << " ";
			}
		}
	}
	else
	{
		cout << "加载失败" << endl;
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述
ostringstream的使用

当我们希望逐步构造输出,最后一起打印时,使用ostringstream是很有用的。
使用的时候就将各个字符串<<给ostringstream就可以了。

string str;
ostringstream result;
result << str;
result.str()//打印的时候可以这样

好,这就是IO库。下一张是顺序容器。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值