c++primer 第十七章笔记 01tuple类型

2023-11-10

tuple类型

	//tuple看作一个[快速而随意]的数据结构
	//三个成员都设置为0
	//tuple<size_t, size_t, size_t>threeD;
	//必须使用直接初始化,tuple的构造函数是explicit8789890-=
	tuple < string, vector<double>, int, list<int> >someVal("constants", { 3.14,2.719 }, 42, { 0,1,2,3,4 });
   //为什么可以
	tuple<size_t, size_t, size_t>threeD = { 1,2,3 };
	tuple<size_t, size_t, size_t>threed{ 1,2,3 };

	//类似make_pair ,用make_tuple来生成对象
	//item是一个tuple。包含 const char* ,int,double
	auto item = make_tuple("0-99901423-X",3,20.00);

访问tuple的成员

	//类似make_pair ,用make_tuple来生成对象
	//item是一个tuple。包含 const char* ,int,double
	auto item = make_tuple("0-99901423-X",3,20.00);

	//返回第一个成员
	auto book = get<0>(item);
	cout <<book<< endl;
	//返回第二个成员
	auto cnt = get<1>(item);
	cout << cnt << endl;
	//返回最后一个成员
	auto price = get<2>(item)/cnt;
	cout << price << endl;

	//打折百分之20  get返回指定成员的引用,就是左值引用
     get<2>(item) *= 0.8;
	cout << get<2>(item) << endl;


	//trans是item的类型  decltype确定trangs的类型 
	typedef decltype(item)trans; 
	//返回trans类型对象中成员的数量
	size_t sz = tuple_size<trans>::value;
	cout << sz << endl;
	//cnt的类型与item中第二个成员相同  cnt是一个int
	tuple_element<1, trans>::type CNT = get<1>(item);
	cout <<CNT << endl;

关系和相等运算符
类型不同或成员数量不同都不能使用关系和相等运算符

	tuple<string, string>duo("1", "2");
	tuple<size_t, size_t>twoD(1, 2);
	//bool b = (duo == twoD);//报错 ,不能比较 size_t 和string

	tuple<size_t, size_t, size_t>thREED(1, 2, 3);
	//bool b = (twoD < thREED); //报错 成员数量不同

	tuple<size_t, size_t>origin(0, 0);
	 bool b = (origin < twoD); //正确 ,b为true
	 cout << b << endl;

练习17.1.1节练习
练习17.1 17.2

	 tuple<int, int, int>a{ 10,20,30 };
	 cout << get<0>(a) << endl;
	 cout << get<1>(a) << endl;
	 cout << get<2>(a) << endl;

	 tuple<string, vector<string>, pair<string, int>>B{ "1",{"2"},{"3",4} };
	 cout << get<0>(B) << endl;
	 auto v= get<1>(B);
	 vector<string>::iterator X= v.begin();
	 cout << *X << endl;


	 auto PAIR = get<2>(B);
	 cout << PAIR.first << endl;
	 cout << PAIR.second << endl;

练习17.3

typedef vector<string>::size_type line_no;
typedef tuple<string, shared_ptr<set<line_no>>, shared_ptr<vector<string>>>QueryResult;

ostream& print(ostream& os, const QueryResult& qr);

class TextQuery
{
public:
	TextQuery(ifstream&);
	QueryResult query(const string&)const;

private:
	shared_ptr<vector<string>>file;
	map<string, shared_ptr<set<line_no>>>wm;

};

