《C++primer(第五版)》学习之路-第八章:IO库

【 声明:版权所有,转载请标明出处,请勿用于商业用途。  联系信箱:[email protected]】

8.1 IO类

1.

istream(输入流)类型,提供输入操作

ostream(输出流)类型,提供输出操作

cin,一个istream对象,从标准输入读取数据

cout,一个ostream对象,向标准输出写入数据

cerr,一个ostream对象,通常用于输出程序错误信息,写入到标准错误

>>运算符,用来从一个istream对象读取输入数据

<<运算符,用来向一个ostream对象写入输出数据

getline函数,从一个给定的istream读取一行数据,存入一个给定的string对象中

2.

IO 类型在三个独立的头文件中定义:

iostream 定义读写控制窗口的类型,

fstream 定义读写已命名文件的类型,

sstream 所定义的类型则用于读写存储在内存中的 string 对象。

在 fstream 和 sstream 里定义的每种类型都是从iostream 头文件中定义的相关类型派生而来。

3.IO库类型和头文件

4.IO库条件状态

strm::iostate     // 机器相关的整型名,由各个iostream类定义,用于定义条件状态
strm::badbit      // strm::iostate类型的值,用于指出被破坏的流
strm::failbit       // strm::iostate类型的值,用于指出失败的IO操作
strm::eofbit       // strm::iostate类型的值,用于指出流已经到达文件结束符
s.eof()               // 如果设置了流s的eofbit值,则该函数返回true
s.fail()               // 如果设置了流s的failbit值,则该函数返回true
s.bad()              // 如果设置了流s的badbit值,则该函数返回true
s.good()            // 如果流s处于有效状态,则该函数返回true
s.clear()            // 将流s中的所有状态值都重设为有效状态
s.clear(flag)      // 将流s中的某个指定条件状态设置为有效。flag的类型是strm::iostate
s.setstate(flag) // 给流s添加指定条件。flag的类型是strm::iostate
s.rdstate()        // 返回流s的当前条件,返回值类型为strm::iostate

5.

导致缓冲刷新的原因有很多:

1. 程序正常结束,作为main函数的return操作的一部分,缓冲刷新被执行。

2. 缓冲区满时,需要刷新缓冲,而后新的数据才能继续写入缓冲区。

3.我们可以使用操纵符如endl来显式刷新缓冲区。

4. 在每次输出操作完后,我们可以用操作符unitbuf设置流的内部状态,从而清空缓冲区。默认情况下,对cerr是设置unitbuf的,因此写到cerr的内容都是立即刷新的。

5. 一个输出流可能被关联到另一个流。在这种情况下,当肚泻被关联的流时,关联到的流的缓冲区会被刷新。

6.刷新输出缓冲区

endl 操纵符,用于输出一个换行符并刷新缓冲区。

flush操纵符,用于刷新流,但不在输出中添加任何字符。

ends操作符,这个操纵符在缓冲区中插入空字符 null,然后后刷新它。

7.

unitbuf操纵符,这个操纵符在每次执行完写操作后都刷新流。

nounitbuf操纵符将流恢复为使用正常的、由系统管理的缓冲区刷新方式。

8.2 文件输入输出

1.C++ 通过以下几个类支持文件的输入输出:

ofstream: 写操作(输出)的文件类 (由ostream引申而来)

ifstream: 读操作(输入)的文件类(由istream引申而来)

fstream: 可同时读写操作的文件类 (由iostream引申而来)

2.文件模式

in              打开文件做读操作

out             打开文件做写操作

app             在每次写之前找到文件尾

ate             打开文件后立即将文件定位在文件尾

trunc           打开文件时清空已存在的文件流

binary          以二进制模式进行 IO 操作

8.3 string流

1.标准库定义了三种类型的字符串流:

istringstream,由 istream 派生而来,提供读 string 的功能。

ostringstream,由 ostream 派生而来,提供写 string 的功能。

stringstream,由 iostream 派生而来,提供读写 string 的功能。

2.stringstream 特定的操作

sstream strm;              strm是一个未绑定的stringstream对象。sstream是头文件sstream中定义的一个类型

sstream strm(s);          strm是一个sstream对象,保存string s的一个拷贝。此构造函数是explict的。

strm.str()                     返回strm所保存的string的拷贝

strm.str(s)                   将string s拷贝到strm中。返回void

PS:部分练习答案

练习8.1

istream& func(istream& is)
{
	std::string sbuf;
	while(is >> sbuf)
		std::cout << sbuf << std::endl;
	is.clear();
	return is;
}

练习8.2

#include <iostream>
using std::istream;

istream& func(istream& is)
{
	std::string sbuf;
	while(is >> sbuf)
		std::cout << sbuf << std::endl;
	is.clear();
	return is;
}

int main()
{
	istream& is = func(std::cin);
	std::cout << is.rdstate() << std::endl;

	return 0;
}

练习8.4

#include <fstream>
#include <string>
#include <vector>
#include <iostream>

