---
# System prepended metadata

title: 第三章 字串、向量和陣列 練習

---

# 第三章 字串、向量和陣列 練習

註：此章節以後，都改為使用 using 的方式做宣告，而程式碼主體中都將省略 namescope

## 練習 3.1

以適當的 using 宣告改寫 1.4.1 和 2.6.2 的練習

解：

```cpp
// 1.4.1
#include <iostream>

using std::cin;
using std::cout;
using std::endl;

int main() {
  int sum = 0, val = 1;
  while (val <= 10) {
    sum += val;
    ++val;
  }
  cout << "Sum of 1 to 10 inclusive is " << sum << endl;
  return 0;
}
```
```cpp
// 2.6.2
#include <iostream>
#include <string>

#include "Sales_data.h"

using std::cerr;
using std::cin;
using std::cout;
using std::endl;

int main() {
  Sales_data data1, data2;
  double price = 0;
  cin >> data1.bookNo >> data1.units_sold >> price;
  data1.revenue = data1.units_sold * price;
  cin >> data2.bookNo >> data2.units_sold >> price;
  data2.revenue = data2.units_sold * price;
  if (data1.bookNo == data2.bookNo) {
    unsigned totalCnt = data1.units_sold + data2.units_sold;
    double totalRevenue = data1.revenue + data2.revenue;
    cout << data1.bookNo << " " << totalCnt << " " << totalRevenue << " ";
    if (totalCnt != 0)
      cout << totalRevenue / totalCnt << endl;
    else
      cout << "(no sales)" << endl;
    return 0;
  } else {
    cerr << "Data must refer to the same ISBN" << endl;
    return -1;
  }
}
```

## 練習 3.2

寫一個程式，一次讀取一行的標準輸入。修改你的程式，改成一次讀取一個字詞

解：

```cpp
// 一次讀取一行
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::string;

int main() {
  string s;
  while (getline(cin, s)) cout << s << endl;
  return 0;
}
```

```cpp
// 一次讀取一個詞
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::getline;
using std::string;

int main() {
  string s;
  while (cin >> s) cout << s << endl;
  return 0;
}
```

## 練習 3.3
解釋空白字元（whitespace characters）在 string 輸入運算子及 getline 函式中是如何被處理的

解：

- 以輸入運算子讀取：string 物件會忽略開頭的空白（例如 spaces、newlines、tabs）並且從第一個非空白的自員開始讀取，直到遇見下一個空白為止
- 以 getline 讀取：string 物件會從輸入流讀取字串，直到遇見 newline 為止


## 練習 3.4

寫一個程式來讀取兩個 string，並回報這些 string 是否相等。如果不是，就回報何者較大。現在，變更此程式來回報這些 string 是否有相同的長度，若非如此，就回報哪個比較長

解：

```cpp
// 比較字串大小
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main() {
  string str1, str2;
  while (cin >> str1 >> str2)
    if (str1 == str2)
      cout << "The two strings are equal." << endl;
    else
      cout << "The larger string is " << ((str1 > str2) ? str1 : str2);
  return 0;
}
```

```cpp
// 比較字串長度
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main() {
  string str1, str2;
  while (cin >> str1 >> str2)
    if (str1.size() == str2.size())
      cout << "The two strings have the same length." << endl;
    else
      cout << "The longer string is "
           << ((str1.size() > str2.size()) ? str1 : str2) << endl;
  return 0;
}
// 註：if else 僅為一個 statement，因此 while
// 後面可不加上大括號，但通常依然會加入，此範例僅為示範，實際專案請勿使用此較無可讀性的寫法
```

## 練習 3.5

寫一個程式從標準輸入讀取 string，並將讀取到的串接起來放到一個大型的 string 中。將串接後的 string 印出。接著，更改程式，以一個空格（space）分隔相鄰的輸入

解：

```cpp
// 直接串接字串，不使用空格（space）分隔
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main() {
  string result, str;
  while (cin >> str) result += str;
  cout << result << endl;
  return 0;
}
```

