第一章 开始

练习1.1

查阅你使用的编译器的文档,确定它所使用的文件名约定。编译并运行第2页的main程序。

解:

  • g++ --std=c++11 ch1.cpp -o main
  • ./main

练习1.2

改写程序,让它返回-1。返回值-1通常被当做程序错误的标识。重新编译并运行你的程序,观察你的系统如何处理main返回的错误标识。

解:

  • 在ubuntu下,使用g++,返回-1,./main没有发现任何异常。
  • echo $?,返回255。

练习1.3

编写程序,在标准输出上打印Hello, World。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. std::cout << "Hello, World" << std::endl;
  5. return 0;
  6. }

练习1.4

我们的程序使用加法运算符+来将两个数相加。编写程序使用乘法运算符*,来打印两个数的积。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. std::cout << "Enter two numbers:" << std::endl;
  5. int v1 = 0, v2 = 0;
  6. std::cin >> v1 >> v2;
  7. std::cout << "The product of " << v1 << " and " << v2
  8. << " is " << v1 * v2 << std::endl;
  9. }

练习1.5

我们将所有的输出操作放在一条很长的语句中,重写程序,将每个运算对象的打印操作放在一条独立的语句中。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. std::cout << "Enter two numbers:" << std::endl;
  5. int v1 = 0, v2 = 0;
  6. std::cin >> v1 >> v2;
  7. std::cout << "The product of ";
  8. std::cout << v1;
  9. std::cout << " and ";
  10. std::cout << v2;
  11. std::cout << " is ";
  12. std::cout << v1 * v2;
  13. std::cout << std::endl;
  14. }

练习1.6

解释下面程序片段是否合法。

  1. std::cout << "The sum of " << v1;
  2. << " and " << v2;
  3. << " is " << v1 + v2 << std::endl;

如果程序是合法的,它的输出是什么?如果程序不合法,原因何在?应该如何修正?

解:

程序不合法,有多余的分号,修改如下:

  1. std::cout << "The sum of " << v1
  2. << " and " << v2
  3. << " is " << v1 + v2 << std::endl;

练习1.7

编译一个包含不正确的嵌套注释的程序,观察编译器返回的错误信息。

解:

  1. /* 正常注释 /* 嵌套注释 */ 正常注释*/

错误信息:

  1. /* 正常注释 /* 嵌套注释 */ 正常注释*/
  2. ^
  3. ch1.cpp:97:37: error: stray \255 in program
  4. ch1.cpp:97:37: error: stray \243 in program
  5. ch1.cpp:97:37: error: stray \345 in program
  6. ch1.cpp:97:37: error: stray \270 in program
  7. ch1.cpp:97:37: error: stray \270 in program
  8. ch1.cpp:97:37: error: stray \346 in program
  9. ch1.cpp:97:37: error: stray \263 in program
  10. ch1.cpp:97:37: error: stray \250 in program
  11. ch1.cpp:97:37: error: stray \351 in program
  12. ch1.cpp:97:37: error: stray \207 in program
  13. ch1.cpp:97:37: error: stray \212 in program
  14. ch1.cpp: In function int main()’:
  15. ch1.cpp:97:50: error: expected primary-expression before ‘/’ token
  16. /* 正常注释 /* 嵌套注释 */ 正常注释*/
  17. ^
  18. ch1.cpp:98:5: error: expected primary-expression before return
  19. return 0;
  20. ^

练习1.8

指出下列哪些输出语句是合法的(如果有的话):

  1. std::cout << "/*";
  2. std::cout << "*/";
  3. std::cout << /* "*/" */;
  4. std::cout << /* "*/" /* "/*" */;

预测编译这些语句会产生什么样的结果,实际编译这些语句来验证你的答案(编写一个小程序,每次将上述一条语句作为其主体),改正每个编译错误。

解:

只有第三句编译出错,改成如下即可:

  1. std::cout << /* "*/" */";

第四句等价于输出 " /* "

练习1.9