TextQuery::TextQuery(ifstream& infile) :file(make_shared<vector<string>>())
{
	string line;
	string word;
	line_no index = 0;

	while (getline(infile,line))
	{
		file->push_back(line);
		++index;
		istringstream strline(line);
		while (strline >> word)
		{
			if (ispunct(word[0]))
			{
				word.erase(0, 1);
			}
			if (ispunct(word[word.size() - 1]))
			{
				word.pop_back();
			}
			if (ispunct(word[word.size() - 1]))
			{
				word.pop_back();
			}
			if (!wm[word])
			{
				wm[word] = make_shared < set<line_no>>();
			}
			wm[word]->insert(index);
		}
	}
}
QueryResult TextQuery::query(const string& s)const
{
	static shared_ptr < set <line_no>>nodata(make_shared<set<line_no>>());

	auto loc = wm.find(s);
	if (loc == wm.end())
	{
		return QueryResult(s, nodata, file);
	}
	else
	{

		return QueryResult(s, loc->second, file);
	}
}

inline string make_plural(size_t ctr, const string& word, const string& ending)
{
	return (ctr > 1) ? word + ending : word;
}


ostream& print(ostream& os, const QueryResult& qr)
{
	os << get<0>(qr) << " occurs " << get<1>(qr)->size() << " "
		<< make_plural(get<1>(qr)->size(), "time", "s") << endl;

	for (auto num : *(get<1>(qr)))
		os << "\t(line " << num << ") " << (*get<2>(qr))[num - 1] << endl;

	return os;
}

如果查询的结果是临时使用,tuple就很轻松。
建议还是定义QueryResult类 ,可以有其他种操作,比如多加几种查询方式

17.1.2使用tuple返回多个值

typedef tuple<vector<Sales_data>::size_type,vector<Sales_data>::const_iterator,vector<Sales_data>::const_iterator >matches;

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->end(),book,compareIsbn);

		if (found.first != found.second) //此书店销售了给定书籍
		{
			//记者此书店的索引及匹配的范围
			ret.push_back(make_tuple(it - files.cbegin(), found.first, found.second));
		}
	}

	return ret;//如果未找到匹配记录的话,ret为空
}

使用函数返回的tuple

void reportRseult(istream& in, ostream& os, const vector < vector < Sales_data >>&files )
{
	string s;//要查找的书

	while (in >> s)
	{
		auto trans = findBook(files, s); //销售了这本书的书店
		if (trans.empty())
		{
			cout << s << "now found in any stores" << endl;
			continue; //获得下一步要查找的书
		}

		for (const auto& store : trans) //对每家销售了给定书籍的书店
		{
			//get<n>返回store中的tuple指定的成员
			os << "stroe" << get<0>(store)
				//使用accumulate得包含头文件
				<< "sales: " << accumulate(get<1>(store), get<2>(store), Sales_data(s)) << endl;
		}

	}
}

17.1.2节练习
练习17.4

// tuple.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
#include <iostream>
#include<numeric>
#include<string>
#include<tuple>
#include<vector>
#include<list>
#include<set>
#include<map>
#include<algorithm>
using namespace std;
struct Sales_data {
	//新增的构造函数
	Sales_data() = default;
	Sales_data(const string& s) :booKNo(s) { }
	Sales_data(const string& s, unsigned n, double p) :
		booKNo(s), units_sold(n), revene(p* n) { }
	//构造函数初始化
	Sales_data(istream& is)
	{
		read(is, *this); //read函数的作用是从is中读取一条交易信息然后
						//存入this对象中
	}
	Sales_data& operator+=(const Sales_data& rhs)
	{
		units_sold += rhs.units_sold;
		revene += rhs.revene;
		return *this;

	}


	//新成员:关于Sales_对象的操作
	string isbn() const { return this->booKNo; };
	Sales_data& combine(const Sales_data&);
	double avg_price()const;
	istream& read(istream& is, Sales_data& item)
	{
		double price = 0;
		is >> item.booKNo >> item.units_sold >> price;
		item.revene = price * item.units_sold;
		return is;
	}

	//成员属性
	string booKNo;
	unsigned units_sold = 0;
	double revene = 0.0;
};
ostream& operator<<(ostream&os,const Sales_data&item)
{
	os << item.isbn() << " " << item.units_sold << " " << item.revene << " "
		<< item.revene << " " << item.avg_price();

	return os;
}