```cpp
// 串接後須使用空格（space）分隔
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::string;

int main() {
  string result, str;
  while (cin >> str) result += str + " ";
  cout << result << endl;
  return 0;
}
```

## 練習 3.6

使用一個範圍 for 來將一個 string 中的所有字元改為 X

解：

```cpp
#include <cctype>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

int main() {
  string str = "this is a string";
  for (auto &c : str) c = 'X';
  cout << str << endl;
  return 0;
}
```

## 練習 3.7

如果你將前面練習的迴圈控制變數定義型別 char，會發生什麼事？預測結果，然後修改你的程式，使用一個 char 看看你是否正確

解：

必須要使用 char 參考才能修改到 string 中原本的字串，因此如果單純只是定義為 char，原本的字串將不會被修改

## 練習 3.8

改寫第一個練習中的程式，先使用 while，接著再使用一個傳統的 for 迴圈，這三種中你比較喜歡哪一個？為什麼？

解：

```cpp
// 使用 while
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

int main() {
  string str = "this is a string";
  decltype(str.size()) i = 0;
  while (i != str.size()) {
    str[i] = 'X';
    ++i;
  }
  cout << str << endl;
  return 0;
}
```
```cpp
// 使用傳統 for
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

int main() {
  string str = "this is a string";
  // 此 for 迴圈非可讀性寫法，僅測試讀者對語法理解度練習使用，請勿在多人協作中使用
  for (decltype(str.size()) i = 0; i < str.size(); str[i] = 'Y', ++i)
    ;
  cout << str << endl;
  return 0;
}
```

使用範圍 for 述句（range for stetement）更好，因為不需要操控索引值（index），更簡潔

## 練習 3.9

下列程式會做什麼事？它是有效的嗎？如果不是，為何呢？

```cpp
string str;
cout << str[0] << endl;
```

解：

無效。使用下標運算子（subscript operator）存取空字串是非法的行為

## 練習 3.10

寫出一個程式，讀取一串字元，包括標點符號，然後寫出所讀到的東西，但移除標點符號

解：

```cpp
#include <cctype>
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

int main() {
  string str = "this, is. a :string!";
  string result;
  for (auto c : str)
    if (!ispunct(c)) result += c;
  cout << result << endl;
  return 0;
}
// 註：if else 僅為一個 statement，因此 for
// 後面可不加上大括號，但通常依然會加入，此範例僅為示範，實際專案請勿使用此較無可讀性的寫法
```

## 練習 3.11

下面的範圍 for 合法嗎？如果是，c 的型別是什麼呢？

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

解：

要根據 for 循環中的 body 來看是否合法，c 是 string 物件中字元的參考，s 是常數，因此如果 body 中的程式碼對 c 指定（assign）就會是非法，但如果不改變，就是合法

## 練習 3.12

如果有的話，下列哪個 vector 定義是錯誤的？對於合法的那些，請解釋那些定義做些什麼。而不合法的那些，請解釋它們為何不合法

```cpp
（a）vector<vector<int>> ivec;
（b）vector<string> svec = ivec;
（c）vector<string> svec(10, "null");
```

- （a）：合法
- （b）：不合法，一個型別是 vector\<int>，另一個型別是 vector\<string>，不一樣
- （c）：合法

## 練習 3.13

下列每個 vector 中各有多少元素？那些元素的值又是什麼？

```cpp
（a）vector<int> v1;         // size:0,  no values.
（b）vector<int> v2(10);     // size:10, value:0
（c）vector<int> v3(10, 42); // size:10, value:42
（d）vector<int> v4{10};     // size:1,  value:10
（e）vector<int> v5{10, 42}; // size:2,  value:10, 42
（f）vector<string> v6{10};  // size:10, value:""
（g）vector<string> v7{10, "hi"};  // size:10, value:"hi"
```

