第 17 章 标准库特殊设施

练习 17.1:

tuple<int, int, int> threeInt( 10,20,30 );

练习 17.2:

tuple<string, vector<string>, pair<string, int>> t;

练习 17.3:

#ifndef EX17_3_H
#define EX17_3_H

#include<iostream>
#include<fstream>
#include<vector>
#include<map>
#include<set>
#include<string>
#include<memory>
#include<tuple>
using namespace std;

using line_no = vector<string>::size_type;
using query_result = tuple<string, shared_ptr<set<line_no>>, shared_ptr<vector<string>>>;

class TextQuery
{
public:
	TextQuery(ifstream& ifs);
	query_result query(const string& sought) const;
private:
	shared_ptr<vector<string>> file;	// 输入文件
	// 每个单词到它所在的行号的集合的映射
	map <string, shared_ptr<set<line_no>>> wm;
};

// 打印结果
ostream& print(ostream&, const query_result&);

#endif // !EX17_3_H
#include"ex17_3.h"
#include<sstream>

TextQuery::TextQuery(ifstream& ifs) : file(new vector<string>)
{
	line_no lineNo = 0;
	for (string line; getline(ifs, line); ++lineNo)
	{
		file->push_back(line);				// 保存此行文本
		istringstream line_iss(line);
		for (string word; line_iss >> word;)
		{
			// 删除标点符号
			word.erase(remove_if(word.begin(), word.end(), ispunct), word.end());
			// 如果单词不在wm中,以之为下标在wm中添加一项
			auto& lines = wm[word];
			if (!lines)	// 第一次遇到这个单词时,此指针为空
				lines.reset(new set<line_no>);
			lines->insert(lineNo);
		}
	}
}

query_result TextQuery::query(const string& sought) const
{
	// 如果未找到sought,我们将返回一个指向此set的指针
	static shared_ptr<set<line_no>> nodata(new set<line_no>);
	auto loc = wm.find(sought);
	if (loc == wm.end())
		return make_tuple(sought, nodata, file);	// 未找到
	else
		return make_tuple(sought, loc->second, file);
}

// 打印结果
ostream& print(ostream& os, const query_result& qr)
{
	// 如果找到了单词,打印出现次数和所有出现的位置
	os << get<0>(qr) << " occurs " << get<1>(qr)->size() 
		<< (get<1>(qr)->size() > 1 ? " times" : " time") << endl;
	// 打印单词出现的每一行
	for (auto line_no : *get<1>(qr))
		os << "\t(line " << line_no + 1 << ") " << *(get<2>(qr)->begin() + line_no) << endl;
	return os;
}
#include"ex17_3.h"
#include<sstream>

void runQueries(ifstream& infile)
{
	// infile是一个ifstream,指向我们要处理的文件
	TextQuery tq(infile);	// 保存文件并建立查询map
	// 与用户交互:提示用户输入要查询的单词,完成查询并打印结果
	while (true)
	{
		cout << "enter word to look for, or q to quit: ";
		string s;
		// 若遇到文件尾或输入‘q’时循环终止
		if (!(cin >> s) || s == "q")break;
		// 指向查询并打印结果
		print(cout, tq.query(s)) << endl;
	}

}

int main()
{
	ifstream ifs("storyDataFile.txt");
	runQueries(ifs);

	return 0;
}

练习 17.4:

#include"Sales_data.h"
#include<tuple>
#include<vector>
#include<algorithm>
#include<numeric>
using namespace std;

// matches有三个成员:一家书店的索引和两个指向书店vector中元素的迭代器
typedef tuple<vector<Sales_data>::size_type,
	vector<Sales_data>::const_iterator,
	vector<Sales_data>::const_iterator> matches;
// files保存每家书店的销售记录
// findBook返回一个vector,每家销售了给定书籍的书店在其中都有一项
vector<matches> findBook(const vector<vector<Sales_data>>& files, const string& book)
{
	vector<matches> ret;	// 初始化为空vector
	// 对于每家书店,查找与给定书籍匹配的记录范围
	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		// 查找具有相同ISBN的Sales_data范围
		auto found = equal_range(it->cbegin(), it->cend(), Sales_data(book),
			[](const Sales_data& lhs, const Sales_data& rhs)
			{return lhs.isbn() < rhs.isbn(); });
		if (found.first != found.second)	// 此书店销售了给定书籍
			ret.push_back(make_tuple(it - files.cbegin(), found.first, found.second));
	}
	return ret;		// 如果未找到匹配的销售记录,ret为空
}