//Sales_data的非成员接口函数
Sales_data  add(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs; //拷贝到sum
	sum.combine(rhs); //把rhs的成员加到sum
	return sum;
}
ostream& print(ostream& os, const Sales_data& item)
{
	os << item.isbn() << " " << item.units_sold << " "
		<< item.revene << " " << item.avg_price();
	return os;
}


Sales_data operator+(const Sales_data& lhs, const Sales_data& rhs)
{
	Sales_data sum = lhs;
	sum += rhs;
	return sum;
}





Sales_data& Sales_data::combine(const Sales_data& rhs)
{
	units_sold += rhs.units_sold;  //把rhs的成员添加到this对象的成员上
	revene += rhs.revene;
	return *this; //返回调用该函数的对象
}

double Sales_data::avg_price()const
{
	if (units_sold)
	{
		return revene / units_sold;
	}
	else
		return 0;
}
template<typename Y>
int compare(const Y& v1, const Y& v2)
{
	if (v1 < v2)return -1;
	if (v2 < v1)return 1;
	return 0;
}

bool compareIsbn(const Sales_data& lhs, const Sales_data& rhs)
{
	return lhs.isbn() < rhs.isbn();
}


typedef tuple<vector<Sales_data>::size_type,vector<Sales_data>::const_iterator,vector<Sales_data>::const_iterator >matches;

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->end(),book,compareIsbn);

		if (found.first != found.second) //此书店销售了给定书籍
		{
			//记住此书店的索引及匹配的范围
			ret.push_back(make_tuple(it - files.cbegin(), found.first, found.second));
		}
	}

	return ret;//如果未找到匹配记录的话,ret为空
}

void reportRseult(istream& in, ostream& os, const vector < vector < Sales_data >>&files )
{
	string s;//要查找的书

	while (in >> s)
	{
		auto trans = findBook(files, s); //销售了这本书的书店
		if (trans.empty())
		{
			cout << s << "now found in any stores" << endl;
			continue; //获得下一步要查找的书
		}

		for (const auto& store : trans) //对每家销售了给定书籍的书店
		{
			//get<n>返回store中的tuple指定的成员
			os << "stroe" << get<0>(store)
				//使用accumulate得包含头文件
				<< "sales: " << accumulate(get<1>(store), get<2>(store), Sales_data(s)) << endl;
		}

	}
}
void test02()
{
	Sales_data a("a", 1, 2);
	Sales_data d("a", 1, 2);
	Sales_data e("a", 1, 2);
	Sales_data b("a", 1, 2);
	Sales_data c("c", 1, 2);

	vector<vector<Sales_data>>files;
	vector< Sales_data > FIkes;
	FIkes.push_back(a);
	FIkes.push_back(b);
	FIkes.push_back(c);
	FIkes.push_back(e);	FIkes.push_back(d);
	files.push_back(FIkes);

	reportRseult(cin, cout, files);
}

练习17.5

typedef pair<vector<Sales_data>::size_type, pair<vector<Sales_data>::const_iterator, vector<Sales_data>::const_iterator>>PAIR;

vector<PAIR> findBookK(const vector<vector<Sales_data>>& files, const string& book)
{
	vector<PAIR>ret; //初始化 为空vector
	//对每家书店,查找与给定书籍匹配的记录范围(如果存在的话)

	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		//查找具有相同ISBN的Sales_data范围
		auto found = equal_range(it->cbegin(), it->end(), book, compareIsbn);

		if (found.first != found.second) //此书店销售了给定书籍
		{
			//记住此书店的索引及匹配的范围
			ret.push_back(make_pair(it - files.cbegin(), make_pair(found.first, found.second)));
		}
	}

	return ret;//如果未找到匹配记录的话,ret为空
}

练习17.6
代码链接 https://blog.csdn.net/wlli1985/article/details/99846489