- （a）：size 為 0，容器內沒有任何元素，因此沒有 value
- （b）：size 為 10，value 為 0
- （c）：size 為 10，value 為 42
- （d）：size 為 1，value 為 10
- （e）：size 為 2，value 為 10, 42
- （f）：size 為 10，value 為 ""
- （g）：size 為 10，value 為 "hi"

## 練習 3.14

寫一個程式從 cin 讀取一序列的 int，並將那些值儲存在一個 vector 中

解：

```cpp
#include <iostream>
#include <vector>

using std::cin;
using std::vector;

int main() {
  vector<int> vec;
  int i;
  while (cin >> i) vec.push_back(i);
  return 0;
}
```

## 練習 3.15

重複前一個程式，但這次改讀取 string

解：

```cpp
#include <iostream>
#include <string>
#include <vector>

using std::cin;
using std::string;
using std::vector;

int main() {
  vector<string> vec;
  string str;
  while (cin >> str) v.push_back(str);
  return 0;
}
```

## 練習 3.16

寫出一個程式印出練習 3.13 中那些 vector 的大小與內容。檢查你對於那個練習的解答是否正確。若非如此，重新研讀 3.3.1 直到你了解為何出錯為止

解：

```cpp
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

void check_and_print(const vector<int>& vec) {
  cout << "size: " << vec.size() << "  content: [";
  for (auto i : vec) cout << i << ", ";
  cout << "]\n" << endl;
}

void check_and_print(const vector<string>& vec) {
  cout << "size: " << vec.size() << "  content: [";
  for (auto i : vec) cout << i << ", ";
  cout << "]\n" << endl;
}

int main() {
  vector<int> v1;
  vector<int> v2(10);
  vector<int> v3(10, 42);
  vector<int> v4{10};
  vector<int> v5{10, 42};
  vector<string> v6{10};
  vector<string> v7{10, "hi"};

  check_and_print(v1);
  check_and_print(v2);
  check_and_print(v3);
  check_and_print(v4);
  check_and_print(v5);
  check_and_print(v6);
  check_and_print(v7);
  return 0;
}
```

輸出：
```
size: 0  content: []

size: 10  content: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]

size: 10  content: [42, 42, 42, 42, 42, 42, 42, 42, 42, 42, ]

size: 1  content: [10, ]

size: 2  content: [10, 42, ]

size: 10  content: [, , , , , , , , , , ]

size: 10  content: [hi, hi, hi, hi, hi, hi, hi, hi, hi, hi, ]
```

## 練習 3.17

從 cin 讀取一序列的字詞，並將那些值儲存為一個 vector。在你讀完了所有的字詞之後，就處理那個 vector 並將每個字詞變為大寫。印出變換後的元素，一行八個字

解：

```cpp
#include <iostream>
#include <string>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main() {
  vector<string> vec;
  string str;
  while (cin >> str) v.push_back(str);
  for (auto &str : vec)
    for (auto &c : str) c = toupper(c);
  for (auto s : vec) cout << s << endl;
  return 0;
}
// 註：此為非可讀性寫法
```

## 練習 3.18

下列的程式合法嗎？若非，你會如何修正之？

```cpp
vector<int> ivec;
ivec[0] = 42;
```

解：

不合法，應改為：
```cpp
ivec.push_back(42);
```

## 練習 3.19

列出定義一個 vector 的三種方法，並賦予它們十個元素，每個都有值 42。指出要這麼做是否有偏好的方式以及原因

```cpp
vector<int> ivec1(10, 42);
vector<int> ivec2{42, 42, 42, 42, 42, 42, 42, 42, 42, 42};
vector<int> ivec3;
for (int i = 0; i < 10; ++i) ivec3.push_back(42);
```
第一種方式最好、最簡潔

## 練習 3.20
將一組整數讀到一個 vector 中。印出每個對相鄰元素的和。更改你的程式，改印出第一與最後一個元素的和，後面接著第二個和倒數第二個元素的和

解：