void reportResults(istream& is, ostream& os, const vector<vector<Sales_data>>& files)
{
	string s_book;	//要查找的书
	while (cout << "Enter the book ISBN to look for: ", is >> s_book)
	{
		auto trans = findBook(files, s_book);
		if (trans.empty())
		{
			cout << s_book << " not found in any stores" << endl;
			continue;
		}
		// 输出匹配的销售记录
		for (const auto& store : trans)
		{
			auto total = accumulate(get<1>(store), get<2>(store), Sales_data(s_book));
			os << "store " << get<0>(store) + 1 << " sales: " << total << endl;
		}
		cout << "-------------------" << endl;
	}
}
#include "findBook.h"
#include <fstream>

vector<Sales_data> build_store(const string& s)
{
    vector<Sales_data> ret;
    ifstream ifs(s);
    Sales_data item;
    while (ifs >> item) 
        ret.push_back(item);
    sort(ret.begin(), ret.end(), [](const Sales_data& lhs, const Sales_data& rhs) 
        {return lhs.isbn() < rhs.isbn(); });
    return ret;
}

int main()
{
    vector<vector<Sales_data>> files;
    for (int i = 0; i != 4; ++i)
        files.push_back(build_store("book_sales"));

    reportResults(cin, cout, files);
}

练习 17.5:

#include"Sales_data.h"
#include<utility>
#include<vector>
#include<algorithm>
#include<numeric>
using namespace std;

// matches有三个成员:一家书店的索引和两个指向书店vector中元素的迭代器
using matches = pair<vector<Sales_data>::size_type,
	pair<vector<Sales_data>::const_iterator, 
	vector<Sales_data>::const_iterator>>;
// files保存每家书店的销售记录
// findBook返回一个vector,每家销售了给定书籍的书店在其中都有一项
vector<matches> findBook(const vector<vector<Sales_data>>& files, const string& book)
{
	vector<matches> ret;	// 初始化为空vector
	// 对于每家书店,查找与给定书籍匹配的记录范围
	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		// 查找具有相同ISBN的Sales_data范围
		auto found = equal_range(it->cbegin(), it->cend(), Sales_data(book),
			[](const Sales_data& lhs, const Sales_data& rhs)
			{return lhs.isbn() < rhs.isbn(); });
		if (found.first != found.second)	// 此书店销售了给定书籍
			ret.push_back(make_pair(it - files.cbegin(), make_pair(found.first, found.second)));
	}
	return ret;		// 如果未找到匹配的销售记录,ret为空
}

void reportResults(istream& is, ostream& os, const vector<vector<Sales_data>>& files)
{
	string s_book;	//要查找的书
	while (cout << "Enter the book ISBN to look for: ", is >> s_book)
	{
		auto trans = findBook(files, s_book);
		if (trans.empty())
		{
			cout << s_book << " not found in any stores" << endl;
			continue;
		}
		// 输出匹配的销售记录
		for (const auto& store : trans)
		{
			auto total = accumulate(store.second.first, store.second.second, Sales_data(s_book));
			os << "store " << store.first + 1 << " sales: " << total << endl;
		}
		cout << "-------------------" << endl;
	}
}

练习 17.6:

#include"Sales_data.h"
#include<tuple>
#include<vector>
#include<algorithm>
#include<numeric>
using namespace std;

// Matches有三个成员:一家书店的索引和两个指向书店vector中元素的迭代器
class Matches
{
	friend void reportResults(istream&, ostream&, const vector<vector<Sales_data>>&);
public:
	Matches(vector<Sales_data>::size_type index, 
		vector<Sales_data>::const_iterator begin,
		vector<Sales_data>::const_iterator end)
		: _index(index), _begin(begin), _end(end){ }
private:
	vector<Sales_data>::size_type _index;
	vector<Sales_data>::const_iterator _begin;
	vector<Sales_data>::const_iterator _end;
};

// files保存每家书店的销售记录
// findBook返回一个vector,每家销售了给定书籍的书店在其中都有一项
vector<Matches> findBook(const vector<vector<Sales_data>>& files, const string& book)
{
	vector<Matches> ret;	// 初始化为空vector
	// 对于每家书店,查找与给定书籍匹配的记录范围
	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		// 查找具有相同ISBN的Sales_data范围
		auto found = equal_range(it->cbegin(), it->cend(), Sales_data(book),
			[](const Sales_data& lhs, const Sales_data& rhs)
			{return lhs.isbn() < rhs.isbn(); });
		if (found.first != found.second)	// 此书店销售了给定书籍
			ret.push_back(Matches(it - files.cbegin(), found.first, found.second));
	}
	return ret;		// 如果未找到匹配的销售记录,ret为空
}