```bash
class metches
{
public:
	metches(vector<Sales_data>::size_type n,pair<vector<Sales_data>::const_iterator,vector<Sales_data>::const_iterator>t):
	num(n),first(t.first),last(t.second){}

	vector<Sales_data>::size_type get_num()const { return num; }
	vector<Sales_data>::const_iterator get_first()const { return first; }
	vector<Sales_data>::const_iterator get_last()const { return last; }

private:
	vector<Sales_data>::size_type num;
	vector<Sales_data>::const_iterator first, last;
};

vector<metches>findBook(const vector<vector<Sales_data>>& files, const string& book)
{
	vector<metches>ret;

	for (auto it = files.cbegin(); it != files.cend(); ++it)
	{
		auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);

		if (found.first != found.second)
		{
			ret.push_back(metches(it - files.cbegin(), make_pair(found.first, found.second)));
		}
	}

	return ret;
}

void reportResules(istream& in, ostream& os, const vector<vector<Sales_data>>& files)
{
	string s;

	while (in >> s)
	{
		auto trans = findBook(files, s);
		if (trans.empty())
		{
			cout << s << "not found in any stores" << endl;
			continue;
		}
		for (const auto& store : trans)
		{
			os << "store" << store.get_num() << "sales:" << accumulate(store.get_first(), store.get_last(), Sales_data(s)) << endl;
		}
	}
}
练习17.7
都差不多,但如果要进行更复杂的查询操作,如查询文本再探的那种,只能用类来实现了

练习17.8
Sales_data()默认构造函数,isbn为空串在输出结果无法看到书的isbn
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

c++primer 第十七章笔记 01tuple类型 的相关文章

随机推荐

  • 2023年武汉市中等职业学校技能大赛 “网络搭建与应用”

    2023年武汉市中等职业学校技能大赛 网络搭建与应用 一 竞赛内容分布 网络搭建及应用 竞赛共分二个部分 其中 第一部分 企业网络搭建部署项目 占总分的比例为50 第二部分 企业网络服务配置及应用项目 占总分的比例为50 项目背景及网络拓扑
  • OpenCV函数cvWaitKey(k)简介

    作者本人的开发环境为VS的MFC构架 结合OpenCV1 0进行图像的处理 可能很多像作者本人一样的初始开发程序员都会用到cvWaitKey 但是对cvWaitKey 的理解一知半解 在具体开发中会由此产生一些困惑 在查询了一些资料后 将资
  • Java实现文件分片上传

    为什么需要文件分片上传 大文件上传中断 假如我们有一个5G的文件 上传过程中突然中断我们该怎么办 上文件上传响应时间长 假如我们有个10G的文件 单次上传时间长 用户体验长 该怎么办 大文件上传重复上传 某些大文件 我们已经上传过了 我们不
  • JavaScript基础知识总结(6张思维导图)

    以下导图均为学习pink老师js基础视频时 自主整理的 有不足的地方 欢迎大家多多指出
  • 如何正确的进行网站入侵渗透测试

    大家都知道渗透测试就是为了证明网络防御按照预期计划正常运行而提供的一种机制 而且够独立地检查你的网络策略 一起来看看网站入侵渗透测试的正确知识吧 简单枚举一些渗透网站一些基本常见步骤 一 信息收集 要检测一个站首先应先收集信息如whois信
  • FastDB简单介绍及实例(Linux)

    本文内容主要是通过学习官网 博客及阅读官网demo做出的总结 FastDB是一个内存数据库 通过把数据加载到内存中实现对数据的操作 相比于传统的数据库 操作的速度更快 但是存在一个缺点就是使用FastDB数据库的应用程序都必须运行在同一台主
  • 【LWIP】stm32用CubeMX(6.4版)配置LwIP+Ping+TCPclient+TCPserver发送信息到PC(操作部分)

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 前言 零 更新 2022 08 07 一 实验平台 二 手把手全程配置步骤 1 配置电脑环境 2 配置cubeMX 3 配置MDK Keil5 4 配置TCPcli
  • 监听屏幕滚动开始和结束事件(scroll start 和scroll stop)

    背景 最近在写一个专题页 产品要求右边导航栏在滑动的时候收起 滑动停止时显示 这样就需要监听到屏幕滚动 scroll start 事件和滚动结束 scroll end 事件 但是又不能为了这个功能专门引入jQuery mobile这个库 所
  • 来,看看这20个常用的宏定义!

    关注 星标公众号 直达精彩内容 ID 技术让梦想更伟大 作者 李肖遥 写好C语言 漂亮的宏定义很重要 使用宏定义可以防止出错 提高可移植性 可读性 方便性等等 下面列举一些成熟软件中常用的宏定义 1 防止一个头文件被重复包含 1 ifnde
  • npm 查看安装包版本

    npm info 安装包包名 如 npm info webpack
  • Linux查看CPU信息[//proc/loadavg]

    工作原理 基于 proc 文件系统 Linux 系统为管理员提供了非常好的方法 使其可以在系统运行时更改内核 而不需要重新引导内核系统 这是通过 proc 虚拟文件系统实现的 proc 文件虚拟系统是一种内核和内核模块用来向进程 proce
  • 1Panel 和宝塔有什么区别?

    宝塔是一款被广泛使用的 Linux 面板 与宝塔 Linux 面板相比 1Panel 的特色是开源和现代化 开源 1Panel 强调开源开放 广泛获取社区使用反馈 并快速迭代 现代化 一方面 1Panel 采纳最新的前端技术 并通过精心设计
  • SpringBoot Restful API 请求响应总结

    Controller 映射注解分为两大类 url映射注解和参数绑定注解 url映射注解 Controller 修饰class 用来创建处理http请求的对象 RestController Spring4之后加入的注解 原来在 Control
  • 2020-11-14

    MySQL学习周报 视图 数据库数据导入导出数据 数据库设计 1 视图 view 1 1 什么是视图 站在不同的角度去看到数据 同一张表的数据 通过不同的角度去看待 1 2 怎么创建视图 怎么删除视图 create view myview
  • 使用宝塔面板安装Rocket.Chat多功能团队聊天室

    安装 官方文档 https rocket chat docs 环境要求 NodeJS 8 11 4 Mongodb 4 0 9 Nginx 非必需 提示 由于官方建议的最低内存1G 所以512M或更小的建议加点虚拟内存 可以使用Swap一键
  • Linux 配置SSH免密登录

    介绍 SSH原理其实是非对称加密 即公钥加密私钥解密 免密登录原理 即事先将RSA非对称加密的公钥由主节点拷贝到到其他节点 只需实现主节点至其他节点的免密即可 流程如下 Client将自己的公钥存放在Server上 追加在文件authori
  • 华为荣耀8手机微信登录显示服务器错误,华为荣耀8手机无法登录360会员圈由于华为荣耀8手机无法登录3 爱问知识人...

    2017 10 12 05 41 48 保存个人资料恢复出厂值试一下 全部 2017 10 12 05 41 48 2017 10 12 05 41 48 会员的名称密码还有么 全部 2017 10 12 05 41 48 2017 10
  • STL算法之排序

    stl 算法库中提供的排序相关算法主要有以下几种 除了 q sort 定义在 cstdlib 头文件中 其余都定义在 algorithm 头文件 算法 功能 sort 排序 stable sort 稳定排序 保证等值情况时的原有顺序 par
  • 【C++】教大家在七夕new一个对象

    new是啥 new 是C 的关键字之一 它一般用来在堆上创建对象 但它与一般的创建对象的方法不同 它在创建对象时 会返回这个对象的指针 堆是啥 还有 和栈有什么区别 栈是由编译器自动分配和释放的 一般存放函数的参数值 局部变量的值等 速度较
  • c++primer 第十七章笔记 01tuple类型

    tuple类型 tuple看作一个 快速而随意 的数据结构 三个成员都设置为0 tuple