第三章 字符串、向量和数组

练习3.1

使用恰当的using 声明重做 1.4.1节和2.6.2节的练习。

解:

1.4.1

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

2.6.2 类似

练习3.2

编写一段程序从标准输入中一次读入一行,然后修改该程序使其一次读入一个词。

解:

一次读入一行:

  1. #include <iostream>
  2. #include <string>
  3. using std::string;
  4. using std::cin;
  5. using std::cout;
  6. using std::endl;
  7. using std::getline;
  8. int main()
  9. {
  10. string s;
  11. while (getline(cin,s))
  12. {
  13. cout << s << endl;
  14. }
  15. return 0;
  16. }

一次读入一个词

  1. #include <iostream>
  2. #include <string>
  3. using std::string;
  4. using std::cin;
  5. using std::cout;
  6. using std::endl;
  7. using std::getline;
  8. int main()
  9. {
  10. string s;
  11. while (cin >> s)
  12. {
  13. cout << s << endl;
  14. }
  15. return 0;
  16. }

练习3.3

请说明string类的输入运算符和getline函数分别是如何处理空白字符的。

解:

  • 类似is >> s的读取:string对象会忽略开头的空白并从第一个真正的字符开始,直到遇见下一空白为止。
  • 类似getline(is, s)的读取:string对象会从输入流中读取字符,直到遇见换行符为止。

练习3.4

编写一段程序读取两个字符串,比较其是否相等并输出结果。如果不相等,输出比较大的那个字符串。改写上述程序,比较输入的两个字符串是否等长,如果不等长,输出长度较大的那个字符串。

解:

比较大的

  1. #include <iostream>
  2. #include <string>
  3. using std::string;
  4. using std::cin;
  5. using std::cout;
  6. using std::endl;
  7. int main()
  8. {
  9. string str1, str2;
  10. while (cin >> str1 >> str2)
  11. {
  12. if (str1 == str2)
  13. cout << "The two strings are equal." << endl;
  14. else
  15. cout << "The larger string is " << ((str1 > str2) ? str1 : str2);
  16. }
  17. return 0;
  18. }

长度大的

  1. #include <iostream>
  2. #include <string>
  3. using std::string;
  4. using std::cin;
  5. using std::cout;
  6. using std::endl;
  7. int main()
  8. {
  9. string str1, str2;
  10. while (cin >> str1 >> str2)
  11. {
  12. if (str1.size() == str2.size())
  13. cout << "The two strings have the same length." << endl;
  14. else
  15. cout << "The longer string is " << ((str1.size() > str2.size()) ? str1 : str2) << endl;
  16. }
  17. return 0;
  18. }

练习3.5

编写一段程序从标准输入中读入多个字符串并将他们连接起来,输出连接成的大字符串。然后修改上述程序,用空格把输入的多个字符串分割开来。

解:

未隔开的:

  1. #include <iostream>
  2. #include <string>
  3. using std::string;
  4. using std::cin;
  5. using std::cout;
  6. using std::endl;
  7. int main()
  8. {
  9. string result, s;
  10. while (cin >> s)
  11. {
  12. result += s;
  13. }
  14. cout << result << endl;
  15. return 0;
  16. }

隔开的:

  1. #include <iostream>
  2. #include <string>
  3. using std::string;
  4. using std::cin;
  5. using std::cout;
  6. using std::endl;
  7. int main()
  8. {
  9. string result, s;
  10. while (cin >> s)
  11. {
  12. result += s + " ";
  13. }
  14. cout << result << endl;
  15. return 0;
  16. }

练习3.6

编写一段程序,使用范围for语句将字符串内所有字符用X代替。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. using std::string;
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. int main()
  9. {
  10. string s = "this is a string";
  11. for (auto &x : s)
  12. {
  13. x = 'X';
  14. }
  15. cout << s << endl;
  16. return 0;
  17. }

练习3.7

就上一题完成的程序而言,如果将循环控制的变量设置为char将发生什么?先估计一下结果,然后实际编程进行验证。

解:

如果设置为char,那么原来的字符串不会发生改变。

练习3.8

分别用while循环和传统for循环重写第一题的程序,你觉得哪种形式更好呢?为什么?

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. using std::string;
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. int main()
  9. {
  10. string s = "this is a string";
  11. decltype(s.size()) i = 0;
  12. while (i != s.size())
  13. {
  14. s[i] = 'X';
  15. ++i;
  16. }
  17. cout << s << endl;
  18. for (i = 0; i != s.size(); ++i)
  19. {
  20. s[i] = 'Y';
  21. }
  22. cout << s << endl;
  23. return 0;
  24. }

