C++Primer_课后习题第九章

本文答案,部分参考于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
请按任意键继续. .

9.51

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

9.52

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

导图

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Huangpengyu123/article/details/107773488