C++ Primer 习题解答 第三章

来源:互联网 发布:小米手机网络助手套餐 编辑:程序博客网 时间:2024/05/21 09:41
 

习题 3.1 用适当的using声明,而不用std::前缀,访问标准库中名字的方法,重新编写2.3节的程序,计算一给定数的给定次幂的结果。

解答:修改习题2.11的程序如下:(比较和2.11的区别)

#include <iostream>

using std::cout;

using std::cin;

using std::endl;

 

int main()

{

    cout << "Please enter two numbers:/n"

    " (the first nuber as a base and the second number as a exponent)" << endl;

    int base;

    int exponent;

    cin >> base >> exponent;

    int result = 1;

    for(int cnt = 0; cnt != exponent; ++cnt){

        result *= base;

    }

    cout << "The result of " << base << " of " << exponent << " power is " << result << endl;

    return 0;

}

 

习题 3.2 什么是默认构造函数?

解答:构造函数是类的一个特殊成员函数,定义如果初始化该类的对象。当没有明确指定对象初始化式时,系统将使用默认构造函数。

 

习题 3.3 列出三种初始化string对象的方法。

解答:

string s2(s1);      //s2初始化为s1的一个副本

string s3(“value”);//s3初始化为一个字符串字面值常量

string s4(n, ‘c’); //s4初始化为字符’c’n个副本

 

习题 3.4 ss2的值分别是什么?

string s;

int main(){

    string s2;

}

解答:当没有显示初始化string对象时,不管该对象是定义在函数体内还是定义在函数体外,都将调用string的默认构造函数,初始化string对象为空串。所以ss2的值都为空。

 

习题 3.5 编写程序实现从标准输入每次读入一行文本。然后改写程序,每次读入一个单词。

解答:

//每次读入一行

    string line;

    while(getline(cin, line)){

        cout << line << endl;

    }

改写程序,每次读入一个单词:

string word;

while( cin >> word){

    cout << word << endl;

}

 

习题 3.6 解释string类型的输入操作符和getline函数分别如何处理空白字符。

解答:string类型的输入操作符读取并忽略开头所有的空白字符,读取字符直到再次遇到空白字符。getline并不忽略开头的换行符,只要遇到换行符,它就停止读入并返回。

 

习题 3.7 编一个程序读入两个string对象,测试它们是否相等。若不相等,则指出两个中哪个较大。接着,改写程序测试它们的长度是否相等,若不相等指出哪个较长。

解答:判断两个中的较大者

     string s1,s2;

    cout << "Please enter two words:" << endl;

    cin >> s1 >> s2;

    if(s1 == s2){

        cout << "They are the same words." << endl;

    }

    else if( s1 > s2 ){

        cout << s1 << " is greater than " << s2 << endl;

    }

    else{

        cout << s2 << " is greater than " << s1 << endl;

    }

判断两者中的较长者

     string s1,s2;

    cout << "Please enter two words:" << endl;

    cin >> s1 >> s2;

    if(s1.size() == s2.size()){

        cout << "They have the same long." << endl;

    }

    else if( s1.size() > s2.size() ){

        cout << s1 << " is longer than " << s2 << endl;

    }

    else{

        cout << s2 << " is longer than " << s1 << endl;

    }

习题 3.8 编一个程序,从标准输入读取多个string对象,把它们连接起来放到一个更大的string对象中。并输出连接后的string对象。接着,改写程序,将连接后相邻string对象以空格隔开。

解答:

没有空格隔开的string:

    string s,s1;

    cout << "Please enter some words:" << endl;

    while( cin >> s1 ){

        s += s1;

    }

    cout << s << endl;

将相邻string对象以空格隔开:

     string s,s1;

    cout << "Please enter some words:" << endl;

    while( cin >> s1 ){

        s += s1 + " ";

    }

    cout << s << endl;

 

习题 3.9 下列程序实现什么功能?实现合法吗?如果不合法,说明理由。

string s;

cout << s[0] << endl;

解答:这个程序是合法的,输出空字符’/0’

 

习题 3.10 编一个程序,从string对象中去掉标点符号。要求输入到程序的字符串必须含有标点符号,输出结果则是去掉标点符号后的string对象。

解答:

     string line;

    cout << "Please input some words(include punctuation):" << endl;

    getline( cin, line );

    string result;

    for( string::size_type ix = 0; ix != line.size(); ++ ix){

        if(!ispunct(line[ix])){

            result += line[ix];

        }

    }

    cout << result << endl;

注意头文件要包含 cctype

 

习题 3.11 下面哪些vector定义不正确?

(a) Vector< vector<int> > ivec;

(b) Vector<string> svec = ivec;