范围for语句更好,不直接操作索引,更简洁。

练习3.9

下面的程序有何作用?它合法吗?如果不合法?为什么?

  1. string s;
  2. cout << s[0] << endl;

解:

不合法。使用下标访问空字符串是非法的行为。

练习3.10

编写一段程序,读入一个包含标点符号的字符串,将标点符号去除后输出字符串剩余的部分。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. using std::string;
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. int main()
  9. {
  10. string s = "this, is. a :string!";
  11. string result;
  12. for (auto x : s)
  13. {
  14. if (!ispunct(x))
  15. {
  16. result += x;
  17. }
  18. }
  19. cout << result << endl;
  20. return 0;
  21. }

练习3.11

下面的范围for语句合法吗?如果合法,c的类型是什么?

  1. const string s = "Keep out!";
  2. for(auto &c : s){ /* ... */ }

解:

要根据for循环中的代码来看是否合法,c是string 对象中字符的引用,s是常量。因此如果for循环中的代码重新给c赋值就会非法,如果不改变c的值,那么合法。

练习3.12

下列vector对象的定义有不正确的吗?如果有,请指出来。对于正确的,描述其执行结果;对于不正确的,说明其错误的原因。

  1. vector<vector<int>> ivec; // 在C++11当中合法
  2. vector<string> svec = ivec; // 不合法,类型不一样
  3. vector<string> svec(10, "null"); // 合法

练习3.13

下列的vector对象各包含多少个元素?这些元素的值分别是多少?

  1. vector<int> v1; // size:0, no values.
  2. vector<int> v2(10); // size:10, value:0
  3. vector<int> v3(10, 42); // size:10, value:42
  4. vector<int> v4{ 10 }; // size:1, value:10
  5. vector<int> v5{ 10, 42 }; // size:2, value:10, 42
  6. vector<string> v6{ 10 }; // size:10, value:""
  7. vector<string> v7{ 10, "hi" }; // size:10, value:"hi"

练习3.14

编写一段程序,用cin读入一组整数并把它们存入一个vector对象。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. #include <vector>
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. using std::vector;
  9. int main()
  10. {
  11. vector<int> v;
  12. int i;
  13. while (cin >> i)
  14. {
  15. v.push_back(i);
  16. }
  17. return 0;
  18. }

练习3.15

改写上题程序,不过这次读入的是字符串。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. #include <vector>
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. using std::vector;
  9. using std::string;
  10. int main()
  11. {
  12. vector<string> v;
  13. string i;
  14. while (cin >> i)
  15. {
  16. v.push_back(i);
  17. }
  18. return 0;
  19. }

练习3.16

编写一段程序,把练习3.13中vector对象的容量和具体内容输出出来

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. #include <vector>
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. using std::vector;
  9. using std::string;
  10. int main()
  11. {
  12. vector<int> v1; // size:0, no values.
  13. vector<int> v2(10); // size:10, value:0
  14. vector<int> v3(10, 42); // size:10, value:42
  15. vector<int> v4{ 10 }; // size:1, value:10
  16. vector<int> v5{ 10, 42 }; // size:2, value:10, 42
  17. vector<string> v6{ 10 }; // size:10, value:""
  18. vector<string> v7{ 10, "hi" }; // size:10, value:"hi"
  19. cout << "v1 size :" << v1.size() << endl;
  20. cout << "v2 size :" << v2.size() << endl;
  21. cout << "v3 size :" << v3.size() << endl;
  22. cout << "v4 size :" << v4.size() << endl;
  23. cout << "v5 size :" << v5.size() << endl;
  24. cout << "v6 size :" << v6.size() << endl;
  25. cout << "v7 size :" << v7.size() << endl;
  26. cout << "v1 content: ";
  27. for (auto i : v1)
  28. {
  29. cout << i << " , ";
  30. }
  31. cout << endl;
  32. cout << "v2 content: ";
  33. for (auto i : v2)
  34. {
  35. cout << i << " , ";
  36. }
  37. cout << endl;
  38. cout << "v3 content: ";
  39. for (auto i : v3)
  40. {
  41. cout << i << " , ";
  42. }
  43. cout << endl;
  44. cout << "v4 content: ";
  45. for (auto i : v4)
  46. {
  47. cout << i << " , ";
  48. }
  49. cout << endl;
  50. cout << "v5 content: ";
  51. for (auto i : v5)
  52. {
  53. cout << i << " , ";
  54. }
  55. cout << endl;
  56. cout << "v6 content: ";
  57. for (auto i : v6)
  58. {
  59. cout << i << " , ";
  60. }
  61. cout << endl;
  62. cout << "v7 content: ";
  63. for (auto i : v7)
  64. {
  65. cout << i << " , ";
  66. }
  67. cout << endl;
  68. return 0;
  69. }