```cpp
// 印出每個相鄰元素的和
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> ivec;
  int i;
  while (cin >> i) ivec.push_back(i);
  for (int i = 0; i < ivec.size() - 1; ++i)
    cout << ivec[i] + ivec[i + 1] << " ";
  return 0;
}
```

```cpp
// 印出前後相對元素的和
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> ivec;
  int i;
  while (cin >> i) ivec.push_back(i);
  for (int m = 0, n = ivec.size() - 1; m <= n;
       cout << ivec[m] + ivec[n] << endl, ++m, --n)
    ;
  return 0;
}
// 非可讀性寫法
```

## 練習 3.21

使用迭代器重新做一遍 3.3.3 的第一個練習

解：

```cpp
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

using std::cout;
using std::endl;
using std::string;
using std::vector;

void check_and_print(const vector<int>& vec) {
  cout << "size: " << vec.size() << "  content: [";
  for (auto it = vec.begin(); it != vec.end(); ++it)
    cout << *it << (it != vec.end() - 1 ? ", " : "");
  cout << "]\n" << endl;
}

void check_and_print(const vector<string>& vec) {
  cout << "size: " << vec.size() << "  content: [";
  for (auto it = vec.begin(); it != vec.end(); ++it)
    cout << *it << (it != vec.end() - 1 ? ", " : "");
  cout << "]\n" << endl;
}

int main() {
  vector<int> v1;
  vector<int> v2(10);
  vector<int> v3(10, 42);
  vector<int> v4{10};
  vector<int> v5{10, 42};
  vector<string> v6{10};
  vector<string> v7{10, "hi"};

  check_and_print(v1);
  check_and_print(v2);
  check_and_print(v3);
  check_and_print(v4);
  check_and_print(v5);
  check_and_print(v6);
  check_and_print(v7);
  return 0;
}
```

## 練習 3.22

修改會印出 text 第一個段落的迴圈，改為將 text 中對應到第一個段落的元素全都變為大寫。更新 text 之後，印出其內容

解：

```cpp
#include <iostream>
#include <string>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;

int main() {
  vector<string> text;
  for (string line; getline(cin, line);) text.push_back(line);
  for (auto it = text.begin(); it != text.end() && !it->empty(); ++it) {
    for (auto& c : *it) c = toupper(c);
    cout << *it << endl;
  }
  return 0;
}
```

## 練習 3.23

寫一個程式來建立帶有十個 int 元素的一個 vector。使用一個迭代器將每個元素的指定為目前值的兩倍。印出這個 vector 來測試你的程式

解：

```cpp
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> v(10, 1);
  for (auto it = v.begin(); it != v.end(); it++) *it *= 2;
  for (auto one : v) cout << one << endl;
  return 0;
}
```

## 練習 3.24

使用迭代器重做 3.3.3 的最後一個練習

解：

```cpp
// 印出每個相鄰元素的和
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> ivec;
  int i;
  while (cin >> i) ivec.push_back(i);
  for (auto it = ivec.begin(); it != ivec.end() - 1; ++it)
    cout << *it + *(it + 1) << " ";
  return 0;
}
```

```cpp
// 印出前後相對元素的和
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> ivec;
  int i;
  while (cin >> i) ivec.push_back(i);
  for (auto it1 = ivec.begin(), it2 = ivec.end() - 1; it1 <= it2;
       cout << *(it1++) + *(it2--) << " ")
    ;
  return 0;
}
// 非可讀性寫法
```

## 練習 3.25

使用迭代器來取代下標，改寫 3.3.3 的成績叢集程式

解：

```cpp
#include <iostream>
#include <vector>

using std::cin;
using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> scores(11, 0);
  int grade;
  while (cin >> grade) ++*(scores.begin() + grade / 10);
  for (auto result : scores) cout << result << " ";
  cout << endl;
}
```

## 練習 3.26

在前面的二元搜尋中，為什麼我們寫的是 mid = beg + (end - beg) / 2;，而非 mid = (beg + end) / 2;？

解：

