# 第三章 字串、向量和陣列 練習
註:此章節以後,都改為使用 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;
}
```