C++ Primer 第 5 版 第 3 章习题答案

3.2

#include<iostream>
#include <string>

using std::cin, std::cout, std::string, std::getline,std::endl;

int main() {
    //一次读入一整行
//    string buffer_words{0};
//    while (getline(cin, buffer_words)) {
//        cout << "输入:" << buffer_words << endl;
//    }

    //一次读入一个词
    string buffer_word{0};
    while (cin>>buffer_word){
        cout<< "输入:" <<buffer_word<<endl;
    }
    return 0;
}

3.3

标准库 string 的输入运算符自动忽略字符串开头的空白(包括空格符、换行符、制表符等),从第一个真正的字符开始读起,直到遇见下一处空白为止。

如果希望在最终的字符串中保留输入时的空白符,应该使用 getline 函数代替原来的 >> 运算符,getline 从给定的输入流中读取数据,直到遇到换行符为止,此时换行符也被读取进来,但是并不存储在最后的字符串中

3.4

输出较大的字符串

#include<iostream>
#include <string>

using std::cin, std::cout, std::string, std::getline,std::endl;

int main() {
    string str1,str2;
    cin>>str1>>str2;
    if(str1>str2){
        cout<< str1 <<endl;
    }else if(str1<str2){
        cout<< str2 <<endl;
    } else{
        cout<< "相等" <<endl;
    }
    return 0;
}

输出长度较长的字符串

#include<iostream>
#include <string>

using std::cin, std::cout, std::string, std::getline, std::endl;

int main() {
    string str1, str2;
    cin >> str1 >> str2;
    auto slen1 = str1.size();
    auto slen2 = str2.size();
    if (slen1 == slen2)cout << "长度相等" << endl;
    else if (slen1 > slen2)cout << str1 << "-长度更长" << endl;
    else cout << str2 << "-长度更长" << endl;
    return 0;
}

3.5

连接多个字符串的程序如下所示:

#include<iostream>
#include <string>

using std::cin, std::cout, std::string, std::getline, std::endl;

int main() {
    cout<<"请输入字符串:";
    string buf,result;
    while (cin>>buf){
        result+=buf;
        char flag;
        cout<< "是否继续输入y/n";
        cin>>flag;
        if(flag=='n'||flag=='N'){
            break;
        } else{
            cout<<"请输入字符串:";
        }
    }
    cout<< result <<endl;
    return 0;
}

连接多个字符串并以空格分隔的程序如下所示:

#include<iostream>
#include <string>

using std::cin, std::cout, std::string, std::getline, std::endl;

int main() {
    cout<<"请输入字符串:";
    string buf,result;
    while (cin>>buf){
        result+=buf+" ";
        char flag;
        cout<< "是否继续输入y/n";
        cin>>flag;
        if(flag=='n'||flag=='N'){
            break;
        } else{
            cout<<"请输入字符串:";
        }
    }
    cout<< result <<endl;
    return 0;
}

3.6

字符串内所有字符用X替换

#include<iostream>
#include <string>

using namespace std;

int main() {
    string s{"xadsadasdq2eqdasc"};
    for (auto &item: s)
        item='X';
    cout<< s <<endl;
    return 0;
}

3.7

就本题而言,将循环控制变量的类型设为 char 不会对程序运行结果造成影响,因为我们使用 auto 自动推断字符串 s 的元素类型,结果同样是 char。

#include<iostream>
#include <string>

using namespace std;

int main() {
    string s{"xadsadasdq2eqdasc"};
    for (char &item: s)
        item='X';
    cout<< s <<endl;
    return 0;
}

3.8

while循环写一遍

#include<iostream>
#include <string>

using namespace std;

int main() {
    string s{"xadsadasdq2eqdasc"};
    int index{0};
    while(s[index]!='\0')
        s[index++] = 'X';
    cout<< s <<endl;
    return 0;
}

3.9

string s;
cout<<s[0];

该程序的原意是输出字符串 s 的首字符,但程序是错误的。因为初始状态下没有给 s 赋任何初值,所以字符串 s 的内容为空,当然也就不存在首字符,下标 0 是非法的。

但是在某些编译器环境中,上述语句并不会引发编译错误。

3.10

删除标点符号

#include<iostream>
#include <string>
#include<cctype>
using namespace std;