兩個迭代器（iterator）相互之間支持的運算只有減號，而沒有加號，但是迭代器和迭代器之間的差值（difference_type）為整數型別，支持加號的運算

## 練習 3.27

假設 txt_size 是一個函式，它不接受引數（arguments），並回傳一個 int 值，下列哪些定義是非法的？解釋原因

```cpp
unsigned buf_size = 1024;
（a）int ia[buf_size];
（b）int ia[4 * 7 - 14];
（c）int ia[txt_size()];
（d）char st[11] = "fundamental";
```

解：
- （a）非法，陣列的大小（dimensioin）必須是一個 constant expression
- （b）合法
- （c）非法，txt_size() 的值必須要到執行時期才能得到
- （d）非法，陣列的大小應為 12，後面應含有一個 /0 字元結尾

## 練習 3.28

下列陣列中的值是什麼？

```cpp
string sa[10];
int ia[10];
int main() {
	string sa2[10];
	int ia2[10];
}
```

解：

陣列中的所有元素都會被默認初始化（default initialize）

sa 的元素全部為空字串，ia 的元素全部為 0

sa2 的元素值全部為空字串，ia2 的元素值全部為未定義

## 練習 3.29

列出使用陣列而非 vector 的一些缺點

解：

- 陣列的大小必須是確定的
- 不能隨意增加元素
- 不允許拷貝和指定

## 練習 3.30

辨識出下列程式碼中的索引錯誤：

```cpp
constexpr size_t array_size = 10;
int ia[array_size];
for (size_t ix = 1; ix <= array_size; ++ix)
	ia[ix] = ix;
```

解：

當 ix 達到 10 的時候，會發生越界，產生未定義行為（undefined behavior）

## 練習 3.31

寫一個程式來定義由十個 int 所構成的陣列。賦予每個元素與其在陣列中所在位置的相同值

```cpp
#include <iostream>

using std::cout;
using std::endl;

int main() {
  int arr[10];
  for (auto i = 0; i < 10; ++i) arr[i] = i;
  for (auto i : arr) cout << i << " ";
  cout << endl;
  return 0;
}
```

## 練習 3.32

將你前面定義的陣列拷貝到另一個陣列。使用 vector 改寫你的程式

```cpp
// copy array
#include <iostream>

using std::cout;
using std::endl;

int main() {
  int arr[10];
  for (auto i = 0; i < 10; ++i) arr[i] = i;
  int arr2[10];
  for (auto i = 0; i < 10; ++i) arr2[i] = arr[i];
  for (auto i : arr) cout << i << " ";
  cout << endl;
  return 0;
}
```

```cpp
// copy vector
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> v(10);
  for (auto i = 0; i != 10; ++i) v[i] = i;
  vector<int> v2(v);
  for (auto i : v2) cout << i << " ";
  cout << endl;
  return 0;
}
```

## 練習 3.33

如果我們沒有初始化前面程式中的 scores 陣列，會發生什麼事？

解：

陣列中所有元素的值將會是未定義的值

## 練習 3.34

如果 p1 和  p2 指向同一個陣列中的元素，下列的程式碼會做什麼呢？有 p1 或 p2 的值會讓這段程式碼變得不合法嗎？

```cpp
p1 += p2 - p1;
```

解：

意思是將 p1 移動到 p2 的位置，且任何情況下的合法

## 練習 3.35

使用指標寫一個程式來將一個陣列中的元素設為 0

解：

```cpp
#include <iostream>

using std::cout;
using std::endl;

int main() {
  const int size = 10;
  int arr[size];
  for (auto ptr = arr; ptr != arr + size; ++ptr) *ptr = 0;
  for (auto i : arr) cout << i << " ";
  cout << endl;
  return 0;
}
```

## 練習 3.36

寫一個程式來比較兩個陣列的相等性。寫一個類似的程式來比較兩個 vector

解：

