练习10.26 解释三种插入迭代器的不同。
三种类型分别为 back_inserter、front_inserter、inserter。
back_inserter创建一个尾部迭代器push_back,比如这个例子。
vector<int> vec;
auto it = back_inserter(vec);/it现在就是push_back的那个迭代器。
*it = 10;//通过这个操作赋值为10
在一个循环中每次back_inserter都会指向容器中新的push_back。
front_inserter创建一个push_front迭代器,每次迭代时,都指向容器头,这样就会将插入的顺序反向。比如下面这个例子。使用front_inserter必须保证容器支持push_front操作。
list<int> lst = {1,2,3,4};
list<int> lst1;
copy(lst.cbegin(),lst.cend(),front_inserter(lst1));// lst1的值为 4 3 2 1
inserter迭代器接受两个参数,这个参数必须是一个指向给定容器的迭代器。元素将被插入到给定迭代器所表示的元素之前。
练习10.27:除了unique之外,标准库还定义了名为unique_copy函数,他接受第三个迭代器,表示拷贝不重复元素的目的位置。编写一个程序,使用unique_copy将一个vector中不重复的元素拷贝到一个初始为空的list中。
vector<int> ivec = {1,2,3,3,4,5,6,7,8,8,9,9,9,2,1};
list<int> il1,il2;
unique_copy(ivec.cbegin(),ivec.cend(), inserter(il1, il1.begin()));
unique_copy(ivec.cbegin(),ivec.cend(), front_inserter(il2));
练习10.28 一个vector中保存1到9,将其拷贝到三个其他容器中。分别使用inserter、back_inserter和front_inserter将元素添加到三个容器中。对每种inserter,估计输出序列是怎样的,运行程序验证你的估计是否正确。
vector<int> ivec = {1,2,3,4,5,6,7,8,9};
list<int> il1,il2,il3;
copy(ivec.cbegin(),ivec.cend(), inserter(il1, il1.begin()));//正序
copy(ivec.cbegin(),ivec.cend(), front_inserter(il2)); //倒序
copy(ivec.cbegin(),ivec.cend(), back_inserter(il3)); //正序
练习10.29 编写程序,使用流迭代器读取一个文本文件,存入一个vector中的string里。
int main() {
ifstream ifs("test.txt");
istream_iterator<string> in(ifs),eof;
vector<string> s;
copy(in,eof, back_inserter(s));
return 0;
}
练习10.30 使用流迭代器、sort和copy从标准输入读取一个整数序列,将其排序,并将结果写到标准输出。
int main() {
ifstream ifs("test.txt");
istream_iterator<int> in(ifs),eof;
vector<int> s;
copy(in,eof, back_inserter(s));
sort(s.begin(),s.end());
ostream_iterator<int> out(cout," ");
copy(s.cbegin(),s.cend(),out);
return 0;
}
练习10.31 修改前一题的程序,使其只打印不重复的元素。你的程序应使用unique_copy。
int main() {
ifstream ifs("test.txt");
istream_iterator<int> in(ifs),eof;
vector<int> s;
copy(in,eof, back_inserter(s));
sort(s.begin(),s.end());
ostream_iterator<int> out(cout," ");
unique_copy(s.cbegin(),s.cend(),out);
return 0;
}
练习10.33 编写程序,接受三个参数:一个输入文件和两个输出文件的文件名。输入文件保存的应该是整数。使用istream_iterator读取输入文件。使用ostream将奇数写入一个输出文件,每个值都跟一个空格。将偶数写入第二个输出文件,每个值都独占一行。
int main(int argc, char **argv)
{
if (argc != 4) return -1;
std::ifstream ifs(argv[1]);
std::ofstream ofs_odd(argv[2]), ofs_even(argv[3]);
std::istream_iterator<int> in(ifs), in_eof;
std::ostream_iterator<int> out_odd(ofs_odd, " "), out_even(ofs_even, "\n");
std::for_each(in, in_eof, [&out_odd, &out_even](const int i){
*(i & 0x1 ? out_odd : out_even)++ = i;
});
练习10.34 使用reverse_iterator逆序打印一个vector。
vector<int> ivec = {1,2,3,4,5,6,7,8,9};
ostream_iterator<int> out(cout," ");
for (auto i = ivec.crbegin(); i != ivec.crend() ; ++i) {
out = *i;
}
练习10.35 使用普通迭代器逆序打印一个vector。
int main() {
vector<int> ivec = {1,2,3,4,5,6,7,8,9};
ostream_iterator<int> out(cout," ");
for (auto i = ivec.cend() - 1; i != ivec.cbegin() - 1; --i) {
out = *i;
}
return 0;
}
练习10.36 使用 find在一个int的list中查找最后一个值为0 的元素。
int main() {
list<int> il = {0,1,2,3,4,5,6,0,1,2,3,4,0,11,23};
auto end = find(il.crbegin(),il.crend(),0);
return 0;
}
练习10.37 给定一个包含10个元素的vector,将位置3到位置7之间的元素按逆序拷贝到一个list中。
int main() {//逆向迭代器的方法。
list<int> il;
vector<int> ivec = {1,2,3,4,5,6,7,8,9,10};
ostream_iterator<int> out(cout," ");
copy(ivec.crbegin() + 3,ivec.crend() - 2,back_inserter(il));
copy(il.cbegin(),il.cend(),out);
return 0;
}
int main() {//front_inserter方法。
list<int> il;
vector<int> ivec = {1,2,3,4,5,6,7,8,9,10};
ostream_iterator<int> out(cout," ");
copy(ivec.cbegin() + 2,ivec.cend() - 3,front_inserter(il));
copy(il.cbegin(),il.cend(),out);
return 0;
}
练习10.38 列出5个迭代器类别,以及每类迭代器所支持的操作。
输入迭代器:==、!=、++、*、->。算法find、accumulate要求输入迭代器。
输出迭代器:++、*。算法copy的第三个参数就是输出迭代器。ostream_iterator也是输出迭代器。
前向迭代器:支持读写操作,只能在序列中沿一个方向移动,可以多次读写同一个元素。repace要求前向迭代器。forward_list上的迭代器是前向迭代器。
双向迭代器:支持正反向读写操作,还支持--操作。算法reverse要求双向迭代器,除了forward_list,其他标准库都提供符合双向迭代器要求的迭代器。
随机访问迭代器:提供在常量时间内序列任意元素的能力,支持(<、<=、>、>=、+、+=、-、-=)
下标运算符iter[n]。
练习10.39 list上的迭代器属于哪类?vector呢?
list的迭代器是双向迭代器,vector的迭代器是随机访问迭代器。
练习10.40 你认为copy要求哪类迭代器?reverse和unique呢?
copy的第一和第二个参数要求输入迭代器,第三个参数要求输出迭代器。
reverse要求双向迭代器。
unique要求前向迭代器。