int main() {
    string s;
    cout<< "请输入字符串:";
    cin>>s;
    auto len=s.size();
    for (int i = 0; i < len; ++i) {
        if(ispunct(s[i])){
            s.erase(i,1);
        }
    }
    cout<< s <<endl;
    return 0;
}

3.11

判断是否合法

const string s = "Keep out!";
for(auto &c:s){/*...*/}

合法,c的类型是const char&

3.12

(a)是正确的,定义了一个名为 ivec 的 vector 对象,其中的每个元素都是 vector 对象。

(b)是错误的,svec 的元素类型是 string,而 ivec 的元素类型是 int,因此不能使用 ivec 初始化 svec。

(c)是正确的,定义了一个名为 svec 的 vector 对象,其中含有 10 个元素,每个元素都是字符串 null。

3.13

(a)的元素数量为 0;

(b)的元素数量为 10,每一个元素都被初始化为 0;

(c)的元素数量为 10,每一个元素都被初始化为 42;

(d)的元素数量为 1,元素的值为 10;

(e)的元素数量为 2,两个元素的值分别是 10 和 42;

(f)的元素数量为 10,每一个元素都被初始化为空串;

(g)的元素数量为 10,每一个元素都被初始化为"hi"。

3.14

#include<iostream>
#include <vector>
#include<cctype>

using namespace std;

int main() {
   vector<int>v;
   int i{0};
   char flag{'n'};
   while(cin>>i){
       v.push_back(i);
       cout<< "是否继续输入y/n" <<endl;
       cin>>flag;
       if(flag=='n'||flag=='N')break;
   }
    for (const int &j : v) {
        cout<< j <<endl;
    }
    return 0;
}

3.15

#include<iostream>
#include <vector>
#include<cctype>

using namespace std;

int main() {
   vector<string>v;
   string i{0};
   char flag{'n'};
   while(cin>>i){
       v.push_back(i);
       cout<< "是否继续输入y/n" <<endl;
       cin>>flag;
       if(flag=='n'||flag=='N')break;
   }
    for (const string &j : v) {
        cout<< j <<endl;
    }
    return 0;
}

3.16

如上

3.17

#include<iostream>
#include <vector>
#include<cctype>

using namespace std;

int main() {
    vector<string>v;
    string s;
    int sum{0};
    cout<< "请输入要输入词的个数:";
    cin>>sum;
    for (; sum>0;--sum) {
        cin>>s;
        s[0]= toupper(s[0]);
        v.push_back(s);
    }
    for (auto &item: v) {
        cout<< item <<endl;
    }

    return 0;
}

3.18

不合法

vector<int> ivec;
ivec.push_back(42);

3.19

vector<int>v1(10,42);
vector<int>v2{42,42,42,42,42,42,42,42,42,42};
vector<int>v3;
for (int i = 0; i < 10; i++)
    v3.push_back(42);

3.20

求相邻元素和的程序如下所示:

#include<iostream>
#include <vector>
#include<cctype>

using namespace std;

int main() {
    vector<int>v;
    int num;
    int sum{0};
    cout<< "请输入要输入整数的个数:";
    cin>>sum;
    for (; sum>0;--sum) {
        cin>>num;
        v.push_back(num);
    }
    auto len = v.size();
    for (int i = 0; i < len-1; ++i) {
        cout<< v[i]+v[i+1] <<endl;
    }

    return 0;
}

求首尾元素和的程序如下所示:

#include<iostream>
#include <vector>
#include<cctype>

using namespace std;

int main() {
    vector<int>v;
    int num;
    int sum{0};
    cout<< "请输入要输入整数的个数:";
    cin>>sum;
    for (; sum>0;--sum) {
        cin>>num;
        v.push_back(num);
    }
    auto len = v.size();
    for (int i = 0; i < len/2; ++i) {
        cout<< v[i]+v[len-1-i] <<endl;
    }
    if(len % 2 != 0){
        cout<< v[len/2] <<endl;
    }
    return 0;
}

3.21

#include<iostream>
#include <vector>
#include<cctype>

using namespace std;

int main() {
    vector<int>v;
    int num;
    int sum{0};
    cout<< "请输入要输入整数的个数:";
    cin>>sum;
    for (; sum>0;--sum) {
        cin>>num;
        v.push_back(num);
    }
    for (auto normalIterator = v.begin(); normalIterator != v.end(); ++normalIterator) {
        cout<< *normalIterator <<endl;
    }
    return 0;
}

