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