using std::vector;
using std::string;
using std::ifstream;
using std::cout;
using std::endl;

void ReadFileToVec(const string& fileName,vector<string>& vec)
{
	ifstream ifs(fileName);
	if(ifs)
	{
		string buf;
		while(std::getline(ifs,buf))
			vec.push_back(buf);
	}
}

int main()
{
	vector<string> vec;
	ReadFileToVec("data.txt",vec);
	for(const auto& str:vec)
		cout << str << endl;
	return 0;
}

练习8.5

#include <fstream>
#include <string>
#include <vector>
#include <iostream>

using std::vector;
using std::string;
using std::ifstream;
using std::cout;
using std::endl;

void ReadFileToVec(const string& fileName,vector<string>& vec)
{
	ifstream ifs(fileName);
	if(ifs)
	{
		string buf;
		while(ifs >> buf)
			vec.push_back(buf);
	}
}

int main()
{
	vector<string> vec;
	ReadFileToVec("data.txt",vec);
	for(const auto& str:vec)
		cout << str << endl;
	return 0;
}

练习8.6

<pre name="code" class="cpp">#include <fstream>
#include <iostream>

#include "ex7_26.h"
using std::ifstream;
using std::cout;
using std::endl;
using std::cerr;

int main(int argc, char** argv)
{
	ifstream input(argv[1]);

	Sales_data total;
	if (read(input, total))
	{
		Sales_data trans;
		while (read(input, trans))
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(cout, total) << endl;
				total = trans;
			}
		}
		print(cout, total) << endl;
	}
	else
	{
		cerr << "No data?!" << endl;
	}

	return 0;
}

练习8.7

#include <fstream>
#include <iostream>

#include "ex7_26.h"
using std::ifstream;
using std::ofstream;
using std::endl;
using std::cerr;

int main(int argc, char** argv)
{
	ifstream input(argv[1]);
	ofstream output(argv[2]);

	Sales_data total;
	if (read(input, total))
	{
		Sales_data trans;
		while (read(input, trans))
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(output, total) << endl;
				total = trans;
			}
		}
		print(output, total) << endl;
	}
	else
	{
		cerr << "No data?!" << endl;
	}

	return 0;
}

练习8.8

#include <fstream>
#include <iostream>

#include "ex7_26.h"
using std::ifstream;
using std::ofstream;
using std::endl;
using std::cerr;

int main(int argc, char** argv)
{
	ifstream input(argv[1]);
	ofstream output(argv[2], ofstream::app);

	Sales_data total;
	if (read(input, total))
	{
		Sales_data trans;
		while (read(input, trans))
		{
			if (total.isbn() == trans.isbn())
				total.combine(trans);
			else
			{
				print(output, total) << endl;
				total = trans;
			}
		}
		print(output, total) << endl;
	}
	else
	{
		cerr << "No data?!" << endl;
	}

	return 0;
}

练习8.9

#include <iostream>
#include <sstream>
using std::istream;

istream& func(istream& is)
{
	std::string buf;
	while(is >> buf)
		std::cout << buf << std::endl;
	is.clear();
	return is;
}

int main()
{
	std::istringstream iss("hello word");
	func(iss);
	return 0;
}

练习8.10

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>

using std::vector;
using std::string;
using std::ifstream;
using std::istringstream;
using std::cout;
using std::endl;
using std::cerr;

int main()
{
	ifstream ifs("data.txt");
	if (!ifs)
	{
		cerr << "No data?" << endl;
		return -1;
	}

	vector<string> vecLine;
	string line;
	while (getline(ifs, line)) vecLine.push_back(line);

	for (auto& s : vecLine)
	{
		istringstream iss(s);
		string word;
		while (iss >> word)
			cout << word << endl;
	}

	return 0;
}

练习8.11

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using std::vector;
using std::string;
using std::cin;
using std::istringstream;

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

int main()
{
	string line, word;
	vector<PersonInfo> people;
	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);
	}

	for (auto& p : people)
	{
		std::cout << p.name << " ";
		for (auto& s : p.phones) std::cout << s << " ";
		std::cout << std::endl;
	}

	return 0;
}

练习8.13

#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>

using std::vector;
using std::string;
using std::cin;
using std::istringstream;
using std::ostringstream;
using std::ifstream;
using std::cerr;
using std::cout;
using std::endl;
using std::isdigit;

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

bool valid(const string& str)
{
	return isdigit(str[0]);
}

string format(const string& str)
{
	return str.substr(0, 3) + "-" + str.substr(3, 3) + "-" + str.substr(6);
}

int main()
{
	ifstream ifs("data.txt");
	if (!ifs)
	{
		cerr << "no phone numbers?" << endl;
		return -1;
	}

	string line, word;
	vector<PersonInfo> people;
	istringstream record;
	while (getline(ifs, line))
	{
		PersonInfo info;
		record.clear();
		record.str(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())
			cout << entry.name << " " << formatted.str() << endl;
		else
			cerr << "input error: " << entry.name << " invalid number(s) " << badNums.str() << endl;
	}

	return 0;
}