void reportResults(istream& is, ostream& os, const vector<vector<Sales_data>>& files)
{
	string s_book;	//要查找的书
	while (cout << "Enter the book ISBN to look for: ", is >> s_book)
	{
		auto trans = findBook(files, s_book);
		if (trans.empty())
		{
			cout << s_book << " not found in any stores" << endl;
			continue;
		}
		// 输出匹配的销售记录
		for (const auto& store : trans)
		{
			auto total = accumulate(store._begin, store._end, Sales_data(s_book));
			os << "store " << store._index + 1 << " sales: " << total << endl;
		}
		cout << "-------------------" << endl;
	}
}

练习 17.8:

输出为空,将无法得到想要的结果。

练习 17.9:

bitset<64> bitvec(32);	// 一共64bits,低位为100000,高位全为0
bitset<32> bv(1010101); // 00000000000011110110100110110101
string bstr; cin >> bstr; bitset<8> bv(bstr); // 取决于输入

练习 17.10:

#include <iostream>
#include <bitset>
using namespace std;

int main()
{
    // 使用序列1, 2, 3, 5, 8, 13, 21初始化一个bitset
    bitset<22> bitvec("1000000010000100101110");
    cout << bitvec << endl;

    // 默认初始化并置位
    bitset<22> bit_default;
    for (auto i : { 1, 2, 3, 5, 8, 13, 21 })
        bit_default.set(i);
    cout << bit_default << endl;

    return 0;
}

练习 17.11_13:

#include<bitset>
using namespace std;

template<size_t N> class QuizAnswers
{
public:
	QuizAnswers() = default;
	QuizAnswers(const string& answers): _answers(answers){ }
	// 接受一个问题编号和一个表示真假解答的值,更新测试的解答
	void setAnswer(size_t index, bool value) { _answers.set(index, value); }
	// 生成测验成绩
	size_t score() { return this->_answers.count() * 1.0 / N * 100; }
private:
	bitset<N> _answers;
};
#include"ex17_11.h"
#include <iostream>

int main()
{
    QuizAnswers<10> quiz_answers_10("1100110101");
    cout << quiz_answers_10.score() << endl;

    QuizAnswers<100> quiz_answers_100;
    for(auto i : {1,5,9,16,34,58,72,86,99})
        quiz_answers_100.setAnswer(i, true);  
    cout << quiz_answers_100.score() << endl;

    return 0;
}

练习 17.14:

#include<iostream>
#include<regex>
#include<string>
using namespace std;

int main()
{
	try
	{
		regex r("[[::alnum::]+\\.(cpp|cxx|cc)$", regex::icase);
	}
	catch (regex_error e)
	{
		cout << e.what() << "\ncode: " << e.code() << endl;
	}
	
	return 0;
}

练习 17.15:

#include<iostream>
#include<regex>
#include<string>
using namespace std;

int main()
{
	try
	{
		string pattern("[^c]ei");
		pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
		regex r(pattern);
		smatch results;
		string test_word;
		while (cout << "enter a word, or \"q\" to quit: ", cin >> test_word)
		{
			if (test_word == "q") break;
			if (regex_search(test_word, results, r))
				cout << "Violate the rule: i before e except after c" << endl;
			else
				cout << test_word + " is okay." << endl;
		}
	}
	catch (regex_error e)
	{
		cout << e.what() << "\ncode: " << e.code() << endl;
	}
	
	return 0;
}

练习 17.17:

#include<iostream>
#include<regex>
#include<string>
using namespace std;

int main()
{
	// 查找前一个字符不是c的字符串ei
	string pattern("[^c]ei");
	pattern = "[[:alpha:]]*" + pattern + "[[:alpha:]]*";
	regex r(pattern, regex::icase);	// 进行匹配时忽略大小写
	string test_str = "receipt freind theif receive";
	for (sregex_iterator it(test_str.begin(), test_str.end(), r), end_it;
		it != end_it; ++it)
		cout << it->str() << endl;

	return 0;
}

练习 17.19:

        如果m[4](或m[6])不匹配,则m[4].str()(或m[6].str())返回一个空字符串,该字符串也可以与其他分隔符进行比较。

练习 17.20:

#include<iostream>
#include<regex>
#include<string>
using namespace std;