练习3.17

从cin读入一组词并把它们存入一个vector对象,然后设法把所有词都改为大写形式。输出改变后的结果,每个词占一行。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. #include <vector>
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. using std::vector;
  9. using std::string;
  10. int main()
  11. {
  12. vector<string> v;
  13. string s;
  14. while (cin >> s)
  15. {
  16. v.push_back(s);
  17. }
  18. for (auto &str : v)
  19. {
  20. for (auto &c : str)
  21. {
  22. c = toupper(c);
  23. }
  24. }
  25. for (auto i : v)
  26. {
  27. cout << i << endl;
  28. }
  29. return 0;
  30. }

练习3.18

下面的程序合法吗?如果不合法,你准备如何修改?

  1. vector<int> ivec;
  2. ivec[0] = 42;

解:

不合法。应改为:

  1. ivec.push_back(42);

练习3.19

如果想定义一个含有10个元素的vector对象,所有元素的值都是42,请例举三种不同的实现方法,哪种方式更好呢?

如下三种:

  1. vector<int> ivec1(10, 42);
  2. vector<int> ivec2{ 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
  3. vector<int> ivec3;
  4. for (int i = 0; i < 10; ++i)
  5. ivec3.push_back(42);

第一种方式最好。

练习3.20

读入一组整数并把他们存入一个vector对象,将每对相邻整数的和输出出来。改写你的程序,这次要求先输出第一个和最后一个元素的和,接着输出第二个和倒数第二个元素的和,以此类推。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. #include <vector>
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. using std::vector;
  9. using std::string;
  10. int main()
  11. {
  12. vector<int> ivec;
  13. int i;
  14. while (cin >> i)
  15. {
  16. ivec.push_back(i);
  17. }
  18. for (int i = 0; i < ivec.size() - 1; ++i)
  19. {
  20. cout << ivec[i] + ivec[i + 1] << endl;
  21. }
  22. //---------------------------------
  23. cout << "---------------------------------" << endl;
  24. int m = 0;
  25. int n = ivec.size() - 1;
  26. while (m < n)
  27. {
  28. cout << ivec[m] + ivec[n] << endl;
  29. ++m;
  30. --n;
  31. }
  32. return 0;
  33. }

练习3.21

请使用迭代器重做3.3.3节的第一个练习。

解:

  1. #include <vector>
  2. #include <iterator>
  3. #include <string>
  4. #include <iostream>
  5. using std::vector;
  6. using std::string;
  7. using std::cout;
  8. using std::endl;
  9. void check_and_print(const vector<int>& vec)
  10. {
  11. cout << "size: " << vec.size() << " content: [";
  12. for (auto it = vec.begin(); it != vec.end(); ++it)
  13. cout << *it << (it != vec.end() - 1 ? "," : "");
  14. cout << "]\n" << endl;
  15. }
  16. void check_and_print(const vector<string>& vec)
  17. {
  18. cout << "size: " << vec.size() << " content: [";
  19. for (auto it = vec.begin(); it != vec.end(); ++it)
  20. cout << *it << (it != vec.end() - 1 ? "," : "");
  21. cout << "]\n" << endl;
  22. }
  23. int main()
  24. {
  25. vector<int> v1;
  26. vector<int> v2(10);
  27. vector<int> v3(10, 42);
  28. vector<int> v4{ 10 };
  29. vector<int> v5{ 10, 42 };
  30. vector<string> v6{ 10 };
  31. vector<string> v7{ 10, "hi" };
  32. check_and_print(v1);
  33. check_and_print(v2);
  34. check_and_print(v3);
  35. check_and_print(v4);
  36. check_and_print(v5);
  37. check_and_print(v6);
  38. check_and_print(v7);
  39. return 0;
  40. }

练习3.22

修改之前那个输出text第一段的程序,首先把text的第一段全部改成大写形式,然后输出它。

解: 略

练习3.23

编写一段程序,创建一个含有10个整数的vector对象,然后使用迭代器将所有元素的值都变成原来的两倍。输出vector对象的内容,检验程序是否正确。

解:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. int main()
  5. {
  6. vector<int> v(10, 1);
  7. for (auto it=v.begin(); it!=v.end(); it++){
  8. *it *= 2;
  9. }
  10. for (auto one : v){
  11. cout << one <<endl;
  12. }
  13. return 0;
  14. }

练习3.24

请使用迭代器重做3.3.3节的最后一个练习。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cctype>
  4. #include <vector>
  5. using std::cin;
  6. using std::cout;
  7. using std::endl;
  8. using std::vector;
  9. using std::string;
  10. int main()
  11. {
  12. vector<int> ivec;
  13. int i;
  14. while (cin >> i)
  15. {
  16. ivec.push_back(i);
  17. }
  18. for (auto it = ivec.begin(); it != ivec.end() - 1; ++it)
  19. {
  20. cout << *it + *(it + 1) << endl;
  21. }
  22. //---------------------------------
  23. cout << "---------------------------------" << endl;
  24. auto it1 = ivec.begin();
  25. auto it2 = ivec.end() - 1;
  26. while (it1 < it2)
  27. {
  28. cout << *it1 + *it2 << endl;
  29. ++it1;
  30. --it2;
  31. }
  32. return 0;
  33. }

练习3.25

3.3.3节划分分数段的程序是使用下标运算符实现的,请利用迭代器改写该程序实现完全相同的功能。

解:

  1. #include <vector>
  2. #include <iostream>
  3. using std::vector; using std::cout; using std::cin; using std::endl;
  4. int main()
  5. {
  6. vector<unsigned> scores(11, 0);
  7. unsigned grade;
  8. while (cin >> grade)
  9. {
  10. if (grade <= 100)
  11. ++*(scores.begin() + grade / 10);
  12. }
  13. for (auto s : scores)
  14. cout << s << " ";
  15. cout << endl;
  16. return 0;
  17. }

练习3.26

在100页的二分搜索程序中,为什么用的是 mid = beg + (end - beg) / 2, 而非 mid = (beg + end) / 2 ; ?

解:

因为两个迭代器相互之间支持的运算只有 - ,而没有 +
但是迭代器和迭代器差值(整数值)之间支持 +

练习3.27

假设txt_size是一个无参函数,它的返回值是int。请回答下列哪个定义是非法的,为什么?

  1. unsigned buf_size = 1024;
  2. (a) int ia[buf_size];
  3. (b) int ia[4 * 7 - 14];
  4. (c) int ia[txt_size()];
  5. (d) char st[11] = "fundamental";

解:

  • (a) 非法。维度必须是一个常量表达式。
  • (b) 合法。
  • (c) 非法。txt_size() 的值必须要到运行时才能得到。
  • (d) 非法。数组的大小应该是12。

练习3.28

下列数组中元素的值是什么?

  1. string sa[10];
  2. int ia[10];
  3. int main() {
  4. string sa2[10];
  5. int ia2[10];
  6. }

解:

数组的元素会被默认初始化。
sa的元素值全部为空字符串,ia 的元素值全部为0。
sa2的元素值全部为空字符串,ia2的元素值全部未定义。

练习3.29

相比于vector 来说,数组有哪些缺点,请例举一些。

解:

  • 数组的大小是确定的。
  • 不能随意增加元素。
  • 不允许拷贝和赋值。

练习3.30

指出下面代码中的索引错误。

  1. constexpr size_t array_size = 10;
  2. int ia[array_size];
  3. for (size_t ix = 1; ix <= array_size; ++ix)
  4. ia[ix] = ix;

解:

ix增长到 10 的时候,ia[ix]的下标越界。

练习3.31

编写一段程序,定义一个含有10个int的数组,令每个元素的值就是其下标值。

  1. #include <iostream>
  2. using std::cout; using std::endl;
  3. int main()
  4. {
  5. int arr[10];
  6. for (auto i = 0; i < 10; ++i) arr[i] = i;
  7. for (auto i : arr) cout << i << " ";
  8. cout << endl;
  9. return 0;
  10. }

练习3.32

将上一题刚刚创建的数组拷贝给另一数组。利用vector重写程序,实现类似的功能。

  1. #include <iostream>
  2. #include <vector>
  3. using std::cout; using std::endl; using std::vector;
  4. int main()
  5. {
  6. // array
  7. int arr[10];
  8. for (int i = 0; i < 10; ++i) arr[i] = i;
  9. int arr2[10];
  10. for (int i = 0; i < 10; ++i) arr2[i] = arr[i];
  11. // vector
  12. vector<int> v(10);
  13. for (int i = 0; i != 10; ++i) v[i] = arr[i];
  14. vector<int> v2(v);
  15. for (auto i : v2) cout << i << " ";
  16. cout << endl;
  17. return 0;
  18. }

练习3.33

对于104页的程序来说,如果不初始化scores将会发生什么?

解:

数组中所有元素的值将会未定义。

练习3.34

假定p1p2 都指向同一个数组中的元素,则下面程序的功能是什么?什么情况下该程序是非法的?

  1. p1 += p2 - p1;

解:

p1 移动到 p2 的位置。任何情况下都合法。

练习3.35

编写一段程序,利用指针将数组中的元素置为0。

解:

  1. #include <iostream>
  2. using std::cout; using std::endl;
  3. int main()
  4. {
  5. const int size = 10;
  6. int arr[size];
  7. for (auto ptr = arr; ptr != arr + size; ++ptr) *ptr = 0;
  8. for (auto i : arr) cout << i << " ";
  9. cout << endl;
  10. return 0;
  11. }

练习3.36

编写一段程序,比较两个数组是否相等。再写一段程序,比较两个vector对象是否相等。

解:

  1. #include <iostream>
  2. #include <vector>
  3. #include <iterator>
  4. using std::begin; using std::end; using std::cout; using std::endl; using std::vector;
  5. // pb point to begin of the array, pe point to end of the array.
  6. bool compare(int* const pb1, int* const pe1, int* const pb2, int* const pe2)
  7. {
  8. if ((pe1 - pb1) != (pe2 - pb2)) // have different size.
  9. return false;
  10. else
  11. {
  12. for (int* i = pb1, *j = pb2; (i != pe1) && (j != pe2); ++i, ++j)
  13. if (*i != *j) return false;
  14. }
  15. return true;
  16. }
  17. int main()
  18. {
  19. int arr1[3] = { 0, 1, 2 };
  20. int arr2[3] = { 0, 2, 4 };
  21. if (compare(begin(arr1), end(arr1), begin(arr2), end(arr2)))
  22. cout << "The two arrays are equal." << endl;
  23. else
  24. cout << "The two arrays are not equal." << endl;
  25. cout << "==========" << endl;
  26. vector<int> vec1 = { 0, 1, 2 };
  27. vector<int> vec2 = { 0, 1, 2 };
  28. if (vec1 == vec2)
  29. cout << "The two vectors are equal." << endl;
  30. else
  31. cout << "The two vectors are not equal." << endl;
  32. return 0;
  33. }

练习3.37

下面的程序是何含义,程序的输出结果是什么?

  1. const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
  2. const char *cp = ca;
  3. while (*cp) {
  4. cout << *cp << endl;
  5. ++cp;
  6. }

解:

会将ca 字符数组中的元素打印出来。但是因为没有空字符的存在,程序不会退出循环。

练习3.38

在本节中我们提到,将两个指针相加不但是非法的,而且也没有什么意义。请问为什么两个指针相加没有意义?

解:

将两个指针相减可以表示两个指针(在同一数组中)相距的距离,将指针加上一个整数也可以表示移动这个指针到某一位置。但是两个指针相加并没有逻辑上的意义,因此两个指针不能相加。

练习3.39

编写一段程序,比较两个 string 对象。再编写一段程序,比较两个C风格字符串的内容。

解:

  1. #include <iostream>
  2. #include <string>
  3. #include <cstring>
  4. using std::cout; using std::endl; using std::string;
  5. int main()
  6. {
  7. // use string.
  8. string s1("Mooophy"), s2("Pezy");
  9. if (s1 == s2)
  10. cout << "same string." << endl;
  11. else if (s1 > s2)
  12. cout << "Mooophy > Pezy" << endl;
  13. else
  14. cout << "Mooophy < Pezy" << endl;
  15. cout << "=========" << endl;
  16. // use C-Style character strings.
  17. const char* cs1 = "Wangyue";
  18. const char* cs2 = "Pezy";
  19. auto result = strcmp(cs1, cs2);
  20. if (result == 0)
  21. cout << "same string." << endl;
  22. else if (result < 0)
  23. cout << "Wangyue < Pezy" << endl;
  24. else
  25. cout << "Wangyue > Pezy" << endl;
  26. return 0;
  27. }

练习3.40

编写一段程序,定义两个字符数组并用字符串字面值初始化它们;接着再定义一个字符数组存放前面两个数组连接后的结果。使用strcpystrcat把前两个数组的内容拷贝到第三个数组当中。

解:

  1. #include <iostream>
  2. #include <cstring>
  3. const char cstr1[]="Hello";
  4. const char cstr2[]="world!";
  5. int main()
  6. {
  7. constexpr size_t new_size = strlen(cstr1) + strlen(" ") + strlen(cstr2) +1;
  8. char cstr3[new_size];
  9. strcpy(cstr3, cstr1);
  10. strcat(cstr3, " ");
  11. strcat(cstr3, cstr2);
  12. std::cout << cstr3 << std::endl;
  13. }

练习3.41

编写一段程序,用整型数组初始化一个vector对象。

  1. #include <iostream>
  2. #include <vector>
  3. using std::vector; using std::cout; using std::endl; using std::begin; using std::end;
  4. int main()
  5. {
  6. int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  7. vector<int> v(begin(arr), end(arr));
  8. for (auto i : v) cout << i << " ";
  9. cout << endl;
  10. return 0;
  11. }

练习3.42

编写一段程序,将含有整数元素的 vector 对象拷贝给一个整型数组。

解:

  1. #include <iostream>
  2. #include <vector>
  3. using std::vector; using std::cout; using std::endl; using std::begin; using std::end;
  4. int main()
  5. {
  6. vector<int> v{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  7. int arr[10];
  8. for (int i = 0; i != v.size(); ++i) arr[i] = v[i];
  9. for (auto i : arr) cout << i << " ";
  10. cout << endl;
  11. return 0;
  12. }

练习3.43

编写3个不同版本的程序,令其均能输出ia的元素。
版本1使用范围for语句管理迭代过程;版本2和版本3都使用普通for语句,其中版本2要求使用下标运算符,版本3要求使用指针。
此外,在所有3个版本的程序中都要直接写出数据类型,而不能使用类型别名、auto关键字和decltype关键字。

解:

  1. #include <iostream>
  2. using std::cout; using std::endl;
  3. int main()
  4. {
  5. int arr[3][4] =
  6. {
  7. { 0, 1, 2, 3 },
  8. { 4, 5, 6, 7 },
  9. { 8, 9, 10, 11 }
  10. };
  11. // range for
  12. for (const int(&row)[4] : arr)
  13. for (int col : row) cout << col << " ";
  14. cout << endl;
  15. // for loop
  16. for (size_t i = 0; i != 3; ++i)
  17. for (size_t j = 0; j != 4; ++j) cout << arr[i][j] << " ";
  18. cout << endl;
  19. // using pointers.
  20. for (int(*row)[4] = arr; row != arr + 3; ++row)
  21. for (int *col = *row; col != *row + 4; ++col) cout << *col << " ";
  22. cout << endl;
  23. return 0;
  24. }

练习3.44

改写上一个练习中的程序,使用类型别名来代替循环控制变量的类型。

解:

  1. #include <iostream>
  2. using std::cout; using std::endl;
  3. int main()
  4. {
  5. int ia[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
  6. // a range for to manage the iteration
  7. // use type alias
  8. using int_array = int[4];
  9. for (int_array& p : ia)
  10. for (int q : p)
  11. cout << q << " ";
  12. cout << endl;
  13. // ordinary for loop using subscripts
  14. for (size_t i = 0; i != 3; ++i)
  15. for (size_t j = 0; j != 4; ++j)
  16. cout << ia[i][j] << " ";
  17. cout << endl;
  18. // using pointers.
  19. // use type alias
  20. for (int_array* p = ia; p != ia + 3; ++p)
  21. for (int *q = *p; q != *p + 4; ++q)
  22. cout << *q << " ";
  23. cout << endl;
  24. return 0;
  25. }

练习3.45

再一次改写程序,这次使用 auto 关键字。

解:

  1. #include <iostream>
  2. using std::cout; using std::endl;
  3. int main()
  4. {
  5. int ia[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
  6. // a range for to manage the iteration
  7. for (auto& p : ia)
  8. for (int q : p)
  9. cout << q << " ";
  10. cout << endl;
  11. // ordinary for loop using subscripts
  12. for (size_t i = 0; i != 3; ++i)
  13. for (size_t j = 0; j != 4; ++j)
  14. cout << ia[i][j] << " ";
  15. cout << endl;
  16. // using pointers.
  17. for (auto p = ia; p != ia + 3; ++p)
  18. for (int *q = *p; q != *p + 4; ++q)
  19. cout << *q << " ";
  20. cout << endl;
  21. return 0;
  22. }