编写程序,使用while循环将50到100整数相加。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. int sum = 0, val = 50;
  5. while (val <= 100){
  6. sum += val;
  7. val += 1;
  8. }
  9. std::cout << "Sum of 50 to 100 inclusive is "
  10. << sum << std::endl;
  11. }

练习1.10

除了++运算符将运算对象的值增加1之外,还有一个递减运算符--实现将值减少1.编写程序与,使用递减运算符在循环中按递减顺序打印出10到0之间的整数。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. int val = 10;
  5. while (val >= 0){
  6. std::cout << val << " ";
  7. val -= 1;
  8. }
  9. std::cout << std::endl;
  10. }

练习1.11

编写程序,提示用户输入两个整数,打印出这两个整数所指定的范围内的所有整数。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. int start = 0, end = 0;
  5. std::cout << "Please input two num: ";
  6. std::cin >> start >> end;
  7. if (start <= end) {
  8. while (start <= end){
  9. std::cout << start << " ";
  10. ++start;
  11. }
  12. std::cout << std::endl;
  13. }
  14. else{
  15. std::cout << "start should be smaller than end !!!";
  16. }
  17. }

练习1.12

下面的for循环完成了什么功能?sum的终值是多少?

  1. int sum = 0;
  2. for (int i = -100; i <= 100; ++i)
  3. sum += i;

解:

从-100加到100,sum的终值是0。

练习1.13

使用for循环重做1.4.1节中的所有练习(练习1.9到1.11)。

解:

练习1.9

  1. #include <iostream>
  2. int main()
  3. {
  4. int sum = 0;
  5. for (int val = 50; val <= 100; ++val){
  6. sum += val;
  7. }
  8. std::cout << "Sum of 50 to 100 inclusive is "
  9. << sum << std::endl;
  10. }

练习1.10

  1. #include <iostream>
  2. int main()
  3. {
  4. for (int val = 10; val >=0; --val){
  5. std::cout << val << " ";
  6. }
  7. std::cout << std::endl;
  8. }

练习1.11

  1. #include <iostream>
  2. int main()
  3. {
  4. int start = 0, end = 0;
  5. std::cout << "Please input two num: ";
  6. std::cin >> start >> end;
  7. if (start <= end) {
  8. for (; start <= end; ++start){
  9. std::cout << start << " ";
  10. }
  11. std::cout << std::endl;
  12. }
  13. else{
  14. std::cout << "start should be smaller than end !!!";
  15. }
  16. }

练习1.14

对比for循环和while循环,两种形式的优缺点各是什么?

解:

  1. The main difference between the `for`'s and the `while`'s is a matter of pragmatics:
  2. we usually use `for` when there is a known number of iterations,
  3. and use `while` constructs when the number of iterations in not known in advance.
  4. The `while` vs `do ... while` issue is also of pragmatics,
  5. the second executes the instructions once at start,
  6. and afterwards it behaves just like the simple `while`.

练习1.15

编写程序,包含第14页“再探编译”中讨论的常见错误。熟悉编译器生成的错误信息。

解:

编译器可以检查出的错误有:

  • 语法错误
  • 类型错误
  • 声明错误

练习1.16

编写程序,从cin读取一组数,输出其和。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. int sum = 0;
  5. for (int value = 0; std::cin >> value; )
  6. sum += value;
  7. std::cout << sum << std::endl;
  8. return 0;
  9. }

练习1.17

如果输入的所有值都是相等的,本节的程序会输出什么?如果没有重复值,输出又会是怎样的?

练习1.18

编译并运行本节的程序,给它输入全都相等的值。再次运行程序,输入没有重复的值。

解:

全部重复:

  1. 1 1 1 1 1
  2. 1 occurs 5 times

没有重复:

  1. 1 2 3 4 5
  2. 1 occurs 1 times
  3. 2 occurs 1 times
  4. 3 occurs 1 times
  5. 4 occurs 1 times
  6. 5 occurs 1 times

练习1.19

修改你为1.4.1节练习1.11(第11页)所编写的程序(打印一个范围内的数),使其能处理用户输入的第一个数比第二个数小的情况。