bool valid(const smatch& m);

int main()
{
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
	regex r(phone);
	smatch m;
	string s;
	while (getline(cin, s))
	{
		for (sregex_iterator it(s.begin(), s.end(), r), end_it; it != end_it; ++it)
		{
			// 检查号码格式是否合法
			if (valid(*it))
				cout << "valid: " << it->str() << endl;
			else
				cout << "not valid: " << it->str() << endl;
		}
	}

	return 0;
}

bool valid(const smatch& m)
{
	// 如果区号前有一个左括号
	if (m[1].matched)
		// 则区号后必须有一个右括号,之后紧跟着剩余号码或一个空格
		return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
	else
		// 否则,区号后不能有右括号
		// 另两个组成部分间的分隔符必须匹配
		return !m[3].matched && m[4].str() == m[6].str();
}

练习 17.21:

#include<iostream>
#include<string>
#include<fstream>
#include<vector>
#include<sstream>
#include<regex>
using namespace std;

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

bool valid(const smatch& m);
void read_record(istream& is, vector<PersonInfo>& people);
void output_record(ostream& os, const vector<PersonInfo>& people);

int main()
{
	string filename;
	cout << "Please input a record file name: ";
	cin >> filename;
	cout << endl;
	ifstream ifs(filename);

	if (!ifs)
	{
		cerr << "No data?" << endl;
		return -1;
	}

	vector<PersonInfo> people;

	read_record(ifs, people);
	
	output_record(cout, people);
	
	return 0;
}

void read_record(istream& is, vector<PersonInfo>& people)
{
	string line, phone_Num;			// 分别保存来自输入的一行和电话号码
	
	while (getline(is, line))
	{
		PersonInfo info;			// 创建一个保存此记录数据的对象
		istringstream record(line);	// 将记录绑定到刚读入的行
		record >> info.name;		// 读取名字
		while (record >> phone_Num) // 读取电话号码
		{
			info.phones.push_back(phone_Num);
		}
		people.push_back(info);
	}
}

void output_record(ostream& os, const vector<PersonInfo>& people)
{
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
	regex r(phone);
	smatch m;
	// 使用ostringstream
	for (const auto& entry : people)		// 对people中每一项
	{
		ostringstream formatted, badNum;	// 每个循环步创建对象
		for (const auto& nums : entry.phones)	// 对每个电话
		{
			for (sregex_iterator it(nums.begin(), nums.end(), r), end_it; it != end_it; ++it)
			{
				if (!valid(*it))
				{
					badNum << " " << nums;		// 将数的字符串形式存入badNum
				}
				else
				{
					formatted << " " << nums;
				}
			}
			
		}
		if (badNum.str().empty())			// 没有错误的电话
		{
			cout << entry.name << formatted.str() << endl;	// 打印名字和格式化的电话
		}
		else // 打印名字和错误格式的电话
		{
			os << "error: " << entry.name << " invalid phone(s): " << badNum.str() << endl;
		}
	}
}

bool valid(const smatch& m)
{
	// 如果区号前有一个左括号
	if (m[1].matched)
		// 则区号后必须有一个右括号,之后紧跟着剩余号码或一个空格
		return m[3].matched && (m[4].matched == 0 || m[4].str() == " ");
	else
		// 否则,区号后不能有右括号
		// 另两个组成部分间的分隔符必须匹配
		return !m[3].matched && m[4].str() == m[6].str();
}

练习 17.22:

string phone = "(\\()?(\\d{3})(\\))?([-. ]|\\s*)?(\\d{3})([-. ]|\\s*)?(\\d{4})";

练习 17.23:

string postcode = "(\\d{5})([-])?(\\d{4})?";
regex r(postcode);

练习 17.24:

#include<iostream>
#include<string>
#include<regex>
using namespace std;
using namespace regex_constants;	// 使用format_no_copy

int main()
{
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
	regex r(phone);
	smatch m;
	string s;
	string fmt = "$2.$5.$7";	// 将号码格式改为ddd.ddd.dddd
	while (getline(cin, s))
		// format_no_copy: 不输出输入序列中未匹配的部分
		cout << regex_replace(s, r, fmt, format_no_copy) << endl;

	return 0;
}

练习 17.25:

#include<iostream>
#include<string>
#include<regex>
using namespace std;
using namespace regex_constants;	// 使用format_no_copy