```cpp
#include <iostream>
#include <vector>
#include <iterator>

using std::begin;
using std::end;
using std::cout;
using std::endl;
using std::vector;

// pb point to begin of the array, pe point to end of the array.
bool compare(int* const pb1, int* const pe1, int* const pb2, int* const pe2)
{
    if ((pe1 - pb1) != (pe2 - pb2)) // have different size.
        return false;
    else
    {
        for (int* i = pb1, *j = pb2; (i != pe1) && (j != pe2); ++i, ++j)
            if (*i != *j) return false;
    }

    return true;
}

int main()
{
    int arr1[3] = { 0, 1, 2 };
    int arr2[3] = { 0, 2, 4 };

    if (compare(begin(arr1), end(arr1), begin(arr2), end(arr2)))
        cout << "The two arrays are equal." << endl;
    else
        cout << "The two arrays are not equal." << endl;

    cout << "==========" << endl;

    vector<int> vec1 = { 0, 1, 2 };
    vector<int> vec2 = { 0, 1, 2 };

    if (vec1 == vec2)
        cout << "The two vectors are equal." << endl;
    else
        cout << "The two vectors are not equal." << endl;

    return 0;
}
```
```cpp
// compare vector
#include <iostream>
#include <vector>

using std::cout;
using std::endl;
using std::vector;

int main() {
  vector<int> vec1 = {0, 1, 2};
  vector<int> vec2 = {0, 1, 2};
  if (vec1 == vec2)
    cout << "The two vectors are equal." << endl;
  else
    cout << "The two vectors are not equal." << endl;
  return 0;
}
```
## 練習 3.37

下列程式會做什麼事呢？

```cpp
const char ca[] = { 'h', 'e', 'l', 'l', 'o' };
const char *cp = ca;
while (*cp)     cout << *(cp++) << endl;
```

解：

會將 ca 字元陣列中的字元都印出來，但是因為沒有空字元作為結尾（null terminated），因此後面可能還會印出其它未定義的字元

## 練習 3.38

在本節中，我們注意到試著將兩個指標相加不只是非法的，也沒有意義。為何將兩個指標相加是沒有意義的呢？

解：

將兩個指標相減可以表是兩個指標（在同一個陣列中）相距的距離，將指標加上一個整數也可以表示移動這個指標到某一位置。但是兩個指標ㄒ央加並沒有邏輯上的意義，因此兩個指標不能相加

## 練習 3.39

撰寫一段程式來比較兩個 string。現在撰寫一個程式來比較兩個 C-style 字元字串的值

解：

```cpp
// compare two strings by std::string
#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

int main() {
  string str1("Mooophy"), str2("Pezy");
  if (str1 == str2)
    cout << "same string." << endl;
  else if (str1 > str2)
    cout << str1 << " > " << str2 << endl;
  else
    cout << str1 << " < " << str2 << endl;
  return 0;
}
```

```cpp
// compare two strings by cstring(strcmp)
#include <cstring>
#include <iostream>

using std::cout;
using std::endl;

int main() {
  const char* cstr1 = "Wangyue";
  const char* cstr2 = "Pezy";
  auto result = strcmp(cstr1, cstr2);
  if (result == 0)
    cout << "same string." << endl;
  else if (result < 0)
    cout << cstr1 << " < " << cstr2 << endl;
  else
    cout << cstr1 << " > " << cstr2 << endl;
  return 0;
}
```

## 練習 3.40

寫一個程式來定義從字串字面值初始化的兩個字元陣列，現在定義第三個陣列來存放那兩個陣列串接的結果。使用 strcpy 和 strcat 來將那兩個陣列拷貝到第三個中

解：

```cpp
#include <cstring>
#include <iostream>

using std::cout;
using std::endl;

int main() {
  const char cstr1[] = "Hello,";
  const char cstr2[] = "world!";
  // cstring 中的 strlen 並非 constexpr 函數，放在 stack
  // 中可能會出錯，因此必須放在 heap 中
  const size_t new_size = strlen(cstr1) + strlen(cstr2) + 1;
  char *cstr3 = new char[new_size];
  strcpy(cstr3, cstr1);
  strcat(cstr3, cstr2);
  cout << cstr3 << endl;
  return 0;
}
```