3.22

#include<iostream>
#include <vector>
#include<cctype>

using namespace std;

int main() {
    vector<string>v;
    string s;
    while (getline(cin,s)){
        if(s!="EOF"||s!="eof")v.push_back(s);
        else break;
    }
    for (auto it = v.begin(); it != v.end(); ++it) {
        for (auto it2 = it->begin(); it2 != it->end(); ++it2) {
            *it2 = ::toupper(*it2);
        }
    }
    for (auto &item: v) {
        cout<< item <<endl;
    }
    return 0;
}

3.23

#include<iostream>
#include <vector>
#include<cctype>
#include<ctime>
using namespace std;

int main() {
    vector<int>v(10);
    srand(time(nullptr));
    for (int i = 0; i < 10; ++i)
        v[i]=(rand()%100);
    cout<< "原先:" <<endl;
    for (auto item = v.begin(); item != v.end(); ++item)
        cout<< *item <<" ";
    for (auto it = v.begin(); it != v.end(); ++it)
        (*it)*=2;
    cout<<"\n";
    cout<< "×2后:" <<endl;
    for (auto item = v.begin(); item != v.end(); ++item)
        cout<< *item <<" ";
    return 0;
}

3.24

#include<iostream>
#include <vector>
#include<cctype>
#include<ctime>
using namespace std;

int main() {
    vector<int>v;
    int number{0};
    cout<< "请输入要输入几个数字:";
    cin>>number;
    v.reserve(number);
    for (int i = 0; i < number; ++i) {
        int num{0};
        cout<<"请输入数字:";
        cin>>num;
        v.push_back(num);
    }
    //相邻之和
    for (auto it = v.begin(); it != v.end()-1; ++it)
        cout<< *it+*(it+1) <<endl;
    //头尾之和
    auto itb = v.begin();
    auto ite = v.end();
    for (auto it = v.begin(); it !=itb+(ite-itb)/2; ++it) {
        cout<< *it+ *(itb+(ite-it)-1)<<endl;
    }
    if((ite-itb)%2!=0)cout<< *(itb+((ite-itb)/2)) <<endl;
    return 0;
}

3.25

#include <iostream>
#include <vector>

using namespace std;

int main() {
    // 该 vector 对象记录各分数段的人数,初始值为 0
    vector<unsigned> vUS(11);
    auto it = vUS.begin();
    int iVal;
    cout << "请输入一组成绩(0 ~ 100):" << endl;
    while (cin >> iVal)
        if (iVal < 101)             // 成绩应在合理范围之内
            ++*(it + iVal / 10);    // 利用迭代器定位到对应的元素,加 1
    cout << "您总计输入了 " << vUS.size() << " 个成绩" << endl;
    cout << "各分数段的人数分布是(成绩从低到高):" << endl;
    // 利用迭代器遍历 vUS 的元素并逐个输出
    for (; it != vUS.end(); it++) {
        cout << *it << " ";
    }
    cout << endl;

    return 0;
}

3.26

因为迭代器的加法不存在,所以 mid = (beg + end) / 2; 不合法。mid = beg + (end - beg) / 2; 的含义是,先计算 end - beg 的值得到容器中的元素个数,然后控制迭代器与整数( (end - beg) / 2 )进行运算,从开始处向右移动二分之一容器的长度,从而定位到容器中间的元素。

3.27

(a)是非法的,buf_size 是一个普通的无符号数,不是常量,不能作为数组的维度。

(b)是合法的,4*7-14 = 14 是一个常量表达式。

(c)是非法的,txt_size() 是一个普通的函数调用,没有被定义为 constexpr,不能作为数组的维度。

(d)是非法的,当使用字符串初始化字符数组时,默认在尾部添加一个空字符 \0,算上这个符号该字符串共有 12 个字符,但是字符数组 st 的维度只有 11,无法容纳题目中的字符串。

需要指出的是,在某些编译器环境中,上面的个别语句被判定为合法,这是所谓的编译器扩展。不过一般来说,建议读者避免使用非标准特性,因为含有非标准特性的程序很可能在其他编译器上失效。

3.28

对于string有默认构造函数,无论是在函数体内部还是在函数体外部,默认初始化为空串