int main()
{
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
	regex r(phone);
	smatch m;
	string s;
	string fmt = "$2.$5.$7";	// 将号码格式改为ddd.ddd.dddd
	while (getline(cin, s))
	{
		// format_no_copy: 不输出输入序列中未匹配的部分
		s = regex_replace(s, r, fmt, format_no_copy);
        if (s.empty()) 
		{ 
			cout << "no match" << endl;
			continue;
		}
		sregex_iterator it(s.begin(), s.end(), r);
		cout << it->str() << endl;
	}
		
	return 0;
}

练习 17.26:

#include<iostream>
#include<string>
#include<regex>
using namespace std;
using namespace regex_constants;	// 使用format_no_copy

int main()
{
	string phone = "(\\()?(\\d{3})(\\))?([-. ])?(\\d{3})([-. ])?(\\d{4})";
	regex r(phone);
	smatch m;
	string s;
	string fmt = "$2.$5.$7";	// 将号码格式改为ddd.ddd.dddd
	while (getline(cin, s))
	{
		// format_no_copy: 不输出输入序列中未匹配的部分
		s = regex_replace(s, r, fmt, format_no_copy);
		if (s.empty()) 
		{ 
			cout << "no match" << endl;
			continue;
		}
		sregex_iterator it(s.begin(), s.end(), r), end_it;
		auto beg = it;
		if (++beg == end_it)
		{
			cout << "no more than one match: " << endl;
			cout << it->str() << endl;
		}
		else
		{
			cout << "after the first match:" << endl;
			for(;beg != end_it; ++beg)
				cout << beg->str() << endl;
		}
	}
		
	return 0;
}

练习 17.27:

#include<iostream>
#include<string>
#include<regex>
using namespace std;

int main()
{
	string postcode = "(\\d{5})([-])?(\\d{4})?";
	regex r(postcode);
	string s;
	string fmt = "$1-$3";	// 将编码格式改为ddddd-dddd
	while (getline(cin, s))
		cout << regex_replace(s, r, fmt);

	return 0;
}

练习 17.28:

#include<iostream>
#include<random>
using namespace std;

unsigned randVal()
{
	static default_random_engine e;
	static uniform_int_distribution<unsigned> u;
	return u(e);
}

int main()
{
	for (size_t i = 0; i != 10; ++i)
		cout << randVal() << endl;

	return 0;
}

练习 17.29:

#include<iostream>
#include<random>
using namespace std;

unsigned randVal(unsigned seed = 0)
{
	static default_random_engine e(seed);
	static uniform_int_distribution<unsigned> u;
	return u(e);
}

int main()
{
	for (size_t i = 0; i != 10; ++i)
		cout << randVal(i) << endl;

	return 0;
}

练习 17.30:

#include<iostream>
#include<random>
using namespace std;

unsigned randVal(unsigned seed = 0, unsigned min = 0, unsigned max = 9)
{
	static default_random_engine e(seed);
	static uniform_int_distribution<unsigned> u(min, max);
	return u(e);
}

int main()
{
	for (size_t i = 0; i != 10; ++i)
		cout << randVal(i, 0, 99) << endl;

	return 0;
}

练习17.31:

        由于引擎返回相同的随机数序列,如果在循环内定义b和e,每次循环都会创建一个新引擎,从而每步循环都会生成相同的值;而在循环外定义,可保持引擎状态,每次得到随机数序列中的下一个值,分布对象也要保持状态,因此应该在循环外定义。

练习 17.32:

        在循环内定义resp,则无法通过编译,因为do语句结束后,resp被销毁,无法进行while条件判断。

练习 17.33:

#include<iostream>
#include<map>
#include<set>
#include<string>
#include<vector>
#include<fstream>
#include<sstream>
#include<random>
#include<ctime>
using namespace std;

map<string, vector<string>> buildMap(ifstream& map_file);
const string& transform(const string& s, const map<string, vector<string>>& m);
void word_transform(ifstream& map_file, ifstream& input);

int main()
{
    ifstream ifs_map("rules"), ifs_content("text");
    if (ifs_map && ifs_content)
        word_transform(ifs_map, ifs_content);

    return 0;
}

