3.13 练习
部分练习题的答案可以在本书的电子文档“Annotated Solution Guide for Thinking in C++”中找到,只需支付很少的费用就可以从http://www.BruceEckel.com得到这个电子文档。
3-1 建立一个头文件(扩展名为‘.h’)。在该文件中,声明一组函数,具有可变参数,返回值包括void、char、int和float类型。建立一个包含上述头文件的.cpp文件,创建所有这些函数的定义。每个定义应该简单地输出函数名,参数列表,并返回类型以便知道它已经被调用。创建另外一个.cpp文件,它包含头文件且定义int main(),在其中调用已经定义的所有函数。编译和运行这个程序。
3-2 编写一个程序使用两重for循环和模运算符(%)去寻找和输出质数(只能被1和它本身整除的整数)。
3-3 编写一个程序,使用一个while循环从标准输入(cin)中把单词读入到string中。这是一个“无穷”while循环,可以使用break语句中断(和退出程序)。对于读入的每个单词,先用一系列的if语句把该单词“映射”为一个整数值,然后用该整数值作为一个switch语句的选择条件(这些操作并不意味着是良好的设计风格,这仅仅是为练习这些控制流程)。在每个case中,输出一些有意义的信息。判定哪些是“有趣“的单词以及这些单词的意义。同时判定哪个单词是程序结束的标志。用文件作为输入来测试该程序(如果想节省输入,这个文件将作为程序的源文件)。
3-4 修改Menu.cpp程序,使用switch语句代替if语句。
3-5 编写一个程序计算在“优先级”一节中的两个表达式的值。
3-6 修改YourPets2.cpp程序以使用不同的数据类型(char、int、float、double和这些类型的变型)。运行该程序并画出结果内存分布图。如果能在多种机器、操作系统或者编译器上运行该程序,用尽可能多的变化进行这个试验。
3-7 创建两个函数,一个接受一个string*参数,另一个接受一个string&参数。每个函数必须用它特有的方式去改变外部的string对象。在main()中,创建和初始化一个string对象,输出它,然后把它传给每个函数,输出结果。
3-8 编写一个使用所有三个图形字符(trigraph)的程序,看看你的编译器是否支持它们。
3-9 编译和运行Static.cpp程序。从代码中删除static关键词,再次编译和运行,解释发生的现象。
3-10 试编译FileStatic.cpp和FileStatic2.cpp程序并把它们连接起来。得到的错误消息的含义是什么?
3-11 修改Boolean.cpp程序,用double值代替int值。
3-12 修改Boolean.cpp和Bitwise.cpp程序,使用显式运算符(如果你的编译器与C++标准兼容,那么它会支持这些运算符)。
3-13 使用在Rotation.cpp程序中的函数去修改Bitwise.cpp程序。确保用这种方式能清楚地显示在旋转过程中的结果。
3-14 修改Ifthen.cpp程序,使用三重if-else运算符(?:)。
3-15 创建一个含有两个string对象和一个int对象的struct。使用typedef为该struct命名。创建struct的一个实例,初始化实例的三个值,然后输出它们。获得实例的地址,然后赋值给定义的struct类型的指针。改变实例的三个值,然后通过指针把它们打印出来。
3-16 编制一个使用颜色枚举类型的程序。创建一个enum类型的变量,然后用for循环输出与颜色名对应的数字。
3-17 用Union.cpp程序做一个试验,删除各种union元素,观察对union大小的影响。试给该union的一个元素赋值(属于某一类型),然后通过不同的元素(属于不同的类型)输出它的值,看看发生了什么情况。
3-18 编制一个程序,连续定义两个int数组。第二个数组的开始下标紧接第一个数组的结束下标。给两个数组赋值。打印出第二个数组观察由此引起的变化。再在两个数组定义之间定义一个char变量,重复上述操作。可以创建一个数组输出函数以简化程序。
3-19 修改ArrayAddresses.cpp程序,使之能处理char、long、int、float以及double类型数据。
3-20 运用ArrayAddresses.cpp程序中的技术,输出在StructArray.cpp程序中定义的struct的大小以及数组元素的地址。
3-21 创建一个string对象数组且对每一个元素赋一个字符串。用for循环输出该数组。
3-22 在ArgsToInts.cpp的基础上,编制两个新程序,它们各自使用atol()和atof()函数。
3-23 修改PointerIncrement2.cpp程序,其中用union代替struct。
3-24 修改PointerArithmetic.cpp程序,其中使用long和long double。
3-25 定义一个float变量。获得它的地址,把地址转化为unsigned char,赋值给一个unsigned char指针。使用指针和[]符号引用float变量中的下标,并用本章中定义的printBinary()函数输出该float的内存映像。(从0到sizeof(float))。改变该float变量的值看看是否能推算出下一步的情况(float包含编码的数据)。
3-26定义一个int数组。获得该数组的起始地址,使用static_cast把它转化为void。写一个带以下参数的函数:一个void、一个数字(表明字节的数目)和一个值(表明每个字节需要设定的值)。该函数必须为特定范围内的每个字节设定特定的值。在这个int数组上试验函数。
3-27 建立一个const double类型数组和一个volatile double类型数组。通过引用每个数组的下标且用const_cast把每个元素分别转换为non-const和non-volatile,然后对每个元素赋值。
3-28 建立一个函数,该函数接受一个指向double类型数组的指针和一个表明该数组大小的值。该函数应该输出数组中的每个元素值。现在建立一个double类型的数组,且初始化每个元素的值为0,然后使用你的函数输出该数组。接着使用reinterpret_cast关键字把数组的起始地址转化为unsigned char*,把每个元素值设置为1(提示:必须用sizeof运算符计算一个double类型变量包含的字节数)。现在使用你的数组输出函数输出结果。想想为什么每个元素值不设成1.0?
3-29(带有挑战性)修改FloatingAsBinary.cpp程序以便能够以单独的二进制位组输出double类型数据。为实现目标,必须用自己的特殊代码(可以从printBinary()函数中衍生)去替换对printBinary()的调用,还必须查阅并理解自己的编译器的浮点数字节格式(这是具有挑战性的部分)。
3-30 创建makefile文件,可以把编译YourPets1.cpp和YourPets2.cpp程序(用你特定的编译器)以及执行这两个程序作为默认的目标,确保使用后缀规则。
3-31 修改StringizingExpressions.cpp程序,通过设置一个命令行标志,使得P(A)能用条件#ifdef与调试代码分离开。需要参考编译器文档,了解在命令行上怎样定义和取消定义预处理的值。
3-32 定义一个函数,该函数接受一个double型参数且返回一个int值。创建和初始化一个指向该函数的指针,通过这个指针调用这个函数。
3-33 声明一个函数,该函数接受一个int参数且返回指向另一个函数的指针,这个函数接受一个char变量且返回一个float值。
3-34 修改FunctionTable.cpp程序使每个函数返回一个string(而不是输出一个消息)以便在main()函数中输出。
3-35 为前面某个练习(自己选择)建立一个makefile文件,允许键入make以构建这个程序,并且键入make debug以构建带有调试信息的程序。