对于int,在函数体内部ia2将不被初始化,如果程序试图拷贝或输出未初始化的变量,将遇到未定义的奇异值。 在函数体外部ia2将被初始化为0

3.29

数组与 vector 的相似之处是都能存放类型相同的对象,且这些对象本身没有名字,需要通过其所在位置访问。

数组与 vector 的最大不同是,数组的大小固定不变,不能随意向数组中增加额外的元素,虽然在某些情境下运行时性能较好,但是与 vector 相比损失了灵活性。

具体来说,数组的维度在定义时已经确定,如果我们想更改数组的长度,只能创建一个更大的新数组,然后把原数组的所有元素复制到新数组中去。数组也无法像 vector 那样使用 size 函数直接获取数组的维度。如果是字符数组,可以调用 strlen 函数得到字符串的长度;如果是其他数组,只能使用 sizeof(array) / sizeof(array[0]) 的方式计算数组的维度。

3.30

数组下标从0开始,上述出现了 数组下标越界的现象

3.31

#include<iostream>

using namespace std;

int main() {
    int arr[10]={0};
    for (int i = 0; i < 10; ++i) {
        arr[i] = i;
    }

    return 0;
}

3.32

数组拷贝

#include<iostream>

using namespace std;

int main() {
    int arr[10]={0};
    for (int i = 0; i < 10; ++i) {
        arr[i] = i;
    }

    int arr2[10]={0};
   ::memcpy(arr2,arr,10*sizeof(int));
    for (auto item: arr2) {
        cout<< item <<endl;
    }
    return 0;
}

vector实现

#include<iostream>
#include <vector>

using namespace std;

int main() {
    vector<int>v1(10);
    for (int i = 0; i < 10; ++i)
        v1[i] = i;
    vector<int>v2(v1);
    for (auto item: v1) {
        cout<< item <<endl;
    }
    return 0;
}

3.33

如果不初始化 scores,则该数组会含有未定义的数值,这是因为 scores 是定义在函数内部的整型数组,不会执行默认初始化。

3.34

如果 p1 和 p2 指向同一个数组中的元素,则该条语句令 p1 指向 p2 原来所指向的元素。

从语法上来说,即使 p1 和 p2 指向的元素不属于同一个数组,但只要 p1 和 p2 的类型相同,该语句也是合法的。

但是如果p1和p2指向元素的类型不同,那么就是非法的

3.35

int main() {
    int arr[10];
    int *p = arr;
    for (int i = 0; i < 10; ++i) {
        *(p+i)=0;
    }
    return 0;
}

3.36

#include<iostream>
#define MAXLEN 5

using namespace std;

int main() {
    int arr1[MAXLEN]={1,1,2,3,4},
    arr2[MAXLEN]={10,1,2,3,4};
    bool isEqual{true};
    for (int i = 0; i < MAXLEN; ++i) {
        if(arr1[i]!=arr2[i]){
            isEqual= false;
            break;
        }
    }
    if(isEqual)cout<< "两个数组相等" <<endl;
    else cout<< "两个数组不相等" <<endl;
    return 0;
}

3.37

是一个字符数组而不是字符串,会一直寻找 直至找到字符串的结尾标志

3.38

指针的值是它所指对象的内存地址,如果我们把两个指针加在一起,就是试图把内存中两个对象的存储地址加在一起,这显然是没有任何意义的。与之相反,指针的减法是有意义的。如果两个指针指向同一个数组中的不同元素,则它们相减的结果表征了它们所指的元素在数组中的距离。

3.39

比较string

#include <iostream>
#include <string>

using namespace std;

int main() {
    string str1, str2;
    cout << "请输入两个字符串:" << endl;
    cin >> str1 >> str2;

    if (str1 > str2)
        cout << "第一个字符串大于第二个字符串" << endl;
    else if (str1 < str2)
        cout << "第一个字符串小于第二个字符串" << endl;
    else
        cout << "两个字符串相等" << endl;

    return 0;
}

比较c语言风格的字符串

#include <iostream>
#include <cstring>

using namespace std;

int main() {
    char str1[80], str2[80];
    cout << "请输入两个字符串:" << endl;
    cin >> str1 >> str2;

    // 利用 cstring 头文件中定义的 strcmp 函数比较大小
    auto result = strcmp(str1, str2);
    if (result > 0)
        cout << "第一个字符串大于第二个字符串" << endl;
    else if (result < 0)
        cout << "第一个字符串小于第二个字符串" << endl;
    else
        cout << "两个字符串相等" << endl;

    return 0;
}