解:

  1. #include <iostream>
  2. int main()
  3. {
  4. int start = 0, end = 0;
  5. std::cout << "Please input two num: ";
  6. std::cin >> start >> end;
  7. if (start <= end) {
  8. while (start <= end){
  9. std::cout << start << " ";
  10. ++start;
  11. }
  12. std::cout << std::endl;
  13. }
  14. else{
  15. std::cout << "start should be smaller than end !!!";
  16. }
  17. }

练习1.20

在网站http://www.informit.com/title/032174113 上,第1章的代码目录包含了头文件 Sales_item.h。将它拷贝到你自己的工作目录中。用它编写一个程序,读取一组书籍销售记录,将每条记录打印到标准输出上。

解:

  1. #include <iostream>
  2. #include "Sales_item.h"
  3. int main()
  4. {
  5. for (Sales_item item; std::cin >> item; std::cout << item << std::endl);
  6. return 0;
  7. }

命令:

  1. ./main < data/add_item

输出:

  1. 0-201-78345-X 3 60 20
  2. 0-201-78345-X 2 50 25

练习1.21

编写程序,读取两个 ISBN 相同的 Sales_item 对象,输出他们的和。

解:

  1. #include <iostream>
  2. #include "Sales_item.h"
  3. int main()
  4. {
  5. Sales_item item_1;
  6. Sales_item item_2;
  7. std::cin >> item_1;
  8. std::cout << item_1 << std::endl;
  9. std::cin >> item_2;
  10. std::cout << item_2 << std::endl;
  11. std::cout << "sum of sale items: " << item_1 + item_2 << std::endl;
  12. return 0;
  13. }

命令:

  1. ./main < data/add_item

输出:

  1. 0-201-78345-X 3 60 20
  2. 0-201-78345-X 2 50 25
  3. sum of sale items: 0-201-78345-X 5 110 22

练习1.22

编写程序,读取多个具有相同 ISBN 的销售记录,输出所有记录的和。

解:

  1. #include <iostream>
  2. #include "Sales_item.h"
  3. int main()
  4. {
  5. Sales_item sum_item;
  6. std::cin >> sum_item;
  7. std::cout << sum_item << std::endl;
  8. for (Sales_item item; std::cin >> item; std::cout << item << std::endl){
  9. sum_item += item;
  10. }
  11. std::cout << "sum of sale items: " << sum_item << std::endl;
  12. return 0;
  13. }

命令:

  1. ./main < data/add_item

输出:

  1. 0-201-78345-X 3 60 20
  2. 0-201-78345-X 2 50 25
  3. sum of sale items: 0-201-78345-X 5 110 22

练习1.23

编写程序,读取多条销售记录,并统计每个 ISBN(每本书)有几条销售记录。

练习1.24

输入表示多个 ISBN 的多条销售记录来测试上一个程序,每个 ISBN 的记录应该聚在一起。

解:

  1. #include <iostream>
  2. #include "Sales_item.h"
  3. int main()
  4. {
  5. Sales_item total;
  6. if (std::cin >> total){
  7. Sales_item trans;
  8. while (std::cin >> trans){
  9. if (total.isbn() == trans.isbn()) {
  10. total += trans;
  11. }
  12. else {
  13. std::cout << total << std::endl;
  14. total = trans;
  15. }
  16. }
  17. std::cout << total << std::endl;
  18. }
  19. else {
  20. std::cerr << "No data?!" << std::endl;
  21. return -1;
  22. }
  23. return 0;
  24. }

命令:

  1. ./main < data/book_sales

输出:

  1. 0-201-70353-X 4 99.96 24.99
  2. 0-201-82470-1 4 181.56 45.39
  3. 0-201-88954-4 16 198 12.375
  4. 0-399-82477-1 5 226.95 45.39
  5. 0-201-78345-X 5 110 22

练习1.25

借助网站上的Sales_item.h头文件,编译并运行本节给出的书店程序。