## 練習 3.41

寫出一個程式從一個 int 陣列初始化一個 vector

```cpp
#include <iostream>
#include <vector>

using std::begin;
using std::cout;
using std::end;
using std::endl;
using std::vector;

int main() {
  int arr[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  vector<int> vec(begin(arr), end(arr));
  for (auto n : vec) cout << n << " ";
  cout << endl;
  return 0;
}
```

## 練習 3.42

寫出一個程式來將由 int 所構成的一個 vector 拷貝到一個 int 陣列

解：

```cpp
#include <iostream>
#include <vector>

using std::begin;
using std::cout;
using std::end;
using std::endl;
using std::vector;

int main() {
  vector<int> vec{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  int arr[10];
  for (int i = 0; i != vec.size(); ++i) arr[i] = vec[i];
  for (auto n : arr) cout << n << " ";
  cout << endl;
  return 0;
}
```

## 練習 3.43

寫出三種不同版本的程式來印出 ia 的元素。一個版本應該使用範圍 for 來管理迭代動作，另外兩個應該使用一個普通的 for 迴圈，其中一個使用下標，另一個使用指標。在所有的三個程式中，直接寫出所有的型別。也就是說，別使用型別別名、auto，或 decltype 來簡化程式碼

解：

```cpp
#include <iostream>

using std::cout;
using std::endl;

int main() {
  int arr[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};

  // by range for
  // 不會更改的值要習慣加上 const
  for (const int(&row)[4] : arr) {
    for (const int col : row) cout << col << " ";
    cout << endl;
  }
  cout << endl;

  // by for loop
  for (size_t i = 0; i != 3; ++i) {
    for (size_t j = 0; j != 4; ++j) cout << arr[i][j] << " ";
    cout << endl;
  }
  cout << endl;

  // by pointers
  // 不會更改的值要習慣加上 const
  for (const int(*row)[4] = arr; row != arr + 3; ++row) {
    for (const int *col = *row; col != *row + 4; ++col) cout << *col << " ";
    cout << endl;
  }
  return 0;
}
```

## 練習 3.44

改寫前面的練習，使用一個型別別名（type alias）作為迴圈控制變數的型別

解：

```cpp
#include <iostream>

using std::cout;
using std::endl;

int main() {
  int ia[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};

  // by range for
  // type alias
  using int_array = int[4];
  // 不會更改的值要習慣加上 const
  for (const int(&row)[4] : ia) {
    for (const int col : row) cout << col << " ";
    cout << endl;
  }
  cout << endl;

  // by for loop
  // 使用下標運算子不需要使用 type alias
  for (size_t i = 0; i != 3; ++i) {
    for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
    cout << endl;
  }
  cout << endl;

  // by pointers
  // 不會更改的值要習慣加上 const
  for (const int_array *row = ia; row != ia + 3; ++row) {
    for (const int *col = *row; col != *row + 4; ++col) cout << *col << " ";
    cout << endl;
  }
  return 0;
}
```

## 練習 3.45

再次改寫程式，這次使用 auto

解：

```cpp
#include <iostream>

using std::cout;
using std::endl;

int main() {
  int ia[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};

  // by range for
  // 自動推斷成 const int(&row)[4]
  for (const auto &row : ia) {  // 不會更改的值要習慣加上 const
    for (const auto col : row) cout << col << " ";
    cout << endl;
  }
  cout << endl;

  // by for loop
  for (size_t i = 0; i != 3; ++i) {
    for (size_t j = 0; j != 4; ++j) cout << ia[i][j] << " ";
    cout << endl;
  }
  cout << endl;

  // by pointers
  // 自動推斷成 int(*row)[4]
  for (auto row = ia; row != ia + 3; ++row) {
    for (const int *col = *row; col != *row + 4; ++col) cout << *col << " ";
    cout << endl;
  }
  return 0;
}
```