3.40

#include <iostream>
#include <cstring>

using namespace std;

int main() {
    char str1[] = "Welcome to ";
    char str2[] = "C++ family!";
    // 利用 strlen 函数计算两个字符串的长度,并求得结果字符串的长度
    char result[size(str1) + size(str2) - 1];
    // char result[strlen(str1) + strlen(str2) + 1];    // 也可

    strcpy(result, str1);       // 把第一个字符串拷贝到结果字符串中
    strcat(result, str2);       // 把第二个字符串拼接到结果字符串中

    cout << "第一个字符串是:" << str1 << endl;
    cout << "第二个字符串是:" << str2 << endl;
    cout << "拼接后的字符串是:" << result << endl;

    return 0;
}

3.41

#include<iostream>
#include <vector>

using namespace std;

int main() {
    int a[]={1,2,3,4,5,6};
    vector<int>v(begin(a), end(a));
    for (auto &item: a) {
        cout<< item <<endl;
    }
    return 0;
}

3.42

#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>

using namespace std;

int main() {
    const int sz = 10;                  // 常量 sz 作为 vector 对象的容量
    vector<int> vInt;
    srand((unsigned) time(NULL));       // 生成随机数种子
    cout << "vector 对象的内容是:" << endl;
    // 利用 for 循环遍历 vector 对象的每个元素
    for (int i = 0; i != sz; i++) {
        vInt.push_back(rand() % 100);   // 生成一个 100 以内的随机数
        cout << vInt[i] << " ";
    }
    cout << endl;

    auto it = vInt.cbegin();
    int a[vInt.size()];
    cout << "数组的内容是:" << endl;
    // 利用范围 for 循环遍历 vector 的每个元素
    for (auto &val : a) {
        val = *it;
        cout << val << " ";
        it++;
    }
    cout << endl;

    return 0;
}

3.43

#include<iostream>


using namespace std;

int main() {
    int ia[3][4] = {
            {0, 1, 2, 3},
            {4, 5, 6, 7},
            {8, 9, 10, 11},
    };
    范围for
    for (int (&pInt)[4]: ia) {
        for (int &i: pInt) {
            cout << i << " ";
        }
        cout << endl;
    }

    //普通for 下标
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 4; ++j) {
            cout << ia[i][j] << " ";
        }
        cout << endl;
    }

    //普通for 指针
    for (int (*p)[4] = ia; p != ia+3; ++p) {
        for (int *q = *p; q != *p+4; ++q) {
            cout << *q << " ";
        }
        cout << endl;
    }

    return 0;
}

3.44

#include <iostream>

using namespace std;
using int_array = int[4];

int main() {
    int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    cout << "利用范围 for 语句输出多维数组的内容:" << endl;
    for (int_array &row : ia) {
        for (int &col : row)
            cout << col << " ";
        cout << endl;
    }

    cout << "利用普通 for 语句和下标运算符输出多维数组的内容:" << endl;
    for (int i = 0; i != 3; i++) {
        for (int j = 0; j != 4; j++)
            cout << ia[i][j] << " ";
        cout << endl;
    }

    cout << "利用普通 for 语句和指针输出多维数组的内容:" << endl;
    for (int_array *p = ia; p != ia + 3; p++) {
        for (int *q = *p; q != *p + 4; q++)
            cout << *q << " ";
        cout << endl;
    }

    return 0;
}

3.45

#include <iostream>

using namespace std;

int main() {
    int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    cout << "利用范围 for 语句输出多维数组的内容:" << endl;
    for (auto &row : ia) {
        for (auto &col : row)
            cout << col << " ";
        cout << endl;
    }

    cout << "利用普通 for 语句和下标运算符输出多维数组的内容:" << endl;
    for (auto i = 0; i != 3; i++) {
        for (auto j = 0; j != 4; j++)
            cout << ia[i][j] << " ";
        cout << endl;
    }

    cout << "利用普通 for 语句和指针输出多维数组的内容:" << endl;
    for (auto p = ia; p != ia + 3; p++) {
        for (auto q = *p; q != *p + 4; q++)
            cout << *q << " ";
        cout << endl;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值