// 读入给定文件,建立起转换映射
map<string, vector<string>> buildMap(ifstream& map_file)
{
    map<string, vector<string>> trans_map;  // 保存转换规则
    string key;     // 要转换的单词
    string pre_value;   // 待处理的内容
    // 读取第一个单词存入key中,行中剩余内容存入pre_value
    while (map_file >> key && getline(map_file, pre_value))
    {
        if (pre_value.size() > 1)   // 检查是否有转换规则
        {
            // brb: be right back是特殊个例只有一种转换方式
            if (key == "brb")
            {
                trans_map[key].push_back(pre_value.substr(1));
                continue;
            }
            // 查找空格位置,通过两个空格的迭代器构造string插入vector
            auto prev = pre_value.begin();
            auto curr = prev + 1;
            for (; (curr = find_if(curr, pre_value.end(), isspace))
                != pre_value.end(); prev = curr,++curr)
                trans_map[key].push_back(string(prev + 1, curr));   // 跳过prev空格
            // 插入最后一个转换方式 
            trans_map[key].push_back(string(prev + 1, curr));
        }
        else
        {
            throw runtime_error("no rule for " + key);
        }
    }
    return trans_map;
}

const string& transform(const string& s, const map<string, vector<string>>& m)
{
    static default_random_engine e(time(0));
    auto map_it = m.find(s);    // 如果存在 返回指向对应元素的迭代器 否则指向尾后迭代器
    if (map_it != m.cend())
    {
        uniform_int_distribution<unsigned> u(0, map_it->second.size() - 1);
        return map_it->second[u(e)];  // 随机使用替换短语
    }
    else
    {
        return s;               // 否则返回原string
    }
}

void word_transform(ifstream& map_file, ifstream& input)
{
    auto trans_map = buildMap(map_file);    // 保存转换规则
    string text;                            // 保存输入中的每一行
    while (getline(input, text))            // 读取每一行输入
    {
        istringstream stream(text);         // 读取每个单词
        string word;
        while (stream >> word)
        {
            //  transform返回它的第一个参数或其转换之后的形式
            cout << transform(word, trans_map) << " "; // 打印输出
        }
        cout << endl;                       // 完成一行的转换
    }
}

练习 17.35:

#include<iostream>
using namespace std;

int main()
{
	cout << "default format: " << 100 * sqrt(2.0) << '\n'
		<< "scientific: " << scientific << 100 * sqrt(2.0) << '\n'
		<< "fixed decimal: " << fixed << 100 * sqrt(2.0) << '\n'
		<< "hexadecimal: " << uppercase << hexfloat << 100 * sqrt(2.0) << '\n'
		<< "use default: " << defaultfloat << 100 * sqrt(2.0) << endl;

	return 0;
}

练习 17.36:

#include<iostream>
#include<iomanip>
using namespace std;

int main()
{
	cout << left << setw(20) << "default format: " << 100 * sqrt(2.0) << '\n'
		<< setw(20) << "scientific: " << scientific << 100 * sqrt(2.0) << '\n'
		<< setw(20) << "fixed decimal: " << fixed << 100 * sqrt(2.0) << '\n'
		<< setw(20) << "hexadecimal: " << hexfloat << uppercase << 100 * sqrt(2.0) << '\n'
		<< setw(20) << "use defaults: " << defaultfloat << 100 * sqrt(2.0) << "\n\n";

	return 0;
}

练习 17.37:

#include<iostream>
#include<string>
#include<fstream>
using namespace std;

int main()
{
	ifstream ifs("test.txt");
	char arr[50];
	string s;
	while (ifs.getline(arr, 20))
		cout << arr << endl;

	return 0;
}

练习 17.39:

#include<iostream>
#include<string>
#include<fstream>
using namespace std;

int main()
{
	fstream inOut("copyOut", 
		fstream::ate | fstream::in | fstream::out);
	if (!inOut)
	{
		cerr << "Unable to open file!";
		return EXIT_FAILURE;
	}
	// inOut以ate模式打开,因此一开始就定位到其文件尾
	fstream::pos_type end_mark = inOut.tellg();		// 记住原文件文件尾位置
	inOut.seekg(0, fstream::beg);					// 重新定位到文件开始
	size_t cnt = 0;									// 字节数累加器
	string line;
	// 继续读取的条件:还未遇到错误且还在读取原数据
	while (inOut && inOut.tellg() != end_mark 
		&& getline(inOut, line))
	{
		cnt += line.size() + 1;						// 加1表示换行符
		auto mark = inOut.tellg();					// 记住读取位置
		inOut.seekp(0, fstream::end);				// 将写标记移动到文件尾
		inOut << cnt;								// 输出累计长度
		// 如果不是最好一行,打印一个分隔符
		if (mark != end_mark)
			inOut << " ";
		inOut.seekg(mark);							// 恢复读位置
	}
	inOut.seekp(0, fstream::end);					// 定位到文件尾
	inOut << "\n";									// 在文件尾输出一个换行符

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值