logo资料库

C++Primer课后习题解答完整版.pdf

第1页 / 共138页
第2页 / 共138页
第3页 / 共138页
第4页 / 共138页
第5页 / 共138页
第6页 / 共138页
第7页 / 共138页
第8页 / 共138页
资料共138页,剩余部分请下载后查看
目录 第一章 快速入门.................................................................................................................................... 2 第二章 变量和基本类型 ........................................................................................................................... 7 第三章 标准库类型 .............................................................................................................................. 13 第四章 数组和指针 .............................................................................................................................. 21 第五章 表达式 ....................................................................................................................................... 31 第六章 语句 .......................................................................................................................................... 37 第七章 函数 .......................................................................................................................................... 37 第八章 标准 IO 库 ................................................................................................................................ 37 第九章 顺序容器 ................................................................................................................................... 43 第十章 关联容器 ................................................................................................................................... 60 第十一章 泛型算法 .............................................................................................................................. 75 第十二章 类和数据抽象 ......................................................................................................................... 86 第十三章 复制控制 .............................................................................................................................. 94 第十四章 重载操作符与转换 .................................................................................................................102 第十五章 面向对象编程 ........................................................................................................................ 116 第十六章 部分选做习题 ........................................................................................................................133 第十七章 用于大型程序的工具............................................................................................................138 第十八章 特殊工具与技术...................................................................................................................138 1
第一章 快速入门 #include int main() { 习题 1.1 查看所用的编译器文档,了解它所用的文件命名规范。编译 并运行本节的 main 程序。 【解答】 一般而言,C++编译器要求待编译的程序保存在文件中。 C++程序中一般涉及两类文件:头文件和源文件。大多数系 统中,文件的名字由文件名和文件后缀(又称扩展名)组成。 文件后缀通常表明文件的类型,如头文件的后缀可以是.h 或.hpp 等;源文件的后缀可以是.cc 或.cpp 等,具体的后 缀与使用的编译器有关。通常可以通过编译器所提供的联机 帮助文档了解其文件命名规范。 习题 1.2 修改程序使其返回-1。返回值-1 通常作为程序运行失败的 指示器。然而,系统不同,如何(甚至是否)报告 main 函 数运行失败也不同。重新编译并再次运行程序,看看你的系 统如何处理 main 函数的运行失败指示器。 【解答】 笔者所使用的 Windows 操作系统并不报告 main 函数的 运行失败,因此,程序返回-1 或返回 0 在运行效果上没有 什么区别。但是,如果在 DOS 命令提示符方式下运行程序, 然后再键入 echo %ERRORLEVEL%命令,则系统会显示返 回值-1。 习题 1.3 编一个程序,在标准输出上打印“Hello, World”。 【解答】 #include int main() { std::cout << "Hello, World" << std::endl; return 0; } 习题 1.4 我们的程序利用内置的加法操作符“+”来产生两个数的和。 编写程序,使用乘法操作符“*”产生两个数的积。 【解答】 2 std::cout << "Enter two numbers:" << std::endl; int v1, v2; std::cin >> v1 >> v2; std::cout << "The product of " << v1 << " and " << v2 << " is " << v1 * v2 << std::endl; return 0; } 习题 1.5 我们的程序使用了一条较长的输出语句。重写程序,使用单 独的语句打印每一个操作数。 【解答】 #include int main() { std::cout << "Enter two numbers:" << std::endl; int v1, v2; std::cin >> v1 >> v2; std::cout << "The sum of "; std::cout << v1; std::cout << " and "; std::cout << v2; std::cout << " is "; std::cout << v1 + v2 ; std::cout << std::endl; return 0; } 习题 1.6 解释下面的程序段: std::cout << "The sum of " << v1; << " and " << v2; << " is " << v1 + v2 << std::endl; 这段代码合法吗?如果合法,为什么?如果不合法,又为什 么? 【解答】 这段代码不合法。 注意,第 1、2、4 行的末尾有分号,表示这段代码包含三 条语句,即第 1、2 行各为一个语句,第 3、4 行构成一个
语句。“<<”为二元操作符,在第 2、3 两条语句中,第一 习题 1.9 个“<<”缺少左操作数,因此不合法。在第 2、3 行的开 下列循环做什么? sum 的最终值是多少? 头加上“std::cout”,即可更正。 int sum = 0; 习题 1.7 编译有不正确嵌套注释的程序。 【解答】 for (int i = -100; i <= 100; ++i) sum += i; 【解答】 该循环 求-100~100 之间 所有 整数的 和( 包括-100 和 由注释对嵌套导致的梦芭莎优惠券编译器错误信息通常令 100)。sum 的最终值是 0。 人迷惑。例如,在笔者所用的编译器中编译 1.3 节中给出的 带有不正确嵌套注释的程序: #include /* 习题 1.10 用 for 循环编程,求从 50~100 的所有自然数的和。然后 用 while 循环重写该程序。 * comment pairs /* */ cannot nest. 【解答】 * "cannot nest" is considered source code, 用 for 循环编写的程序如下: * as is the rest of the program #include */ int main() { return 0; } int main() { int sum = 0; for (int i = 50; i <= 100; ++i) sum += i; 编译器会给出如下错误信息: std::cout << "Sum of 50 to 100 inclusive is " error C2143: syntax error : missing ';' before '<' << sum << std::endl; error C2501: 'include' : missing storage-class or type return 0; specifiers warning C4138: '*/' found outside of comment (第 6 } 行) 用 while 循环编写的程序如下: error C2143: syntax error : missing ';' before '{' (第 8 #include 行) int main() error C2447: '{' : missing function header (old-style { formal list?)(第 8 行) 习题 1.8 指出下列输出语句哪些(如果有)是合法的。 std::cout << "/*"; std::cout << "*/"; std::cout << /* "*/" */; int sum = 0, int i = 50; while (i <= 100) { sum += i; ++i; } std::cout << "Sum of 50 to 100 inclusive is " << sum << std::endl; 预测结果,然后编译包含上述三条语句的程序,检查你的答 return 0; 案。纠正所遇到的错误。 【解答】 第一条和第二条语句合法。 } 习题 1.11 第三条语句中<<操作符之后至第二个双引号之前的部分被 用 while 循环编程,输出 10~0 递减的自然数。然后用 for 注释掉了,导致<<操作符的右操作数不是一个完整的字符 循环重写该程序。 串,所以不合法。在分号之前加上一个双引号即可更正。 【解答】 用 while 循环编写的程序如下: 3
#include 【解答】 int main() { int i = 10; while (i >= 0) { std::cout << i << " "; --i; } return 0; } 用 for 循环编写的程序如下: #include int main(www.bboby.com ) { for (int i = 10; i >= 0; --i) std::cout << i << " "; return 0; } 习题 1.12 sum 的值即为输入值。因为输入的 v1 和 v2 值相等(假设 为 x),所以 lower 和 upper 相等,均为 x。for 循环中的 循环变量 val 初始化为 lower,从而 val<=upper 为真,循 环体执行一次,sum 的值为 val(即输入值 x);然后 val 加 1,val 的值就大于 upper,循环执行结束。 习题 1.15 用两个相等的值作为输入编译并运行本节中的程序。将实际 输出与你在习题 1.14 中所做的预测相比较,解释实际结果 和你预计的结果间的不相符之处。 【解答】 运行 1.4.3 节中给出的程序,输入两个相等的值(例如 3,3), 则程序输出为: Sum of 3 to 3 inclusive is 3 与习题 1.14 中给出的预测一致。 习题 1.16 编写程序,输出用户输入的两个数中的较大者。 【解答】 #include 对比前面两个习题中所写的循环。两种形式各有何优缺点? int main() 【解答】 { 在 for 循环中,循环控制变量的初始化和修改都放在语句头 std::cout << "Enter two numbers:" << std::endl; 部分,形式较简洁,且特别适用于循环次数已知的情况。在 int v1, v2; while 循环中,循环控制变量的初始化一般放在 while 语句 std::cin >> v1 >> v2; // 读入数据 之前,循环控制变量的修改一般放在循环体中,形式上不如 if (v1 >= v2) for 语句简洁,但它比较适用于循环次数不易预知的情况(用 std::cout << "The bigger number is" << v1 << 某一条件控制循环)。两种形式各有优点,但它们在功能上 std::endl; 是等价的,可以相互转换。 else 习题 1.13 std::cout << "The bigger number is" << v2 << std::endl; 编译器不同,理解其诊断内容的难易程度也不同。编写一些 return 0; 程序,包含本小节“再谈编译”部分讨论的那些常见错误。 } 研究编译器产生的信息,这样你在编译更复杂的程序遇到这 些信息时不会陌生。 【解答】 习题 1.17 编写程序,要求用户输入一组数。输出信息说明其中有多少 对于程序中出现的错误,编译器通常会给出简略的提示信 个负数。 息,包括错误出现的文件及代码行、错误代码、错误性质的 【解答】 描述。如果要获得关于该错误的详细信息,一般可以根据编 #include 译器给出的错误代码在其联机帮助文档中查找。 int main() 习题 1.14 { int amount = 0, value; 如果输入值相等,本节展示的程序将产生什么问题? // 读入数据直到遇见文件结束符,计算所读入的负数的个数 4
while (std::cin >> value) std::cout << "Enter two numbers:" << std::endl; if (value <= 0) ++amount; int v1, v2; std::cin >> v1 >> v2; // 读入两个数 std::cout << "Amount of all negative values read is" // 用较小的数作为下界 lower、较大的数作为上界 upper << amount << std::endl; return 0; } 习题 1.18 int lower, upper ; if (v1 <= v2) { lower = v1; upper = v2; 编写程序,提示用户输入两个数并将这两个数范围内的每个 } else { 数写到标准输出。 【解答】 #include int main() { lower = v2; upper = v1; } // 输出从 lower 到 upper 之间的值 std::cout << "Values of " << lower << "to " << upper << "inclusive are: " << std::endl; std::cout << "Enter two numbers:" << std::endl; for (int val = lower, count=1; val <= upper ; ++val, int v1, v2; ++count) { std::cin >> v1 >> v2; // 读入两个数 std::cout << val << " "; // 用较小的数作为下界 lower、较大的数作为上界 upper if (count % 10 == 0) //每行输出 10 个值 int lower, upper ; if (v1 <= v2) { lower = v1; upper = v2; } else { lower = v2; upper = v1; } std::cout << std::endl; } return 0; } 粗黑体部分为主要的修改:用变量 count 记录已输出的数 的个数;若 count 的值为 10 的整数倍,则输出一个换行符。 习题 1.20 // 输出从 lower 到 upper 之间的值 编写程序,求用户指定范围内的数的和,省略设置上界和下 std::cout << "Values of " << lower << "to " 界的 if 测试。假定输入数是 7 和 3,按照这个顺序,预测程 << upper << "inclusive are: " << std::endl; 序运行结果。然后按照给定的数是 7 和 3 运行程序,看结果 for (int val = lower ; val <= upper ; ++val) 是否与你预测的相符。如果不相符,反复研究关于 for 和 std::cout << val << " "; while 循环的讨论直到弄清楚其中的原因。 return 0; } 习题 1.19 【解答】 可编写程序如下: // 1-20.cpp // 省略设置上界和下界的 if 测试,求用户指定范围内的数 如果上题给定数 1000 和 2000,程序将产生什么结果?修 的和 改程序,使每一行输出不超过 10 个数。 #include 【解答】 所有数的输出连在一起,不便于阅读。 int main() { 程序修改如下: #include int main() { std::cout << "Enter two numbers:" << std::endl; int v1, v2; std::cin >> v1 >> v2; // 读入数据 int sum = 0; 5
// 求和 for (int val = v1; val <= v2; ++val) sum += val; // sum = sum + val std::cout << "Sum of " << v1 << " to " << v2 << " inclusive is " << sum << std::endl; return 0; } #include "Sales_item.h" int main() { Sales_item trans1, trans2; // 读入交易 std::cout << "Enter two transactions:" << std::endl; std::cin >> trans1 >> trans2; if (trans1.same_isbn(trans2)) std::cout << "The total information: " << std::endl 如果输入数据为 7 和 3,则 v1 值为 7,v2 值为 3。for 语 << "ISBN, number of copies sold, " 句头中将 val 的初始值设为 7,第一次测试表达式 val <= v2 << "total revenue, and average price are:" 时,该表达式的值为 false,for 语句的循环体一次也不执行, << std::endl << trans1 + trans2; 所以求和结果 sum 为 0。 else 习题 1.21 std::cout << "The two transactions have different ISBN." 本 书 配 套 网 站 << std::endl; (http://www.awprofessional.com/cpp_primer)的第 1 return 0; 章的代码目录下有 Sales_ item.h 源文件。复制该文件到你 } 的工作目录。编写程序,循环遍历一组书的销售交易,读入 每笔交易并将交易写至标准输出。 习题 1.23 【解答】 #include #include "Sales_item.h" int main() { Sales_item book ; // 读入 ISBN,售出书的本数,销售价格 编写程序,读入几个具有相同 ISBN 的交易,输出所有读入 交易的和。 【解答】 #include #include "Sales_item.h" int main() { std::cout << "Enter transactions:" << std::endl; Sales_item total, trans; while (std::cin >> book) // 读入交易 { std::cout << "Enter transactions:" << std::endl; // 输出 ISBN,售出书的本数,总收入,平均价格 if (std::cin >> total) { std::cout << "ISBN, number of copies sold, " while (std::cin >> trans) << "total revenue, and average price are:" if (total.same_isbn(trans)) // ISBN 相同 << std::endl; std::cout << book << std::endl; total = total + trans; else { // ISBN 不同 } return 0; } 习题 1.22 std::cout << "Different ISBN." << std::endl; return –1; } // 输出交易之和 std::cout << "The total information: " << std::endl 编写程序,读入两个具有相同 ISBN 的 Sales_item 对象并 << "ISBN, number of copies sold, " 产生它们的和。 【解答】 #include << "total revenue, and average price are:" << std::endl << total; } 6
else { 行 1.6 节给出的书店程序。 std::cout << "No data?!" << std::endl; 【解答】 return –1; } return 0; } 习题 1.24 可 从 C++ Primer ( 第 4 版 ) 的 配 套 网 站 (http://www.awprofessional.com/cpp_primer)下载头文 件 Sales_item.h,然后使用该头文件编译并执行 1.6 节给出 的书店程序。 习题 1.26 编写程序,读入几笔不同的交易。对于每笔新读入的交易, 在书店程序中,我们使用了加法操作符而不是复合赋值操作 要确定它的 ISBN 是否和以前的交易的 ISBN 一样,并且记 符将 trans 加到 total 中,为什么我们不使用复合赋值操作 下每一个 ISBN 的交易的总数。通过给定多笔不同的交易来 符? 测试程序。这些交易必须代表多个不同的 ISBN,但是每个 【解答】 ISBN 的记录应分在同一组。 【解答】 #include #include "Sales_item.h" int main() { // 声明变量以保存交易记录以及具有相同 ISBN 的交易的 数目 Sales_item trans1, trans2; int amount; // 读入交易 std::cout << "Enter transactions:" << std::endl; std::cin >> trans1; amount=1; while (std::cin >> trans2) if (trans1.same_isbn(trans2))// ISBN 相同 ++amount; else { // ISBN 不同 std::cout << "Transaction amount of previous ISBN: " << amount << std::endl; trans1 = trans2; amount=1; } // 输出最后一个 ISBN 的交易数目 std::cout << "Transaction amount of the last ISBN: " << amount << std::endl; return 0; } 习题 1.25 使用源自本书配套网站的 Sales_item.h 头文件,编译并执 7 因为在 1.5.1 节中提及的 Sales_item 对象上的操作中只包 含 了 + 和 = , 没 有 包 含 += 操 作 。( 但 事 实 上 , 使 用 Sales_item.h 文件,已经可以用+=操作符取代=和+操作符 的复合使用。) 第二章 变量和基本类型 习题 2.1 int、long 和 short 类型之间有什么差别? 【解答】 它们的最小存储空间不同,分别为 16 位、32 位和 16 位。 一般而言,short 类型为半个机器字(word)长,int 类型 为一个机器字长,而 long 类型为一个或两个机器字长(在 32 位机器中,int 类型和 long 类型的字长通常是相同的)。 因此,它们的表示范围不同。 习题 2.2 unsigned 和 signed 类型有什么差别? 【解答】 前者为无符号类型,只能表示大于或等于 0 的数。后者为带 符号类型,可以表示正数、负数和 0。 习题 2.3 如果在某机器上 short 类型占 16 位,那么可以赋给 short 类型的最大数是什么?unsigned short 类型的最大数又是 什么? 【解答】 若在某机器上 short 类型占 16 位,那么可以赋给 short 类 型的最大数是 215-1,即 32767;而 unsigned short 类型 的最大数为 216-1,即 65535。
习题 2.4 当给 16 位的 unsigned short 对象赋值 100000 时,赋的 值是什么? 【解答】 34464。 3.14 为 double 型字面值,3.14f 为 float 型字面值,3.14L 为 long double 型字面值。 习题 2.8 确定下列字面值常量的类型: (a) –10 (b) -10u (c) -10. (d) -10e-2 100000 超过了 16 位的 unsigned short 类型的表示范 【解答】 围,编译器对其二进制表示截取低 16 位,相当于对 65536 (a) int 型 求余(求模,%),得 34464。 (b) unsigned int 型 习题 2.5 float 类型和 double 类型有什么差别? 【解答】 (c) double 型 (d) double 型 习题 2.9 二者的存储位数不同(一般而言,float 类型为 32 个二进 下列哪些(如果有)是非法的? 制位,double 类型为 64 个二进制位),因而取值范围不同, (a) "Who goes with F\145rgus?\012" 精度也不同(float 类型只能保证 6 位有效数字,而 double (b) 3.14e1L (c) "two" L"some" 类型至少能保证 10 位有效数字)。 习题 2.6 (d) 1024f (e) 3.14UL (f) "multiple line comment" 要计算抵押贷款的偿还金额,利率、本金和付款额应分别选 【解答】 用哪种类型?解释你选择的理由。 (c) 非法。因为字符串字面值与宽字符串字面值的连接是未 【解答】 定义的。 利率可以选择 float 类型,因为利率通常为百分之几。一般 (d) 非法。因为整数 1024 后面不能带后缀 f。 只保留到小数点后两位,所以 6 位有效数字就足以表示了。 (e) 非法。因为浮点字面值不能带后缀 U。 本金可以选择 long 类型,因为本金通常为整数。long 类 (f) 非法。因为分两行书写的字符串字面值必须在第一行的 型可表示的最大整数一般为 231-1(即 2147483647),应 末尾加上反斜线。 该足以表示了。付款额一般为实数,可以选择 double 类型, 因为 float 类型的 6 位有效数字可能不足以表示。 习题 2.10 习题 2.7 使用转义字符编写一段程序,输出 2M,然后换行。修改程 序,输出 2,跟着一 解释下列字面值常量的不同之处。 个制表符,然后是 M,最后是换行符。 (a) 'a',L'a',"a",L"a" (b) 10,10u,10L,10uL,012,0xC (c) 3.14,3.14f,3.14L 【解答】 (a) 'a',L'a',"a",L"a" 【解答】 输出 2M、然后换行的程序段: // 输出"2M"和换行字符 std::cout << "2M" << '\n'; 修改后的程序段: 'a'为 char 型字面值,L'a'为 wchar_t 型字面值,"a"为字符 // 输出'2', '\t', 'M'和换行字符 串字面值,L"a"为宽字符串字面值。 (b) 10,10u,10L,10uL,012,0xC 10 为 int 型字面值,10u 为 unsigned 型字面值,10L 为 std::cout << '2' << '\t' << 'M' << '\n'; 习题 2.11 long 型字面值,10uL 为 unsigned long 型字面值,012 为 编写程序,要求用户输入两个数——底数(base)和指数 八进制表示的 int 型字面值,0xC 为十六进制表示的 int 型 (exponent),输出 字面值。 (c) 3.14,3.14f,3.14L 底数的指数次方的结果。 【解答】 8
分享到:
收藏