(c) Vector<string> svec(10, “null”);

解答:

(a) 正确的。定义了一个容器的容器。

(b) 错误。ivec不是string类型的容器,不同类型的容器之间不能复制。

(c) 正确。定义了包含10个字符串”null”的容器。

 

习题 3.12 下列每个vector对象中元素个数是多少?各元素的值是什么?

(a) vector<int> ivec1;

(b) vector<int> ivec2(10);

(c) vector<int> ivec3(10, 42);

(d) vector<string> svec1;

(e) vector<string> svec2(10);

(f) vector<string> svec3(10,”hello”);

解答:

(a) ivec1中没有元素

(b) ivec2中有10个元素,每个元素的值都是0

(c) ivce3中有10个元素,每个元素的值都是42

(d) svec1中没有元素

(e) svec2中有10个元素,第个元素都是空字符串

(f) svec3中有10个元素,每个元素都是字符串”hello”

 

习题 3.13 读一组整数到vector对象,计算并输出每对相邻元素的和。如果读入元素个数为奇数,则提示用户最后一个元素没有求和,并输出其值。然后修改程序:头尾元素两两配对(第一个和最后一个,第二个和倒数第二个,以此类推),计算每对元素的和,并输出。

解答:

输出相邻元素的和(下标操作实现)

    cout << "Please input some numbers:(press enter as end)" << endl;

    int num(0);

    vector<int> ivec;

    while( cin.peek() != '/n' && cin >> num ){

        ivec.push_back(num);

    }

    cout << "The result:" << endl;

    int size(ivec.size());

    for( vector<int>::size_type ix = 1; ix < size; ix += 2 ){

        cout << ivec[ix - 1] + ivec[ix] << " ";

    }

    if(size % 2 == 1){

        cout << "/nThe last number "

<< ivec[size - 1]

<< " is not in the result." << endl;

    }

迭代器实现输出相邻两元素的和:

    cout << "Please input some numbers:(press enter as end)" << endl;

    int num(0);

    vector<int> ivec;

    while( cin.peek() != '/n' && cin >> num ){

        ivec.push_back(num);

    }

    cout << "The result:" << endl;

    for( vector<int>::const_iterator iter = ivec.begin() + 1;

        iter < ivec.end(); iter += 2 ){

        cout << *(iter -1) + *iter << " ";

    }

    if(ivec.size() % 2 == 1){

        cout << "/nThe last number "

            << *(ivec.end() - 1)

            << " is not in the result." << endl;

    }

修改代码,实现头尾两两配对求和(下标操作实现方法):

    cout << "Please input some numbers:(press enter as end)" << endl;

    int num(0);

    vector<int> ivec;

    while( cin.peek() != '/n' && cin >> num ){

        ivec.push_back(num);

    }

    cout << "The result:" << endl;

    int size = ivec.size();

    for( vector<int>::size_type ix = 0;

        !ivec.empty() && ix < size - ix -1; ++ ix ){

        cout << ivec[ix] + ivec[size - ix - 1] << " ";

    }

    if(ivec.size() % 2 == 1){

        cout << "/nThe middle number "

            << ivec[size / 2]

            << " is not in the result." << endl;

    }

迭代器实现方法:

     cout << "Please input some numbers:(press enter as end)" << endl;

    int num(0);

    vector<int> ivec;

    while( cin.peek() != '/n' && cin >> num ){

        ivec.push_back(num);

    }

    cout << "The result:" << endl;

    for( vector<int>::const_iterator first = ivec.begin(),second = ivec.end();

        !ivec.empty() && second - first > 1; ++ first, -- second ){

        cout << *first + *(second - 1)<< " ";

    }

    if(ivec.size() % 2 == 1){

        cout << "/nThe middle number "

            << *(ivec.begin() + ivec.size() / 2)

            << " is not in the result." << endl;

    }

 

习题 3.14 读入一段文本到vector对象,每个单词存储为vector中的一个元素。把vector对象中每个单词转化为大写字母。输出vector对象中转化后的元素,每八个单词为一行输出。

解答:此程序中,注意包含头文件cctype

下标操作实现:

    cout << "Please input some words:(press enter as end)" << endl;

    string word;

    vector<string> svec;

    while( cin.peek() != '/n' && cin >> word ){

        svec.push_back(word);

    }

    cout << "The result to upper:" << endl;

    for( vector<string>::size_type ix = 0;

         ix != svec.size(); ++ ix ){

        for( string::size_type i = 0; i != svec[ix].size(); ++ i){

            svec[ix][i] = toupper(svec[ix][i]);

        }

        if(ix != 0 && ix % 8 == 0){

            cout << endl;

        }

        cout << svec[ix] << " ";

    }

修改程序,用迭代器实现:

     cout << "Please input some words:(press enter as end)" << endl;

    string word;

    vector<string> svec;

    while( cin.peek() != '/n' && cin >> word ){

        svec.push_back(word);

    }

    cout << "The result to upper:" << endl;

    for( vector<string>::iterator iter = svec.begin();

         iter != svec.end(); ++ iter ){

             for( string::iterator i = (*iter).begin(); i != (*iter).end(); ++ i){

            *i = toupper(*i);

        }

        if(iter != svec.begin() && ( iter - svec.begin()) % 8 == 0){

            cout << endl;

        }

        cout << *iter << " ";

    }

 

习题 3.15 下面程序合法吗?如果不合法,如何更正?

vector<int> ivec;

ivec[0] = 42;

解答:这是不合法的,下标操作不添加元素。

 

习题 3.16 列出三种定义vector对象的方法,给定10个元素,每个元素值为42.指出是否还有更好的实现方法,并说明为什么。

解答:

方法一:

    vector<int> ivec;

    for(int cnt = 0; cnt != 10; ++ cnt){

        ivec.push_back(42);

    }

方法二:

    vector<int> ivec(10);

    for(vector<int>::size_type ix = 0; ix != ivec.size(); ++ ix){

        ivec[ix] = 42;

    }

方法三:

vector<int> ivec(10, 42);

感觉没有比第三种方法更好的实现方法了。

 

习题 3.17 重做3.3.2节的习题,用迭代器而不是下标操作来访问vector中的元素。

解答:见上节的习题解答。

 

习题 3.18 编写程序来创建有10个元素的vector对象。用迭代器把每个元素值改为当前值的2倍。

解答:

    vector<int> ivec(10, 42);

    for(vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++ iter){

        *iter *= 2;

        cout << *iter << endl;

    }

 

习题 3.19 验证习题3.18的程序,输出vector的所有元素。

解答:见习题3.18.

 

习题 3.20 解释一下在上几题的程序实现中你用了哪种迭代器,并说明原因。

解答:通过上几题的程序可以看到,使用的都是普通的iterator,因为要遍历整个容器和改变容器内对象的值。如果仅仅是遍历容器,可以定义为const_iterator

 

习题 3.21 何时使用const迭代器的?又在何时使用const_iterator?解释两者的区别。

解答:如果你希望一个迭代器只指向容器内一个特定的元素,就可以把它定义为const迭代器。如果你不想改变一个容器里元素的值,就可以把指向这个容器的迭代器定义成const_iteratorconst迭代器在定义的时候就要指定一个对象,而且定义后不可再指向其它对象,不过可以通过const迭代器改变其指向对象的值。const_iterator可以指向任何一个容器对象,但不能通过const_iterator来更改其指向对象的值。

 

习题 3.22 如果采用下面的方法来计算mid会产生什么结果?

vector<int>::iterator mid = (vi.begin() + vi.end())/2;

解答:会产生编译错误,迭代器并没有定义两个迭代器的+操作。只可以在迭代器对象上加或减去一个整型值,或者是对两个迭代器作“-”操作,得出两个迭代器之间的距离。

 

习题 3.23 解释下面每个bitset对象包含的位模式:

(a) bitset<64> bitvec(32);

(b) bitset<32> bv(1010101);

(c) string bstr; cin >> bstr; bitset<8> bv(bstr);

解答:

(a) 整型字面值3264位二进制位的有序集。

(b) 整型字面值101010132位二进制位的有序集。

(c) 保存用户输入的二进制字符串的前8位。

 

习题 3.24 考虑这样的序列123581321,并初始化一个将该序列数字所对应的位置置为1bitset<32>对象。然后换个方法,给定一个空的bitset对象,编写一小段程序把相应的数位设置为1

解答:

直接初始化

     string s("1000000010000100101110");

    bitset<32> bv(s);

另一种方法:

    bitset<32> bv;

    int n1(1),n2(2);

    bv.set(n1);

    while(n2 <= 32){

        bv.set(n2);

        int temp = n1 + n2;

        n1 = n2;

        n2 = temp;

    }

作为练习,我们用一个容器保存该序列的值,然后再根据容器内元素的值把bitset对象中的相应位置为1:

    bitset<32> bv;

    vector<int> ivec(1,1);

    ivec.push_back(2);

    while(( *(ivec.end() - 1) + *(ivec.end() - 2)) <= 32){

        ivec.push_back(*(ivec.end() - 1) + *(ivec.end() - 2));

    }

    for(vector<int>::const_iterator iter = ivec.begin();

        iter != ivec.end(); ++ iter){

        bv.set(*iter);

    }