• C++Primer中文版(第4版)第三章习题答案


    习题3.1 用适当的using声明,而不用std::前缀,访问标准库中的名字,重新编写2.3节的程序,计算一给定数的给定次幂的结果。 【解答】 #include using std::cin; using std::cout; int main() { // 局部对象 int base, exponent; long result=1; // 读入底数和指数 cout << "Enter base and exponent:" << endl; cin >> base >> exponent; if (exponent < 0) { cout << "Exponent can't be smaller than 0" << endl; return -1; } if (exponent > 0) { // 计算底数的指数次方 for (int cnt = 1; cnt <= exponent; ++cnt) result *= base; } cout << base << " raised to the power of " << exponent << ": " << result << endl; return 0; } 习题3.2 什么是默认构造函数? 【解答】 默认构造函数(default constructor)就是在没有显式提供初始化式时调用的构造函数。它由不带参数的构造函数,或者为所有形参提供默认实参的构造函数定义。如果定义某个类的变量时没有提供初始化式,就会使用默认构造函数。 如果用户定义的类中没有显式定义任何构造函数,编译器就会自动为该类生成默认构造函数,称为合成的默认构造函数(synthesized default constructor)。 习题3.3 列举出三种初始化string对象的方法。 【解答】 (1) 不带初始化式,使用默认构造函数初始化string对象。 (2) 使用一个已存在的string对象作为初始化式,将新创建的string对象初始化为已存在对象的副本。 (3) 使用字符串字面值作为初始化式,将新创建的string对象初始化为字符串字面值的副本。 习题3.4 s和s2的值分别是什么? string s; int main() { string s2; } 【解答】 s和s2的值均为空字符串。 习题3.5 编写程序实现从标准输入每次读入一行文本。然后改写程序,每次读入一个单词。 【解答】 //从标准输入每次读入一行文本 #include #include using namespace std; int main() { string line; // 一次读入一行,直至遇见文件结束符 while (getline(cin, line)) cout << line << endl; // 输出相应行以进行验证 return 0; } 修改后程序如下: //从标准输入每次读入一个单词 #include #include using namespace std; int main() { string word; // 一次读入一个单词,直至遇见文件结束符 while (cin >> word) cout << word << endl; // 输出相应单词以进行验证 return 0; } 注意,一般而言,应该尽量避免使用using指示而使用using声明(参见17.2.4 节),因为如果应用程序中使用了多个库,使用using指示引入这些库中定义的名字空间,容易导致名字冲突。但本书中的程序都只使用了标准库,没有使用其他库。使用using指示引入名字空间std中定义的所有名字不会发生名字冲突。因此为了使得代码更为简洁以节省篇幅,本书的许多代码中都使用了 using指示using namespace std;来引入名字空间std。另外,本题中并未要求输出,加入输出是为了更清楚地表示读入的结果。本书后面部分有些地方与此类似处理,不再赘述。 习题3.6 解释string类型的输入操作符和getline函数分别如何处理空白字符。 【解答】 string类型的输入操作符对空白字符的处理:读取并忽略有效字符(非空白字符)之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止(该空白字符仍留在输入流中)。 getline函数对空白字符的处理:不忽略行开头的空白字符,读取字符直至遇到换行符,读取终止并丢弃换行符(换行符从输入流中去掉但并不存储在string对象中)。 习题3.7 编一个程序读入两个string对象,测试它们是否相等。若不相等,则指出两个中哪个较大。接着,改写程序测试它们的长度是否相等,若不相等,则指出两个中哪个较长。 【解答】 测试两个string对象是否相等的程序: #include #include using namespace std; int main() { string s1, s2; // 读入两个string对象 cout << "Enter two strings:" << endl; cin >> s1 >> s2; // 测试两个string对象是否相等 if (s1 == s2) cout << "They are equal." << endl; else if (s1 > s2) cout << "\"" << s1 << "\" is bigger than" << " \"" << s2 << "\"" << endl; else cout << "\"" << s2 << "\" is bigger than" << " \"" << s1 << "\"" << endl; return 0; } 测试两个string对象的长度是否相等的程序: #include #include using namespace std; int main() { string s1, s2; // 读入两个string对象 cout << "Enter two strings:" << endl; cin >> s1 >> s2; // 比较两个string对象的长度 string::size_type len1, len2; len1 = s1.size(); len2 = s2.size(); if (len1 == len2) cout << "They have same length." << endl; else if (len1 > len2) cout << "\"" << s1 << "\" is longer than" << " \"" << s2 << "\"" << endl; else cout << "\"" << s2 << "\" is longer than" << " \"" << s1 << "\"" << endl; return 0; } 习题3.8 编一个程序,从标准输入读取多个string对象,把它们连接起来存放到一个更大的string对象中,并输出连接后的string对象。接着,改写程序,将连接后相邻string对象以空格隔开。 【解答】 #include #include using namespace std; int main() { string result_str, str; // 读入多个string对象并进行连接 cout << "Enter strings(Ctrl+Z to end):" << endl; while (cin>>str) result_str = result_str + str; // 输出连接后的string对象 cout << "String equal to the concatenation of these strings is:" << endl << result_str << endl; return 0; } 改写后的程序: #include #include using namespace std; int main() { string result_str, str; // 读入多个string对象并进行连接 cout << "Enter strings(Ctrl+Z to end):" << endl; cin >> result_str;//读入第一个string对象,放到结果对象中 while (cin>>str) result_str = result_str + ' ' + str; // 输出连接后的string对象 cout << "String equal to the concatenation of these strings is:" << endl << result_str << endl; return 0; } 习题3.9 下列程序实现什么功能?实现合法吗?如果不合法,说明理由。 string s; cout << s[0] << endl; 【解答】 该程序段输出string对象s所对应字符串的第一个字符。 实现不合法。因为s是一个空字符串,其长度为0,因此s[0]是无效的。 注意,在一些编译器(如Microsoft Visual C++ .NET 2003)的实现中,该程序段并不出现编译错误。 习题3.10 编一个程序,从string 对象中去掉标点符号。要求输入到程序的字符串必须含有标点符号,输出结果则是去掉标点符号后的string对象。 【解答】 #include #include #include using namespace std; int main() { string s, result_str; bool has_punct = false;//用于标记字符串中有无标点 char ch; //输入字符串 cout << "Enter a string:" << endl; getline(cin, s); //处理字符串:去掉其中的标点 for (string::size_type index = 0; index != s.size(); ++index) { ch = s[index]; if (ispunct(ch)) has_punct = true; else result_str += ch; } if (has_punct) cout << "Result:" << endl << result_str < > ivec; (b) vector svec = ivec ; (c) vector svec(10,"null"); 【解答】 (b)不正确。因为svec定义为保存string对象的vector对象,而ivec是保存vector 对象的vector对象(即ivec是vector的vector),二者的元素类型不同,所以不能用ivec来初始化svec。 习题3.12 下列每个vector对象中元素个数是多少?各元素的值是什么? (a) vector ivec1; (b) vector ivec2(10); (c) vector ivec3(10,42); (d) vector svec1; (e) vector svec2(10); (f) vector svec3(10,"hello"); 【解答】 (a) 元素个数为0。 (b) 元素个数为10,各元素的值均为0。 (c) 元素个数为10,各元素的值均为42。 (d) 元素个数为0。 (e) 元素个数为10,各元素的值均为空字符串。 (f) 元素个数为10,各元素的值均为"hello"。 习题3.13 读一组整数到vector对象,计算并输出每对相邻元素的和。如果读入元素个数为奇数,则提示用户最后一个元素没有求和,并输出其值。然后修改程序:头尾元素两两配对(第一个和最后一个,第二个和倒数第二个,以此类推),计算每对元素的和,并输出。 【解答】 //读一组整数到vector对象,计算并输出每对相邻元素的和 #include #include using namespace std; int main() { vector ivec; int ival; // 读入数据到vector对象 cout << "Enter numbers(Ctrl+Z to end):" << endl; while (cin>>ival) ivec.push_back(ival); // 计算相邻元素的和并输出 if (ivec.size() == 0) { cout << "No element?!" << endl; return -1; } cout << "Sum of each pair of adjacent elements in the vector:" << endl; for (vector::size_type ix = 0; ix < ivec.size()-1; ix = ix + 2) { cout << ivec[ix] + ivec[ix+1] << "\t"; if ( (ix+1) % 6 == 0) // 每行输出6个和 cout << endl; } if (ivec.size() % 2 != 0) // 提示最后一个元素没有求和 cout << endl << "The last element is not been summed " << "and its value is " << ivec[ivec.size()-1] << endl; return 0; } 修改后的程序: //读一组整数到vector对象,计算首尾配对元素的和并输出 #include #include using namespace std; int main() { vector ivec; int ival; //读入数据到vector对象 cout << "Enter numbers:" << endl; while (cin>>ival) ivec.push_back(ival); //计算首尾配对元素的和并输出 if (ivec.size() == 0) { cout << "No element?!" << endl; return -1; } cout << "Sum of each pair of counterpart elements in the vector:" << endl; vector::size_type cnt = 0; for (vector::size_type first = 0, last = ivec.size() - 1; first < last; ++first, --last) { cout << ivec[first] + ivec[last] << "\t"; ++cnt; if ( cnt % 6 == 0) //每行输出6个和 cout << endl; } if (first == last) //提示居中元素没有求和 cout << endl << "The center element is not been summed " << "and its value is " << ivec[first] << endl; return 0; } 习题3.14 读入一段文本到vector对象,每个单词存储为vector中的一个元素。把vector对象中每个单词转化为大写字母。输出vector对象中转化后的元素,每8个单词为一行输出。 【解答】 //读入一段文本到vector对象,每个单词存储为vector中的一个元素。 //把vector对象中每个单词转化为大写字母。 //输出vector对象中转化后的元素,每8个单词为一行输出 #include #include #include #include using namespace std; int main() { vector svec; string str; // 读入文本到vector对象 cout << "Enter text(Ctrl+Z to end):" << endl; while (cin>>str) svec.push_back(str); //将vector对象中每个单词转化为大写字母,并输出 if (svec.size() == 0) { cout << "No string?!" << endl; return -1; } cout << "Transformed elements from the vector:" << endl; for (vector::size_type ix = 0; ix != svec.size(); ++ix) { for (string::size_type index = 0; index != svec[ix].size(); ++index) if (islower(svec[ix][index])) //单词中下标为index的字符为小写字母 svec[ix][index] = toupper(svec[ix][index]); cout << svec[ix] << " "; if ((ix + 1) % 8 == 0)//每8个单词为一行输出 cout << endl; } return 0; } 习题3.15 下面程序合法吗?如果不合法,如何更正? vector ivec; ivec[0] = 42; 【解答】 不合法。因为ivec是空的vector对象,其中不含任何元素,而下标操作只能用于获取已存在的元素。 更正:将赋值语句改为语句ivec.push_back(42);。 习题3.16 列出三种定义vector对象的方法,给定10个元素,每个元素值为42。指出是否还有更好的实现方法,并说明为什么。 【解答】 方法一: vector ivec(10, 42); 方法二: vector ivec(10); for (ix = 0; ix < 10; ++ix) ivec[ix] = 42; 方法三: vector ivec(10); for (vector::iterator iter = ivec.begin(); iter != ivec.end(); ++iter) *iter = 42; 方法四: vector ivec; for (cnt = 1; cnt <= 10; ++cnt) ivec.push_back(42); 方法五: vector ivec; vector::iterator iter = ivec.end(); for (int i = 0; i != 10; ++i) { ivec.insert(iter, 42); iter = ivec.end(); } 各种方法都可达到目的,也许最后两种方法更好一些。它们使用标准库中定义的容器操作在容器中增添元素,无需在定义vector对象时指定容器的大小,比较灵活而且不容易出错。 习题3.17 重做3.3.2节的习题,用迭代器而不是下标操作来访问vector中的元素。 【解答】 重做习题3.13如下: //读一组整数到vector对象,计算并输出每对相邻元素的和 //使用迭代器访问vector中的元素 #include #include using namespace std; int main() { vector ivec; int ival; //读入数据到vector对象 cout << "Enter numbers(Ctrl+Z to end):" << endl; while (cin>>ival) ivec.push_back(ival); //计算相邻元素的和并输出 if (ivec.size() == 0) { cout << "No element?!" << endl; return -1; } cout << "Sum of each pair of adjacent elements in the vector:" << endl; vector::size_type cnt = 0; for (vector::iterator iter = ivec.begin(); iter < ivec.end()-1; iter = iter + 2) { cout << *iter + *(iter+1) << "\t"; ++cnt; if ( cnt % 6 == 0) //每行输出6个和 cout << endl; } if (ivec.size() % 2 != 0) //提示最后一个元素没有求和 cout << endl << "The last element is not been summed " << "and its value is " << *(ivec.end()-1) << endl; return 0; } //读一组整数到vector对象,计算首尾配对元素的和并输出 //使用迭代器访问vector中的元素 #include #include using namespace std; int main() { vector ivec; int ival; //读入数据到vector对象 cout << "Enter numbers(Ctrl+Z to end):" << endl; while (cin>>ival) ivec.push_back(ival); //计算首尾配对元素的和并输出 if (ivec.size() == 0) { cout << "No element?!" << endl; return -1; } cout << "Sum of each pair of counterpart elements in the vector:" << endl; vector::size_type cnt=0; for (vector::iterator first = ivec.begin(), last = ivec.end() - 1; first < last; ++first, --last) { cout << *first + *last << "\t"; ++cnt; if ( cnt % 6 == 0) //每行输出6个和 cout << endl; } if (first == last) //提示居中元素没有求和 cout << endl << "The center element is not been summed " << "and its value is " << *first << endl; return 0; } 重做习题3.14如下: //读入一段文本到vector对象,每个单词存储为vector中的一个元素。 //把vector对象中每个单词转化为大写字母。 //输出vector对象中转化后的元素,每8个单词为一行输出。 //使用迭代器访问vector中的元素 #include #include #include #include using namespace std; int main() { vector svec; string str; //读入文本到vector对象 cout << "Enter text(Ctrl+Z to end):" << endl; while (cin>>str) svec.push_back(str); //将vector对象中每个单词转化为大写字母,并输出 if (svec.size() == 0) { cout << "No string?!" << endl; return -1; } cout << "Transformed elements from the vector:" << endl; vector::size_type cnt = 0; for (vector::iterator iter = svec.begin(); iter != svec.end(); ++iter) { for (string::size_type index = 0; index != (*iter).size(); ++index) if (islower((*iter)[index])) //单词中下标为index的字符为小写字母 (*iter)[index] = toupper((*iter)[index]); cout << *iter << " "; ++cnt; if (cnt % 8 == 0)//每8个单词为一行输出 cout << endl; } return 0; } 习题3.18 编写程序来创建有10个元素的vector对象。用迭代器把每个元素值改为当前值的2倍。 【解答】 //创建有10个元素的vector对象, //然后使用迭代器将每个元素值改为当前值的2倍 #include #include using namespace std; int main() { vector ivec(10, 20);//每个元素的值均为20 //将每个元素值改为当前值的2倍 for (vector::iterator iter = ivec.begin(); iter != ivec.end(); ++iter) *iter = (*iter)*2; return 0; } 习题3.19 验证习题3.18的程序,输出vector的所有元素。 【解答】 //创建有10个元素的vector对象, //然后使用迭代器将每个元素值改为当前值的2倍并输出 #include #include using namespace std; int main() { vector ivec(10, 20);//每个元素的值均为20 //将每个元素值改为当前值的2倍并输出 for (vector::iterator iter = ivec.begin(); iter != ivec.end(); ++iter) { *iter = (*iter)*2; cout << *iter << " "; } return 0; } 习题3.20 解释一下在上几个习题的程序实现中你用了哪种迭代器,并说明原因。 【解答】 上述几个习题的程序实现中使用了类型分别为vector::iterator和vector ::iterator的迭代器,通过这些迭代器分别访问元素类型为int和string的vector对象中的元素。 习题3.21 何时使用const迭代器?又在何时使用const_iterator?解释两者的区别。 【解答】 const迭代器是迭代器常量,该迭代器本身的值不能修改,即该迭代器在定义时需要初始化,而且初始化之后,不能再指向其他元素。若需要指向固定元素的迭代器,则可以使用const迭代器。 const_iterator是一种迭代器类型,对这种类型的迭代器解引用会得到一个指向 const对象的引用,即通过这种迭代器访问到的对象是常量。该对象不能修改,因此,const_iterator类型只能用于读取容器内的元素,不能修改元素的值。若只需遍历容器中的元素而无需修改它们,则可以使用const_iterator。 习题3.22 如果采用下面的方法来计算mid会产生什么结果? vector::iterator mid = (vi.begin() + vi.end())/2; 【解答】 将两个迭代器相加的操作是未定义的,因此用这种方法计算mid会出现编译错误。 习题3.23 解释下面每个bitset对象包含的位模式: (a) bitset<64> bitvec(32); (b) bitset<32> bv(1010101); (c) string bstr; cin >> bstr; bitset<8> bv(bstr); 【解答】 (a) bitvec有64个二进制位,(位编号从0开始)第5位置为1,其余位置均为0。 (b) bv有32个二进制位,(位编号从0开始)第0、2、4、5、7、8、11、13、14、16、17、18、19位置为1,其余位置均为0。因为十进制数1010101对应的二进制数为000000000000011110110100110110101。 (c) bv有8个二进制位,(位编号从0开始)用读入的字符串的从右至左的8个字符对bv的0~7位进行初始化。 习题3.24 考虑这样的序列1,2,3,5,8,13,21,并初始化一个将该序列数字所对应的位置设置为1的bitset<32>对象。然后换个方法,给定一个空的bitset对象,编写一小段程序把相应的数位设置为1。 【解答】 bitset<32>对象的初始化: bitset<32> bv(0x20212e) 方法二: bitset<32> bv; int x = 0, y = 1, z; z = x + y; while (z <= 21) { bv.set(z); x = y; y = z; z = x + y; } 注意,设置为1的数位的位编号符合斐波那契数列的规律。
  • 相关阅读:
    SQL常用语句(不定期更新)包含 日期格式,取列
    前端开发 ---浏览器自动刷新
    记录Redis使用中遇到的两个问题(原子性及数据完整性)
    Linux 输出重定向
    逆向手机内核,添加调试支持及绕过反调试
    阿里2014移动安全挑战赛第二题调试笔记
    在redhat6.4上编译z3求解器
    WCF学习笔记一(概述)
    DataReader反射泛型对象
    自定义配置节点(一)
  • 原文地址:https://www.cnblogs.com/piao/p/1959686.html
Copyright © 2020-2023  润新知