版权声明:本文为博主原创文章,如果转载,请注明出处

时间: 2024-10-12 15:40:08

《C++primer(第五版)》学习之路-第八章:IO库的相关文章

C++ Primer 第五版学习笔记

<C++ Primer>第五版中文版学习笔记 ? C++ Primer 第五版学习笔记

C++ Primer(第五版)学习笔记_9_标准模板库_multimap多重映照容器

C++ Primer(第五版)学习笔记_9_标准模板库_multimap多重映照容器 多重映照容器multimap与map结构基本相同,但由于重复键值存在,所以multimap的元素插入.删除.查找都与map的方法不相同. 1.multimap对象创建.元素插入 插入元素时,需要使用insert()方法和类似pair<string,double>("Jack", 300.5)的元素结构.可以看到,重复的元素是按照插入的先后顺序排序的. #include <iostre

C++ Primer(第五版)学习笔记_5_标准模板库string(2)

C++ Primer(第五版)学习笔记_5_标准模板库string(2) 10.搜索string对象的元素或子串 采用find()方法可查找字符串中的第一个字符元素(char, 用单引号界定)或者子串(用双引号界定):如果查到,则返回下标值(从0开始计数),如果查不到,则返回一个很大的数string:npos(即:4294967295). #include <iostream> #include <stdio.h> #include <string> using nam

C++ Primer(第五版)学习笔记_3_标准模板库vector(2)

C++ Primer(第五版)学习笔记_3_标准模板库vector(2) 欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢 6.元素的插入 insert()方法可以在vector对象的任意位置前插入一个新的元素,同时,vector自动扩张一个元素空间,插入位置后的所有元素依次向后挪动一个位置. 要注意的是,insert()方法要求插入的位置,是元素的迭代器位置,而不是元素的下标. #include <iostream> #include <vector> using namespa

C++ Primer(第五版)学习笔记_1_标准模板库--快速入门

C++ Primer(第五版)学习笔记_1_标准模板库--快速入门 欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢 标准模板库(STL)提供三种类型的组件:容器.迭代器和算法,他们都支持泛型程序设计标准. 容器主要有两类:顺序容器和关联容器.顺序容器(vector.list.deque和string等)是一系列元素的有序集合.关联容器(set.multiset.map和multimap)包含查找元素的键值. 迭代器的作用是遍历容器. STL算法库包含四类算法:排序算法.不可变序算法.变序性算法

C++ Primer(第五版)学习笔记_2_标准模板库vector(1)

C++ Primer(第五版)学习笔记_2_标准模板库vector(1) 欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢 向量容器vector不但能像数组一样进行随机访问,还能在尾部插入元素,完全可以替代数组. 值得注意的是,vector具有内存自动管理的功能,对于元素的插入和删除,可以动态调整所占的内存空间. 容器vector的下标是从0开始的,如果vector容器的大小是n,则元素下标为0~n-1,这和数组的一样的.不一样的是,vector可以随时调整其大小. vector重要的方法有三个

C++ Primer(第五版)学习笔记_4_标准模板库string(1)

C++ Primer(第五版)学习笔记_4_标准模板库string(1) 1.创建string对象 创建一个空字符串,其长度为0 #include <iostream> #include <string> using namespace std; int main(int argc, char* argv[]) { string s; cout << s.length() << endl; return 0; } 运行结果: 0 2.给string对象赋值

C++ Primer(第五版)学习笔记_6_标准模板库_set集合容器

C++ Primer(第五版)学习笔记_6_标准模板库_set集合容器 Set集合容器实现了红黑树(Red-BlackTree)的平衡二叉检索树的数据结构,在插入元素时,它会自动调整二叉树的排序,把该元素放到适当的位置. (1)确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值: (2)另外,还得确保根节点左子树的高度与右子树的高度相等.这样,二叉树的高度最小,从而检索速度最快. 平衡二叉检索树的检索使用中序遍历算法,检索效率高.默认情况下,将键值由小到大遍历. 对于s

C++ Primer(第五版)学习笔记_8_标准模板库_map映照容器

C++ Primer(第五版)学习笔记_8_标准模板库_map映照容器 map映照容器的元素数据是由一个键值和一个映照数据组成的,键值与映照数据之间具有一一映照的关系. map映照容器的数据结构也是采用红黑树来实现的. 1.map创建.元素插入和遍历访问 #include <iostream> #include <stdio.h> #include <vector> #include <map> #include <string> using n

C++ Primer(第五版)学习笔记_7_标准模板库_multiset多重集合容器

C++ Primer(第五版)学习笔记_7_标准模板库_multiset多重集合容器 多重集合容器multiset与set一样,也是使用红黑树来组织元素数据的,唯一不用的是,multiset允许重复的元素键值插入.其结构示意图如下: 1.multiset元素插入 #include <iostream> #include <stdio.h> #include <vector> #include <set> #include <string> usi