练习10.7: 下面的程序是否有错误?如果有,请改正。
(a)
vector<int>vec;
list<int>lst;
int i;
while (cin >> i)
lst.push_back(i);
copy(lst.cbegin(),lst.cend(), vec.begin());
(b)
vector<int>v;
v.reserve(10);
fill_n(v.begin(), 10, 0);
(a)Fixed: added this statement :
vec.resize(lst.size());
vector<int>vec;
list<int>lst;
int i;
while (cin >> i)
lst.push_back(i);
vec.resize(lst.size());
copy(lst.cbegin(), lst.cend(), vec.begin());
Cause Algorithms that write to a destination iterator assume the destination is large enough to hold the number of elements being written.
Another way to fix bug :
copy(lst.cbegin(), lst.cend(), back_inserter(vec));
(b)Fixed: 1. use v.resize(10);
or 2. use fill_n(std::back_inserter(v), 10, 0);
vector<int>v;
v.resize(10);
fill_n(v.begin(), 10, 0);
c.reserve(n);分配至少能容纳n个元素的内存空间。
vector 的reserve增加了vector的capacity,但是它的size没有改变!而resize改变了vector的capacity同时也增加了它的size!
原因如下:
reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。
resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的
只读算法:
#include<numeric>
// sum the elements in vec starting the summation with the value 0
int sum = accumulate(vec.cbegin(), vec.cend(), 0);
string sum = accumulate(v.cbegin(), v.cend(), string(""));
![得意](http://static.blog.csdn.net/xheditor/xheditor_emot/default/proud.gif)
Ordinarily it is best to usecbegin()andcend() with algorithms that read, but do not write, the elements.
Another read-only algorithm is equal, which lets us determine whether two sequences hold the same values.
// roster2 should have at least as many elements as roster1
equal(roster1.cbegin(), roster1.cend(), roster2.cbegin());
Algorithms That Write Container Elements写容器元素的算法
fill(vec.begin(), vec.end(), 0); // reset each element to 0
// set a subsequence of the container to 10
fill(vec.begin(), vec.begin() + vec.size()/2, 10);
back_inserter定义在头文件
iterator中
vector<int> vec; // empty vector
auto it = back_inserter(vec); // assigning through it adds elements to vec
*it = 42; // vec now has one element with value 42
vector<int> vec; // empty vector
// ok: back_inserter creates an insert iterator that adds elements to vec
fill_n(back_inserter(vec), 10, 0); // appends ten elements to vec
Copy Algorithms拷贝算法
int a1[] = { 0,1,2,3,4,5,6,7,8,9 };
int a2[sizeof(a1) / sizeof(*a1)]; // a2 has the same size as a1
// ret points just past the last element copied into a2
auto ret = copy(begin(a1), end(a1), a2); // copy a1 into a2
// replace any element with the value 0 with 42
replace(ilst.begin(), ilst.end(), 0, 42);
This call replaces all instances of 0 by 42
// use back_inserter to grow destination as needed
replace_copy(ilst.cbegin(), ilst.cend(),
back_inserter(ivec), 0, 42);
After this call,
ilst
is unchanged, and
ivec
contains a copy of
ilst
with the
exception that every element in ilst with the value 0 has the value 42 in ivec .
练习10.9:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
// print containers like vector,deque, list, etc.
template <typename Sequence> auto println(Sequence const& seq) -> std::ostream &
{
for (auto const& elem : seq) std::cout << elem << " ";
return std::cout << std::endl;
}
auto eliminate_duplicates(std::vector<std::string>& vs)-> std::vector<std::string> &
{
std::sort(vs.begin(), vs.end());
println(vs);
auto new_end = std::unique(vs.begin(), vs.end());
println(vs);
vs.erase(new_end, vs.end());
return vs;
}
int main()
{
std::vector<std::string> vs{ "a", "v", "a", "s", "v", "a", "a" };
println(vs);
println(eliminate_duplicates(vs));
system("pause");
return 0;
}
运行结果:
练习10.11:编写程序,使用stable_sort和is_shorter将传递给你的elimdups版本的vector排序。
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <list>
template<typename Sequence>inline std::ostream& println(Sequence const &seq)
{
for (auto const& elem : seq)std::cout << elem << " ";
std::cout << std::endl;
return std::cout;
}
inline bool is_shorter(std::string const&lhs, std::string const& rhs)
{
return lhs.size() < rhs.size();
}
void elimdups(std::vector<std::string>&vs)
{
std::sort(vs.begin(), vs.end());
auto new_end = std::unique(vs.begin(), vs.end());
vs.erase(new_end, vs.end());
}
int main()
{
std::vector<std::string>v = { "abc","acb","bac","bca","cab","cba","abc","acb","123","123","1234","1234","Hi" };
std::cout << "原始输入:";
println(v); std::cout << std::endl;
elimdups(v);
std::cout << "排序并去除相同元素:"; std::cout << std::endl;
println(v); std::cout << std::endl;
std::stable_sort(v.begin(), v.end(),is_shorter);//stable_sort保持等长元素的字典序
std::cout << "加入等长元素排序(练习10.11):"; std::cout << std::endl;
println(v); std::cout << std::endl;
system("pause");
return 0;
}
运行结果:
练习10.13:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
bool predicate(const std::string& s)
{
return s.size() >= 5;
}
int main()
{
auto v = std::vector<std::string>{ "a","as","aasss","aaaaassaa","aaaaaabba","aaa" };
auto pivot = std::partition(v.begin(), v.end(), predicate);//接受一个谓词,true在前,false在后,返回最后一个true元素之后的位置
for (auto it = v.cbegin(); it != pivot; ++it) std::cout << *it << " ";
std::cout << std::endl;
system("pause");
return 0;
}
练习10.16:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
void elimdups(std::vector<std::string>&vs)
{
std::sort(vs.begin(), vs.end());
auto new_end = std::unique(vs.begin(), vs.end());
vs.erase(new_end, vs.end());
}
void biggies(std::vector<std::string>&vs, std::size_t sz)
{
using std::string;
elimdups(vs);
//sort by size,but maintain alphabetical order for same size.
std::stable_sort(vs.begin(), vs.end(), [](string const & lhs, string const &rhs) {return lhs.size() < rhs.size(); });
//get an iterator to the first one whose size() is >=sz
auto wc = std::find_if(vs.begin(), vs.end(), [sz](string const &s) {return s.size() >= sz; });
//print the biggies
std::for_each(wc, vs.end(), [](const string&s) {std::cout << s << " "; });
}
int main()
{
std::vector<std::string> v{ "1234", "1234", "1234", "hi~","alan", "alan", "cp","a","adfdsgfsdgf" };
std::cout << " Ex 10.16:";
biggies(v, 3);
std::cout << std::endl;
system("pause");
return 0;
}
关于std::for_each的用法示例:
#include <vector>
#include <algorithm>
#include <iostream>
struct Sum {
Sum() { sum = 0; }
void operator()(int n) { sum += n; }
int sum;
};
int main()
{
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::cout << "before: ";
for (auto n : nums) {
std::cout << n << " ";
}
std::cout << '\n';
std::for_each(nums.begin(), nums.end(), [](int &n){ n++; });
Sum s = std::for_each(nums.begin(), nums.end(), Sum());
std::cout << "after: ";
for (auto n : nums) {
std::cout << n << " ";
}
std::cout << '\n';
std::cout << "sum: " << s.sum << '\n';
}
输出:
before: 3 4 2 9 15 267
after: 4 5 3 10 16 268
sum: 306
练习10.18/10.19:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
//! from ex 10.9
void elimdups(std::vector<std::string>& vs)
{
std::sort(vs.begin(), vs.end());
auto new_end = std::unique(vs.begin(), vs.end());
vs.erase(new_end, vs.end());
}
//! ex10.18
void biggies_partition(std::vector<std::string>& vs, std::size_t sz)
{
elimdups(vs);
auto pivot = partition(vs.begin(), vs.end(), [sz](const std::string& s) {
return s.size() >= sz;
});
for (auto it = vs.cbegin(); it != pivot; ++it) std::cout << *it << " ";
}
//! ex10.19
void biggies_stable_partition(std::vector<std::string>& vs, std::size_t sz)
{
elimdups(vs);
auto pivot =
stable_partition(vs.begin(), vs.end(),
[sz](const std::string& s) { return s.size() >= sz; });
for (auto it = vs.cbegin(); it != pivot; ++it) std::cout << *it << " ";
}
int main()
{
//! ex10.18
std::vector<std::string> v{"the", "quick", "red", "fox", "jumps",
"over", "the", "slow", "red", "turtle"};
std::cout << "ex10.18: ";
std::vector<std::string> v1(v);
biggies_partition(v1, 4);
std::cout << std::endl;
//! ex10.19
std::cout << "ex10.19: ";
std::vector<std::string> v2(v);
biggies_stable_partition(v2, 4);
std::cout << std::endl;
return 0;
}
//! output :
//!
// ex10.18: turtle jumps over quick slow
// ex10.19: jumps over quick slow turtle
值捕获:
void fcn1()
{
size_t v1 = 42;//局部变量
auto f = [v1] {return v1;};//将V1拷贝到名为f的可调用对象
v1 = 0;
auto j = f();//j为42;f保存了我们创建它时v1的拷贝
}
引用捕获:
void fcn2()
{
size_t v1 = 42;//局部变量
auto f2 = [&v1] {return v1;};//对象f2包含v1的引用
v1 = 0;
auto j = f2();//j为0;f2保存v1的引用,而非拷贝
}
Warning!当以引用方式捕获一个变量时,必须保证在lambda执行时变量是存在的。一般来说,我们应该尽量减少捕获的数据量,来避免潜在的捕获导致的问题。而且,如果可能的话,应该避免捕获指针或引用。
可变lambda
void fcn3()
{
size_t v1 = 42;//局部变量
auto f = [v1]()mutable {return ++v1; };//f可以改变它所捕获的变量的值
v1 = 0;
auto j = f();//j为43
}
void fcn4()
{
size_t v1 = 42;//局部变量,v1是一个非const变量的引用
auto f2 = [&v1] {return ++v1; };//可以通过f2中的引用来改变它
v1 = 0;
auto j = f2();//j为1
}
#include <iostream>
#include <string>
#include <cctype>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int>vi{ 1,2,3,-1,-2,-3,4,5,6,-4,-5,-6 };
transform(vi.begin(), vi.end(), vi.begin(), [](int i) {return i < 0 ? -i : i; });
for (auto ele : vi)
std::cout << ele << " ";
std::cout<<std::endl;
std::string s("hello,luwenwen!");
std::transform(s.begin(), s.end(), s.begin(), (int(*)(int))std::toupper);
std::cout << s;
std::cout << std::endl;
system("pause");
return 0;
}
使用尾置返回类型:
transform(vi.begin(), vi.end(), vi.begin(), [](int i)->int {if (i < 0)return-i; else return i; });
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using std::vector;
using std::string;
using std::cout;
using std::endl;
int main()
{
vector<string> words{ "cppprimer", "pezy", "learncpp","greater", "rewrite", "programmer" };
cout << std::count_if(words.cbegin(), words.cend(), [](const string& word) {return word.size() > 6;}) << std::endl;
system("pause");
}
练习10.21:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
int local_val = 7;// local int variable
auto decrement_to_zero = [&local_val]()
{
if (local_val == 0)
return true;
else
{
--local_val;
return false;
}
};
while (!decrement_to_zero()) cout << local_val << ",";
system("pause");
}
运行结果: