C++ primer(第五版)第3章习题答案

时间:2022-10-13 00:14:37

第三章 字符串,向量和数组

3.1

Part A

// use `using` for 1.4.1

#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int main()
{
    int sum = 0, val = 1;
    // keep executing the while as long as val is less than or equal to 10
    while (val <= 10) {
        sum += val;
        ++val;
    }
    cout << "Sum of 1 to 10 inclusive is " << sum << endl;
    return 0;

Part B

#include <iostream>
#include <string>

using std::string;
using std::cin;
using std::cout;
using std::endl;
using std::cerr;

struct Sales_data {
string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};

int main()
{
    Sales_data data1, data2;

    // code to read into data1 and data2
    double price = 0; // price per book, used to calculate total revenue

    // read the first transactions: ISBN, number of books sold, price per book
    cin >> data1.bookNo >> data1.units_sold >> price;
    // calculate total revenue from price and units_sold
    data1.revenue = data1.units_sold * price;

    // read the second transaction
    cin >> data2.bookNo >> data2.units_sold >> price;
    data2.revenue = data2.units_sold * price;

    // code to check whether data1 and data2 have the same ISBN
    //        and if so print the sum of data1 and data2
    if (data1.bookNo == data2.bookNo) {
        unsigned totalCnt = data1.units_sold + data2.units_sold;
        double totalRevenue = data1.revenue + data2.revenue;

        // print: ISBN, total sold, total revenue, average price per book
        cout << data1.bookNo << " " << totalCnt << " " << totalRevenue << " ";
        if (totalCnt != 0)
            cout << totalRevenue / totalCnt << endl;
        else
            cout << "(no sales)" << endl;

        return 0; // indicate success
    }
    else { // transactions weren't for the same ISBN
        cerr << "Data must refer to the same ISBN" << endl;
        return -1; // indicate failure
    }
}


3.2

part  A

// read the standard input a line at a time.
#include <iostream>
#include <string>

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

int main()
{
    string input;
    while (getline(cin, input)) cout << input << endl;

    return 0;
}

part B

// read the standard input a word at a time
#include <iostream>
#include <string>

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

int main()
{
    string word;
    while (cin >> word) cout << word << endl;

    return 0;
}


3.3

在执行读取操作时,string对象会自动忽略开头的空白(即空格符,换行符,制表符等),并从一个真正的字符开始读起,直到遇见下一处空白为止。

getline函数从给定的输入流读入内容,直到遇到换行符,然后把所读的内容存入到那个string对象中去(不存换行符)。


3.4

part A

// read two strings and report whether the strings are equal
// If not, report which of the two is larger.
#include <iostream>
#include <string>

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

int main()
{
    string str1, str2;
    while (cin >> str1 >> str2) {
        if (str1 == str2)
            cout << "The two strings are equal." << endl;
        else
            cout << "The larger string is " << ((str1 > str2) ? str1 : str2);
    }

    return 0;
}

part B

    
// read two strings and report whether the strings have the same length
// If not, report which is longer
#include <iostream>
#include <string>

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

int main()
{
    string str1, str2;
    while (cin >> str1 >> str2) {
        if (str1.size() == str2.size())
            cout << "The two strings have the same length." << endl;
        else
            cout << "The longer string is "
                 << ((str1.size() > str2.size()) ? str1 : str2);
    }

    return 0;
}


3.5

part A

// read strings from the standard input, concatenating what is read into one
// large string.
// Print the concatenated string.
#include <iostream>
#include <string>

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

int main()
{
    string largeStr;
    string str;
    while (cin >> str) {
        largeStr += str;
    }

    cout << "The concatenated string is " << largeStr << endl;

    return 0;
}

part B

// separate adjacent input strings by a space.
#include <iostream>
#include <string>

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

int main()
{
    string largeStr;
    string str;
    while (cin >> str) {
        if (largeStr.empty())
            largeStr += str;
        else
            largeStr += " " + str;
    }

    cout << "The concatenated string is " << largeStr << endl;

    return 0;
}


3.6

// Use a range for to change all the characters in a string to X.

#include <iostream>
#include <string>

using std::string;
using std::cout;
using std::endl;

int main()
{
    string str("a simple string");
    for (auto& c : str) c = 'X';
    cout << str << endl;

    return 0;
}


3.7

没有不同,通过使用auto关键字让编译器来决定变量c的类型,这里c的类型是char。


3.8

// Use a range for to change all the characters in a string to X.

#include <iostream>
#include <string>

using std::string;
using std::cout;
using std::endl;

int main()
{
    string str("a simple string");
    // use while
    decltype(str.size()) i = 0;
    while (i < str.size()) {
        str[i] = 'X';
        ++i;
    }
    cout << str << endl;

    // use traditional for
    for (i = 0; i < str.size(); ++i) str[i] = 'Y';
    cout << str << endl;

    // I like the first one.
    return 0;
}


3.9

不合法。因为s为空,s[0]的结果将是未定义的。在访问指定字符之前,首先检查s是否为空。


3.10

    
// reads a string of characters including punctuation and writes what was read
// but with the punctuation removed.

#include <iostream>
#include <string>

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

int main()
{
    string s;
    cout << "Enter a string of characters including punctuation." << endl;
    while (getline(cin, s)) {
        for (auto i : s)
            if (!ispunct(i)) cout << i;
        cout << endl;
    }

    return 0;
}

 3.11

c的类型是字符型常量引用,只要不改变c的值,都是合法的,否则是非法的。


3.12

(a)合法(c++11),其对象是vector对象。

(b)不合法,两个vector对象的类型必须相同。

(c)合法,有10个“null"。


3.13

(a)初始状态为空,没有元素。

(b)10个元素,都是0。

(c)10个元素,都是42。

(d)1个元素,是10。

(e)2个元素,10和42。

(f)10个默认初始化的元素。

(g)10个值为”hi"的元素。


3.14

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> vec;
    int i;                                                                                    
    while (std::cin >> i) vec.push_back(i);

    return 0;
}

3.15

include <iostream>
#include <vector>
#include <string>

int main()
{
    std::vector<std::string> vec;
    std::string str;
    while (std::cin >> str) vec.push_back(str);

    return 0;
}


3.16

C++ primer(第五版)第3章习题答案
#include <iostream>
#include <vector>
#include <string>

using std::vector;
using std::string;
using std::cout;
using std::endl;

int main()
{
    vector<int> v1;
    cout << "{\n \"v1\":{\"size\":\"" << v1.size() << "\",\"value\":[";
    for (auto i : v1) cout << i << ",";
    if (!v1.empty()) cout << "\b";
    cout << "]}" << endl;

    vector<int> v2(10);
    cout << " \"v2\":{\"size\":\"" << v2.size() << "\",\"value\":[";
    for (auto i : v2) cout << i << ",";
    if (!v2.empty()) cout << "\b";
    cout << "]}" << endl;

    vector<int> v3(10, 42);
    cout << " \"v3\":{\"size\":\"" << v3.size() << "\",\"value\":[";
    for (auto i : v3) cout << i << ",";
    if (!v3.empty()) cout << "\b";
    cout << "]}" << endl;

    vector<int> v4{10};
    cout << " \"v4\":{\"size\":\"" << v4.size() << "\",\"value\":[";
    for (auto i : v4) cout << i << ",";
    if (!v4.empty()) cout << "\b";
    cout << "]}" << endl;

    vector<int> v5{10, 42};
    cout << " \"v5\":{\"size\":\"" << v5.size() << "\",\"value\":[";
    for (auto i : v5) cout << i << ",";
    if (!v5.empty()) cout << "\b";
    cout << "]}" << endl;

    vector<string> v6{10};
    cout << " \"v6\":{\"size\":\"" << v6.size() << "\",\"value\":[";
    for (auto i : v6)
        if (i.empty())
            cout << "(null)"
                 << ",";
        else
            cout << i << ",";
    if (!v6.empty()) cout << "\b";
    cout << "]}" << endl;

    vector<string> v7{10, "hi"};
    cout << " \"v7\":{\"size\":\"" << v7.size() << "\",\"value\":[";
    for (auto i : v7)
        if (i.empty())
            cout << "(null)"
                 << ",";
        else
            cout << i << ",";
    if (!v7.empty()) cout << "\b";
    cout << "]}\n}" << endl;

    return 0;
}


3.17

#include <iostream>
#include <vector>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::vector;
using std::string;

int main()
{
    vector<string> vec;
    string word;
    while (cin >> word) vec.push_back(word);

    for (auto& str : vec)
        for (auto& c : str) c = toupper(c);

    for (decltype(vec.size()) i = 0; i != vec.size(); ++i) {
        if (i != 0 && i % 8 == 0) cout << endl;
        cout << vec[i] << " ";
    }
    cout << endl;

    return 0;
}


3.18

#include <vector>

using std::vector;

int main()
{
    vector<int> ivec{0};
    ivec[0] = 42;
    return 0;
} 


3.19

#include <iostream>
#include <vector>
using std::vector;

int main()
{
    vector<int> ivec1(10, 42);
    vector<int> ivec2{42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
    vector<int> ivec3;
    for (int i = 0; i != 10; ++i) ivec3.push_back(42);
    std::cout << "The first approach is better!" << std::endl;
}


3.20

#include <iostream>
#include <vector>

using std::vector;
using std::cout;
using std::endl;
using std::cin;

int main()
{
    vector<int> ivec;
    int i;
    while (cin >> i) ivec.push_back(i);

    if (ivec.empty()) {
        cout << "input at least one integer." << endl;
        return -1;
    }
    else if (ivec.size() == 1) {
        cout << ivec[0] << " don't have any adjacent elements.";
    }
    else {
        for (decltype(ivec.size()) i = 0; i != ivec.size() - 1; ++i)
            cout << ivec[i] + ivec[i + 1] << " ";
    }

    cout << endl;

    decltype(ivec.size()) size = ivec.size();
    if (size % 2 != 0)
        size = size / 2 + 1;
    else
        size /= 2;

    for (decltype(ivec.size()) i = 0; i != size; ++i)
        cout << ivec[i] + ivec[ivec.size() - i - 1] << " ";
    cout << endl;

    return 0;
}


3.21

#include <vector>
#include <iterator>
#include <string>
#include <iostream>

using std::vector;
using std::string;
using std::cout;
using std::endl;

void check(const vector<int>& vec)
{
    if (vec.empty())
        cout << "size: 0; no values." << endl;
    else {
        cout << "size: " << vec.size() << "; values:";
        for (auto it = vec.begin(); it != vec.end(); ++it) cout << *it << ",";
        cout << "\b." << endl;
    }
}

void check(const vector<string>& vec)
{
    if (vec.empty())
        cout << "size: 0; no values." << endl;
    else {
        cout << "size: " << vec.size() << "; values:";
        for (auto it = vec.begin(); it != vec.end(); ++it)
            if (it->empty())
                cout << "(null)"
                     << ",";
            else
                cout << *it << ",";
        cout << "\b." << endl;
    }
}

int main()
{
    vector<int> v1;
    vector<int> v2(10);
    vector<int> v3(10, 42);
    vector<int> v4{10};
    vector<int> v5{10, 42};
    vector<string> v6{10};
    vector<string> v7{10, "hi"};

    check(v1);
    check(v2);
    check(v3);
    check(v4);
    check(v5);
    check(v6);
    check(v7);

    return 0;
}


3.22

#include <iostream>
#include <vector>
#include <string>
#include <iterator>

using std::vector;
using std::string;
using std::cout;
using std::cin;
using std::endl;

int main()
{
    vector<string> text;
    for (string line; getline(cin, line);) text.push_back(line);

    for (auto it = text.begin(); it != text.end() && !it->empty(); ++it) {
        for (auto& c : *it) c = toupper(c);
        cout << *it << endl;
    }

    return 0;
}


3.23

#include <vector>
#include <iostream>
#include <iterator>

using std::vector;
using std::iterator;
using std::cout;
using std::endl;

int main()
{
    vector<int> ivec(10, 1);
    for (auto it = ivec.begin(); it != ivec.end(); ++it) *it *= 2;
    for (auto value : ivec) cout << value << " ";
    cout << endl;

    return 0;
}


3.24

#include <iostream>
#include <vector>
#include <iterator>

using std::vector;
using std::cout;
using std::endl;
using std::cin;

int main()
{
    int i;
    vector<int> ivec;
    while (cin >> i) ivec.push_back(i);

    if (ivec.empty()) {
        cout << "input at least one integer." << endl;
        return -1;
    }
    else if (ivec.size() == 1) {
        cout << *ivec.begin() << " has no adjacent elements.";
    }

    for (auto it = ivec.begin(); it + 1 != ivec.end(); ++it)
        cout << *it + *(it + 1) << " ";
    cout << endl;

    for (auto beg = ivec.begin(), end = ivec.end() - 1; beg <= end;
         ++beg, --end)
        cout << *beg + *end << " ";
    cout << endl;

    return 0;
}


3.25

#include <vector>
#include <iterator>
#include <iostream>

using std::vector;
using std::cout;
using std::cin;
using std::endl;

int main()
{
    vector<unsigned> scores(11, 0);
    unsigned grade;
    while (cin >> grade)
        if (grade <= 100) ++(*(scores.begin() + grade / 10));

    for (auto score : scores) cout << score << " ";
    cout << endl;

    return 0;
}


3.26

vector迭代器运算中不支持两个迭代器相加,只支持两个迭代器相减,或一个迭代器与整数值的加减。


3.27

(a) 非法,维度必须是一个常量表达式。

(b)合法。

(c)非法,返回值不是常量表达式。

(d)非法,没有空间可存放空字符。


3.28

string不是内置类型,其支持无须显式初始化而定义对象,没有指定初值则生成一个空串,ia,ia2是内置类型,ia在函数体之外被初始化为0,ia2在函数体内部将不被初始化,其值是未定义的。


3.29

数组大小确定不变,不能随意向数组中增加元素。


3.30

数组索引从0开始,所以ix应该小于array_size,不可以等于。


3.31

#include <cstddef>
#include <iostream>

using std::cout;
using std::endl;

int main()
{
    int ia[10];
    for (size_t i = 0; i < 10; ++i) ia[i] = i;

    for (auto i : ia) cout << i << " ";
    cout << endl;

    return 0;
}

3.32

#include <cstddef>
#include <iostream>
#include <vector>
#include <iterator>

using std::cout;
using std::endl;
using std::vector;
using std::iterator;

int main()
{
    // use array
    int ia[10];
    for (size_t i = 0; i < 10; ++i) ia[i] = i;

    int ia2[10];
    for (size_t i = 0; i < 10; ++i) ia2[i] = ia[i];

    // use vector
    vector<int> iv(10);
    for (auto iter = iv.begin(); iter != iv.end(); ++iter)
        *iter = iter - iv.begin();

    vector<int> iv2(iv);

    for (auto i : iv2) cout << i << " ";
    cout << endl;

    return 0;
}

3.33

不初始化数组将含有未定义的值。


3.34

相当于p1=p2; 只要p1和p2都合法,则该程序一直合法。


3.35

#include <iostream>
#include <iterator>

using std::begin;
using std::end;
using std::cout;
using std::endl;

int main()
{
    int arr[10];
    int* b = begin(arr);
    int* e = end(arr);

    for (int* i = b; i != e; ++i) *i = 0;

    for (auto i : arr) cout << i << " ";
    cout << endl;

    return 0;
}


3.36

#include <iostream>
#include <vector>
#include <iterator>

using std::begin;
using std::end;
using std::cout;
using std::endl;
using std::vector;

// pb point to begin of the array, pe point to end of the array.
bool compare(int* const pb1, int* const pe1, int* const pb2, int* const pe2)
{
    if ((pe1 - pb1) != (pe2 - pb2)) // have different size.
        return false;
    else {
        for (int *i = pb1, *j = pb2; (i != pe1) && (j != pe2); ++i, ++j)
            if (*i != *j) return false;
    }

    return true;
}

int main()
{
    int arr1[3] = {0, 1, 2};
    int arr2[3] = {0, 2, 4};

    if (compare(begin(arr1), end(arr1), begin(arr2), end(arr2)))
        cout << "The two arrays are equal." << endl;
    else
        cout << "The two arrays are not equal." << endl;

    cout << "==========" << endl;

    vector<int> vec1 = {0, 1, 2};
    vector<int> vec2 = {0, 1, 2};

    if (vec1 == vec2)
        cout << "The two vectors are equal." << endl;
    else
        cout << "The two vectors are not equal." << endl;

    return 0;
}


3.37

输出数组ca的所有元素。whiile循环检测空字符,需在数组最后一个字符后添加一个空字符。


3.38

因为两个指针相减可以得到在内存区域的相位差(距离),加减一个整数可以表明指针的前后移动。两个指针相加在逻辑上没有意义。


3.39

#include <iostream>
#include <string>
#include <cstring>

using std::cout;
using std::endl;
using std::string;

int main()
{
    // use string.
    string s1("Mooophy");
    string s2("Pezy");

    if (s1 == s2)
        cout << "same string." << endl;
    else if (s1 > s2)
        cout << "Mooophy > Pezy" << endl;
    else
        cout << "Mooophy < Pezy" << endl;

    cout << "=========" << endl;
    // use C-Style character strings.
    const char* cs1 = "Wangyue";
    const char* cs2 = "Pezy";

    auto result = strcmp(cs1, cs2);
    if (result == 0)
        cout << "same string." << endl;
    else if (result < 0)
        cout << "Wangyue < Pezy" << endl;
    else
        cout << "Wangyue > Pezy" << endl;

    return 0;
}


3.40

#include <cstring>
#include <iostream>

using std::cout;
using std::endl;

int main()
{
    const char cstr1[] = "Hello";
    const char cstr2[] = "world!";

    size_t new_size = strlen(cstr1) + strlen(" ") + strlen(cstr2) + 1;
    char* cstr3 = new char[new_size];

    strcpy(cstr3, cstr1);
    strcat(cstr3, " ");
    strcat(cstr3, cstr2);

    std::cout << cstr3 << std::endl;
    delete [] cstr3;
}


3.41

#include <iostream>
#include <vector>

using std::vector;
using std::cout;
using std::endl;
using std::begin;
using std::end;

int main()
{
    int int_arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    vector<int> ivec(begin(int_arr), end(int_arr));

    for (auto i : ivec) cout << i << " ";
    cout << endl;

    return 0;
}


3.42

#include <iostream>
#include <vector>

using std::vector;
using std::cout;
using std::endl;
using std::begin;
using std::end;

int main()
{
    vector<int> ivec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    int int_arr[10];

    for (int* i = begin(int_arr); i != end(int_arr); ++i)
        *i = ivec[i - begin(int_arr)];

    for (auto i : int_arr) cout << i << " ";
    cout << endl;

    return 0;
}


3.43

#include <iostream>

using std::cout;
using std::endl;

int main()
{
    int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

    // a range for to manage the iteration
    for (const int(&p)[4] : ia)
        for (int q : p) cout << q << " ";
    cout << endl;

    // ordinary for loop using subscripts
    for (size_t i = 0; i != 3; ++i)
        for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
    cout << endl;

    // using pointers.
    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 std::cout;
using std::endl;

int main()
{
    int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

    // a range for to manage the iteration
    // use type alias
    using int_array = int[4];
    for (int_array& p : ia)
        for (int q : p) cout << q << " ";
    cout << endl;

    // ordinary for loop using subscripts
    for (size_t i = 0; i != 3; ++i)
        for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
    cout << endl;

    // using pointers.
    // use type alias
    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 std::cout;
using std::endl;

int main()
{
    int ia[3][4] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};

    // a range for to manage the iteration
    for (auto& p : ia)
        for (int q : p) cout << q << " ";
    cout << endl;

    // ordinary for loop using subscripts
    for (size_t i = 0; i != 3; ++i)
        for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
    cout << endl;

    // using pointers.
    for (auto p = ia; p != ia + 3; ++p)
        for (int* q = *p; q != *p + 4; ++q) cout << *q << " ";
    cout << endl;

    return 0;
}