本文答案,部分参考于C++ Primer 习题集
前面章节的习题答案
9.1
(a)
按字典序插入到容器中,意味着进行插入排序操作,从而需要在容器内部频繁进行插入操作,vector在尾部之外的位置插入和删除元素很慢,deque 在头尾之外的位置插入和删除元素很慢.而list在任何位置插入和删除速度都很快.因此,这个任务选择list更为合适.当然,如果不是必须边读取单词边插入到容器中.可以使用vector,将读入的单词一次追加到尾部,读取完毕后,调用标准库到排序算法将到此重排为字典序.
(b)
由于需要在头,尾.分别进行插入,删除操作,因此将vecotor排除在外.
deque和list都可以达到很好的性能.如果还需要频繁进行随机访问,则deque更好.
©
由于整数占用空间很小.且快速的排序算法需频繁随机访问元素,将list排除在外,由于无需在头部进行插入,删除操作.因此使用vector即可.无须使用deque.
9.2
list<deque<int>> a;
9.3
两个迭代器begin和end必须指向同一个元素中的元素,或者是容器最后一个元素之后的位置,而且,对begin反复进行递增操作,可保证达到end,即end不在begin之前.
9.4
#include<iostream>
#include<list>
#include<deque>
#include<vector>
using namespace std;
bool Find(vector<int>::iterator beg, vector<int>::iterator end, int val);
int main() {
vector<int> a{ 1, 2, 3, 4, 5 };
bool result = Find(a.begin(), a.end(), 1);
if (result)
cout << "True";
else
cout << "False";
return 0;
}
bool Find(vector<int>::iterator beg, vector<int>::iterator end, int val) {
while (beg != end) {
if (val == *beg) {
return true;
}
beg++;
}
return false;
}
9.5
#include<iostream>
#include<list>
#include<deque>
#include<vector>
using namespace std;
vector<int>::iterator Find(vector<int>::iterator beg, vector<int>::iterator end, int val);
int main() {
vector<int> a{ 1, 2, 3, 4, 5 };
vector<int>::iterator result = Find(a.begin(), a.end(), 9);
if (result == a.end()) {
cout << "False";
}
else
cout << "True";
return 0;
}
vector<int>::iterator Find(vector<int>::iterator beg, vector<int>::iterator end, int val) {
while (beg != end) {
if (val == *beg) {
return beg;
}
beg++;
}
return end;
}
9.6
错误的地方在于.
没有理解这几种容器的结构特点
list容器是不支持 <运算的
list 容器只支持 递增,递减 == 和 != 运算.
9.7
vector<int>::iterator
9.8
list<string>::value_type
list<string>::reference
9.9
cbegin() 不可以执行写操作
9.10
v1 就是普通的int vector
v2 就是常量的int vector 不能执行写操作
it1是普通的迭代器 可以执行写操作
it2,it3,it4都是const 迭代器,都不能执行写操作
9.11
vector<int> a1;
vector<int> a2(10);
vector<int> a3 = a1; vector<int> a8(a1);
vector<int> a4{ 1,2,3,4 };vector<int> a5 = { 1,2,3,4 };
vector<int> a6(10, 0);
vector<int> a7(a6.begin(), a6.begin() + 3);
vector<int> a9(7);
9.12
前一种完整
后一种灵活
9.13
这是自己写的脑瘫方法
#include<iostream>
#include<list>
#include<deque>
#include<vector>
using namespace std;
int main(){
list<int> a{1,2,3,4,5};
vector<double> b;
for(auto t:a){
double x=(double)t;
b.push_back(x);
}
for(auto t:b){
cout<<t<<" "<<endl;
}
cout<<"---------分割线--------"<<endl;
vector<int> c{1,2,3,4,5};
vector<double> d;
for(auto t:c){
double x=(double)t;
d.push_back(x);
}
for(auto t:d){
cout<<t<<" "<<endl;
}
return 0;
}
这是教科书上的方法
#include<iostream>
#include<list>
#include<vector>
using namespace std;
int main(){
list <int> ilist={1,2,3,4,5,6,7};
vector<int> ivec={7,6,5,4,3,2,1};
vector<double> dvec(ilist.begin(),ilist.end());
vector<double> dvecl(ivec.begin(),ivec.end());
cout<<dvec.capacity()<<" "<<dvec.size()<<" "<<dvec[0]<<" "<<dvec[dvec.size()-1]<<endl;
cout<<dvecl.capacity()<<" "<<dvecl.size()<<" "<<dvecl[0]<<" "<<dvecl[dvecl.size()-1]<<endl;
return 0;
}
9.14
#include<iostream>
#include<list>
#include<vector>
#include<string>
using namespace std;
int main() {
vector<string> a;
list<const char* >b = {"I","will", "Become", "rich", "and", "Stronger", "and", "With", "abs" };
a.assign(b.begin(), b.end());
for(auto t:a){
cout<<t<<endl;
}
return 0;
}
9.15
#include<iostream>
#include<list>
#include<vector>
#include<string>
using namespace std;
int main() {
vector<int>a={1,2,3,4},b={2,3,4,5};
if(a>b)
cout<<"a>b";
else if(a<b)
cout<<"a<b";
else
cout<<"a=b";
return 0;
}
9.16
#include<iostream>
#include<list>
#include<vector>
#include<string>
using namespace std;
bool i_v_equal(vector<int> &ivec,list<int> &ilist){
//比较list和vector元素的个数
if(ilist.size()!=ivec.size())
return false;
auto lb=ilist.cbegin(); //list首元素
auto le=ilist.cend(); //list尾元素
auto vb=ivec.cbegin(); //vector首元素
for(;lb!=le;lb++,vb++)
if(*lb!=*vb)
return false;
return true;
}
int main(){
vector<int> ivec={1,2,3,4,5,6,7};
list<int> ilist={1,2,3,4,5,6,7};
list<int> ilist1={1,2,3,4,5};
list<int> ilist2={1,2,3,4,5,6,8};
list<int> ilist3={1,2,3,4,5,7,6};
cout<<i_v_equal(ivec,ilist)<<endl;
cout<<i_v_equal(ivec,ilist1)<<endl;
cout<<i_v_equal(ivec,ilist2)<<endl;
cout<<i_v_equal(ivec,ilist3)<<endl;
return 0;
}
9.17
① 容器类型必须相同,元素类型也必须相同
② 元素类型必须支持 < 运算符
9.18
#include<iostream>
#include<list>
#include<deque>
#include<vector>
#include<string>
using namespace std;
int main(){
string a;
deque <string> b;
while(cin>>a){
b.push_back(a);
}
deque<string>::iterator begin=b.begin();
deque<string>::iterator end=b.end();
while(begin!=end){
cout<<*begin<<endl;
++begin;
}
return 0;
}
9.19
#include<iostream>
#include<list>
#include<deque>
#include<vector>
#include<string>
using namespace std;
int main(){
string a;
list <string> b;
while(cin>>a){
b.push_back(a);
}
list<string>::iterator begin=b.begin();
list<string>::iterator end=b.end();
while(begin!=end){
cout<<*begin<<endl;
++begin;
}
return 0;
}
9.20
#include<iostream>
#include<list>
#include<deque>
#include<vector>
#include<string>
using namespace std;
int main(){
int a;
list <int> b;
while(cin>>a){
b.push_back(a);
}
list<int>::iterator begin=b.begin();
list<int>::iterator end=b.end();
deque<int> even; //偶数
deque<int> odd; //奇数
while(begin!=end){
cout<<*begin<<endl;
if(*begin%2==0){
even.push_back((*begin));
}
else
odd.push_back((*begin));
++begin;
}
cout<<" \n\n";
for(auto t:even){
cout<<t<<endl;
}
cout<<" \n\n";
for(auto t:odd){
cout<<t<<endl;
}
return 0;
}
9.21
效果其实是一样的。
但是在vector中,只有不是push_back 就是插入到尾部,
别的插入也都是可以的.
但是速度会很慢.
9.22
① 向一个vector,string,deque插入元素.会使现有指向容器的迭代器失效.
② 其次,练习如何利用insert返回的迭代器,使得在向容器插入元素后,仍能正确的在容器中遍历.
解法一:
#include<iostream>
#include<vector>
using namespace std;
int main(void){
vector<int> iv={1,1,2,1};
int some_val=1;
vector<int>::iterator iter=iv.begin();
int org_size=iv.size(),new_ele=0; //原大小和新元素个数
//每个循环步都重新计算 "mid",保证指向iv原中央元素
while(iter!=(iv.begin()+org_size/2+new_ele))
if(*iter==some_val){
iter=iv.insert(iter,2*some_val); //iter指向新元素
new_ele++;
iter++;iter++; //吧tier推进到旧元素的下一个位置
}else iter++; //简单推进iter
//用begin()获取vector首元素迭代器,遍历vector中的所有元素
for(iter=iv.begin();iter!=iv.end();iter++)
cout<<*iter<<endl;
return 0;
}
解法二:
#include<iostream>
#include<vector>
using namespace std;
int main(void){
vector<int> iv={1,1,2,1};
int some_val=1;
vector<int>::iterator iter=iv.begin();
int org_size=iv.size(),i=0; //原大小
//用循环变量控制循环次数
while(i<=org_size/2){
if(*iter==some_val){
iter=iv.insert(iter,2*some_val);
iter++;iter++;
}else iter++;
i++;
}
//用begin()获取vector首元素迭代器,遍历vector中的所有元素
for(iter=iv.begin();iter!=iv.end();iter++)
cout<<*iter<<endl;
return 0;
}
9.23
四个值都一样,都等于容器中第一个元素的指.
9.24
#include<iostream>
#include<vector>
using namespace std;
int main(void){
vector<int> a;
cout<<*a.begin();
cout<<a.front();
cout<<a[0];
cout<<a.at(0);
return 0;
}
结果如下:
9.25
① 当两个迭代器相等时
#include<iostream>
#include<vector>
using namespace std;
int main(void){
vector<int> a={1,2,3,4,5};
a.erase(a.begin(),a.begin());
for(auto i:a){
cout<<i<<endl;
}
return 0;
}
② 当elem1和elem2都是尾后迭代器时
会报错!!!
具体原因没有找到,我翻了一哈,官网的代码说明,没有找到解释,
但是在我自己的环境里写了,会报错.
③ 当elem2是尾后迭代器时
一样的报错.
9.26
#include<iostream>
#include<vector>
#include<list>
using namespace std;
int main(void){
int ia[]={0,1,1,2,3,5,8,13,21,55,89};
vector<int> iv;
list<int> il;
iv.assign(ia,ia+11);
il.assign(ia,ia+11);
vector<int>:: iterator iiv=iv.begin();
while(iiv!=iv.end()){
if(!(*iiv&1))
iiv=iv.erase(iiv);
else iiv++;
}
list<int>:: iterator iil=il.begin();
while(iil!=il.end()){
if(!(*iil&1))
iil=il.erase(iil);
else iil++;
}
for(auto i:iv){
cout<<i<<" ";
}
cout<<endl;
for(auto i:il){
cout<<i<<" ";
}
cout<<endl;
}
9.27
#include<iostream>
#include<vector>
#include<list>
#include<forward_list>
using namespace std;
int main(void){
forward_list<int> flst={0,1,2,3,4,5,6,7,8,9};
auto prev=flst.before_begin();
auto curr=flst.begin();
while(curr!=flst.end()){
if(*curr%2)
curr=flst.erase_after(prev);
else{
prev=curr;
++curr;
}
}
for(auto i:flst){
cout<<i<<" ";
}
cout<<endl;
}
9.28
#include<iostream>
#include<string>
#include<forward_list>
using namespace std;
void forwar_list_insert(forward_list<string> &, string, string);
int main(void) {
forward_list<string> flst = { "Money","Power","Girl","Desire" };
forwar_list_insert(flst, "Power", "Wife");
//输出
for (auto i : flst) {
cout << i << " ";
}
cout << endl;
}
void forwar_list_insert(forward_list<string>& flst, string find_string, string insert_string) {
auto curr = flst.begin();
auto prev = flst.before_begin();
while (curr != flst.end()) {
if (*curr == find_string) {
flst.insert_after(curr, insert_string);
return;
}
else {
prev = curr;
++curr;
}
}
flst.insert_after(prev, insert_string);
return;
}
9.29
会自动填充75个值,值的内容要看vec的类型
resize(10) 会删除后面的90个元素
9.30
对于元素是类类型,则单参数resize版本要求该类型必须提供一个默认构造函数
9.31
forward_list的改法
#include<iostream>
#include<string>
#include<forward_list>
#include<list>
using namespace std;
int main(void) {
forward_list<int> llist = { 0,1,2,3,4,5,6,7,8,9 };
auto iter = llist.begin();
auto iter_before = llist.before_begin();
while (iter != llist.end()) {
if (*iter % 2 == 0) {
iter=llist.erase_after(iter_before);
}
else {
llist.insert_after(iter_before, *iter);
iter_before = iter;
++iter;
}
}
for (auto i : llist) {
cout << i << " ";
}
cout << endl;
}
list的代码
#include<iostream>
#include<string>
#include<forward_list>
#include<list>
using namespace std;
int main(void) {
list<int> llist = { 0,1,2,3,4,5,6,7,8,9 };
auto iter = llist.begin();
while (iter != llist.end()) {
if (*iter % 2 == 0) {
iter=llist.erase(iter);
}
else {
iter=llist.insert(iter, *iter);
++iter;
++iter;
}
}
for (auto i : llist) {
cout << i << " ";
}
cout << endl;
}
9.32
不建议这样写,因为在表示式中调用这个变量,而且结果和中间都有的话,其实是看编译器的.这样写有很大机率出错.
9.33
插入元素会让begin()失效
如果不赋予的话,这个代码会报错.
9.34
会陷入死循环中
代码如下:
#include<iostream>
#include<string>
#include<forward_list>
#include<list>
using namespace std;
int main(void) {
list<int> llist = { 0,1,2,3,4,5,6,7,8,9 };
auto iter = llist.begin();
while (iter != llist.end()) {
if (*iter % 2 )
iter=llist.insert(iter, *iter);
++iter;
}
for (auto i : llist) {
cout << i << " ";
}
cout << endl;
}
9.35
capacity返回已经为vector分配了多大内存空间(单位是元素大小),也就是在不分配新空间的情况下,容器可以保存多少个元素,而size则返回容器当前已经保存了多少个元素
9.36
不可能的
9.37
list是链表,当有新元素加入时,会从内存空间分配一个新节点保存它,当从链表删除元素时,该节点占用的内存空间会被立即释放,因此,一个链表占用的内存空间总是与它保存的元素所需空间相等(换句话说,capacity总是等于size)
而array是固定大小数组,内存一次性分配,大小不变,不会变化.
因此他们均不需要capacity.
9.38
#include<iostream>
#include<string>
#include<forward_list>
#include<list>
#include<vector>
using namespace std;
int main(void) {
vector<int> vlist={0,1,2,3,4,5,6,7,8,9};
cout<<"size:"<<vlist.size()<<endl;
cout<<"cap:"<<vlist.capacity()<<endl;
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
cout<<"size:"<<vlist.size()<<endl;
cout<<"cap:"<<vlist.capacity()<<endl;
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
vlist.push_back(1);
cout<<"size:"<<vlist.size()<<endl;
cout<<"cap:"<<vlist.capacity()<<endl;
}
结果如下:
9.39
一开始就开辟了1024个svec的空间 有1024个string
默认初始化为空串
然后再输入若干字符串
然后再调整大小为
输入大小+输入大小的一半=输入大小的1.5倍
9.40
比384多
比768多
比1500多
比1572多
答案上的解释(我没有试过)
384
768
2048
2048
9.41
#include<iostream>
#include<string>
#include<forward_list>
#include<list>
#include<vector>
using namespace std;
int main(void) {
vector<char> vc={'H','e','l','l','o'};
string s(vc.data(),vc.size());
cout<<s<<endl;
}
9.42
#include<iostream>
#include<string>
#include<forward_list>
#include<list>
#include<vector>
using namespace std;
void input_string(string &s){
s.reserve(100);
char c;
while(cin>>c)
s.push_back(c);
}
int main(void) {
string s;
input_string(s);
cout<<s<<endl;
return 0;
}
9.43
#include<iostream>
#include<string>
#include<forward_list>
#include<list>
#include<vector>
using namespace std;
void replace_string(string &s,const string &oldVal,const string &newVal){
auto l=oldVal.size();
if(!l)
return ; //要查找的字符串为空的情况
auto iter=s.begin();
while(iter<=s.end()-1){ //末尾少于oldVal长度的部分无须检查
auto iter1=iter;
auto iter2=oldVal.begin();
//s中iter开始的子串必须每个字符都与oldVal相同
while(iter2!=oldVal.end()&& *iter1==*iter2){
++iter1;
++iter2;
}
if(iter2==oldVal.end()){
iter=s.erase(iter,iter1);
if(newVal.size()){
iter2=newVal.end();
do{
iter2--;
iter=s.insert(iter,*iter2);
}while(iter2>newVal.begin());
}
iter+=newVal.size();
}else iter++;
}
}
int main(){
string s="tho thru tho!";
replace_string(s,"thru","throught");
cout<<s<<endl;
}
9.44
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void replace_string(string &s,const string &oldVal,const string &newVal){
int p=0;
while(p=s.find(oldVal,p)!=string::npos){
s.replace(p,oldVal.size(),newVal);
p+=newVal.size();
}
}
int main(){
string s="tho thru tho!";
replace_string(s,"thru","throught");
cout<<s<<endl;
}
9.45
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void name_string(string &name,const string &prefix,const string &suffix){
name.insert(name.begin(),1,' ');
name.insert(name.begin(),prefix.begin(),prefix.end());
name.append(" ");
name.append(suffix.begin(),suffix.end());
}
int main(){
string s="James Bond";
name_string(s,"Mr.","II");
cout<<s<<endl;
}
9.46
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void name_string(string &name,const string &prefix,const string &suffix){
name.insert(0," ");
name.insert(0,prefix);
name.insert(name.size()," ");
name.insert(name.size(),suffix);
}
int main(){
string s="James Bond";
name_string(s,"Mr.","II");
cout<<s<<endl;
}
9.47
使用find_first_of
#include<iostream>
#include<vector>
#include<string>
using namespace std;
int main(){
string index="ab2c3d7R4E6";
index.find_first_of("1");
vector<char> Num={'0','1','2','3','4','5','6','7','8','9'};
for(int i=0;i<=9;i++){
if(index.find_first_of(Num[i])!=string::npos){
cout<<Num[i]<<"!"<<endl;
}
}
for(int i=0;i<26;++i){
if(index.find_first_of(char(i+65))!=string::npos){
cout<<char(i+65)<<"!"<<endl;
}
else if( index.find_first_of(char(i+97))!=string::npos){
cout<<char(i+97)<<"!"<<endl;
}
}
}
使用not
#include<iostream>
#include<string>
using namespace std;
void find_not_char(string &s,const string &chars){
cout<<"在"<<s<<"中查找不在"<<chars<<"中字符"<<endl;
string::size_type pos=0;
while((pos=s.find_first_not_of(chars,pos))!=string::npos){
cout<<"pos:"<<pos<<",char: "<<s[pos]<<endl;
++pos;
}
}
int main(){
string s="ab2c3d7R4E6";
cout<<"查找所有数字"<<endl;
find_not_char(s,"abcdefghijkmnopqrstuvwxyz"\
"ABCDEFGHIJKMNOPQRSTUVWXYZ");
cout<<endl<<"查找所有数字"<<endl;
find_not_char(s,"0123456789");
return 0;
}
9.48
会返回
string::npos
因为找不到
9.49
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void find_longest_word(ifstream &in){
string s,longest_word;
int max_length=0;
while(in>>s){
if(s.find_first_of("bdfghjklpqty")!=string::npos)
continue;
cout<<s<<" ";
if(max_length<s.size()){
max_length=s.size();
longest_word=s;
}
}
cout<<endl<<"最长的字符串:"<<longest_word<<endl;
}
int main(int argc,char *argv[]){
ifstream in(argv[1]);
if(!in){
cerr<<"无法打开输入文件"<<endl;
return -1;
}
find_longest_word(in);
return 0;
}
9.50
整数
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
using namespace std;
int main(){
vector<string> index={"1","2","3","4","5","6"};
int sum=0;
for(auto i:index){
sum+=stoi(i);
}
cout<<sum<<endl;
return 0;
}
21
请按任意键继续. . .
浮点数
#include<iostream>
#include<string>
#include<vector>
#include<fstream>
using namespace std;
int main(){
vector<string> index={"1.90","2.85","3","4","5","6"};
double sum=0;
for(auto i:index){
sum+=stod(i);
}
cout<<sum<<endl;
return 0;
}
22.75
请按任意键继续. .