# C++ 呼叫自訂函式修改二維 array 及 vector > 作者:王一哲 > 日期:2023年10月6日 ## 前言 由於 Python 的自訂函式可以回傳 list,如果要呼叫自訂函式修改 list 的內容相當簡單,只要將 list 的內容重設為回傳值即可,例如以下的程式碼: ```python= # 修改1維 list def myfunc(a): a[2] = -1 return a def myprint(a): for i in range(len(a)): print(a[i], end=" " if i < len(a)-1 else "\n") data = [1]*5 # 內容為 [1, 1, 1, 1, 1] print("1D List") myprint(data) print("Modify 1D List") data = myfunc(data) # 內容變為 [1, 1, -1, 1, 1] myprint(data) ``` <br /> ```python= # 修改2維 list def myfunc(a): a[2][2] = -1 return a def myprint(a): for i in range(len(a)): for j in range(len(a[i])): print(a[i][j], end=" " if j < len(a[i])-1 else "\n") data = [[1]*5 for _ in range(3)] # 內容為 [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]] print("2D List") myprint(data) print("Modify 2D List") data = myfunc(data) # 內容變為 [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, -1, 1, 1]] myprint(data) ``` <br /><br /> 但是 C++ 呼叫自訂函式時,無法回傳 array 或 vector,如果要使用自訂函式修改 array 或 vector 的內容,需要使用**傳指標呼叫 (\*)** 或是**傳參考呼叫 (&)**,以下是簡單的例子。 <br /><br /> ## 修改 array ### 1維 array 建立 array 時需要使用指標,再用 new 分配記憶體給 array,最後用 for 迴圈設定 array 的內容。呼叫自訂函式修改 array 內容時,要使用傳指標呼叫,不需要回傳值。 ```cpp= #include <iostream> using namespace std; void myfunc(int*); void myprint(int*, int); int main() { int n = 5; int *data; // 不能直接使用 int data[n] data = new int [n]; for(int i=0; i<n; i++) data[i] = 1; // 內容為 {1, 1, 1, 1, 1} cout << "1D Array" << endl; myprint(data, n); cout << "Modify 1D Array" << endl; myfunc(data); // 內容變為 {1, 1, -1, 1, 1} myprint(data, n); return 0; } /* 自訂函式,呼叫後將索引值為2的元素改為-1 */ void myfunc(int *a) { a[2] = -1; } /* 自訂函式,印出 array 內容,用空格分隔,印出最後一個元素時換行 */ void myprint(int *a, int n) { for(int i=0; i<n; i++) { cout << a[i] << " \n"[i == n-1]; } } ``` <br /> 編譯後執行時輸出 ```cpp 1D Array 1 1 1 1 1 Modify 1D Array 1 1 -1 1 1 ``` <br /><br /> ### 2維 array 建立 2維 array 時需要使用雙重指標,再用 new 分配記憶體給 array,最後用 for 迴圈設定 array 的內容。呼叫自訂函式修改 array 內容時,要使用傳指標呼叫,不需要回傳值。 ```cpp= #include <iostream> using namespace std; void myfunc(int**); void myprint(int**, int, int); int main() { int n = 3, m = 5; int **data; // 不能直接使用 int data[n][m] data = new int *[n]; // n 個指標物件,1維 array // 使用2層 for 迴圈填入元素值,data 內容為 {{1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}} for(int i=0; i<n; i++) { data[i] = new int [m]; // m 個元素的1維 array for(int j=0; j<m; j++) { data[i][j] = 1; } } cout << "2D Array" << endl; myprint(data, n, m); cout << "Modify 2D Array" << endl; myfunc(data); // 內容變為 {{1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, -1, 1, 1}} myprint(data, n, m); return 0; } /* 自訂函式,呼叫後將索引值為[2][2]的元素改為-1 */ void myfunc(int **a) { a[2][2] = -1; } /* 自訂函式,印出 array 內容,用空格分隔,印出每列最後一個元素時換行 */ void myprint(int **a, int n, int m) { for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { cout << a[i][j] << " \n"[j == m-1]; } } } ``` <br /> 編譯後執行時輸出 ```cpp 2D Array 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Modify 2D Array 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 ``` <br /><br /> ## 修改 vector ### 1維 vector 依照一般的方式建立 vector 即可,呼叫自訂函式修改 vector 內容時,要使用傳參考呼叫,不需要回傳值。 ```cpp= #include <iostream> #include <vector> using namespace std; void myfunc(vector<int>&); void myprint(vector<int>); int main() { int n = 5; vector<int> data (n, 1); // 內容為 {1, 1, 1, 1, 1} cout << "1D Vector" << endl; myprint(data); cout << "Modify 1D Vector" << endl; myfunc(data); // 內容變為 {1, 1, -1, 1, 1} myprint(data); return 0; } /* 自訂函式,呼叫後將索引值為2的元素改為-1 */ void myfunc(vector<int> &a) { a[2] = -1; } /* 自訂函式,印出 vector 內容,用空格分隔,印出最後一個元素時換行 */ void myprint(vector<int> a) { for(auto it = a.begin(); it != a.end(); it++) { cout << *it << " \n"[it == a.end()-1]; } } ``` <br /> 編譯後執行時輸出 ```cpp 1D Vector 1 1 1 1 1 Modify 1D Vector 1 1 -1 1 1 ``` <br /><br /> ### 2維 vector 依照一般的方式建立 vector 即可,呼叫自訂函式修改 vector 內容時,要使用傳參考呼叫,不需要回傳值。 ```cpp= #include <iostream> #include <vector> using namespace std; void myfunc(vector<vector<int>>&); void myprint(vector<vector<int>>); int main() { int n = 3, m = 5; vector<vector<int>> data; // 建立空的2維 vector // 使用 for 迴圈及 push_back 填入元素值,data 內容為 {{1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}} for(int i=0; i<n; i++) data.push_back(vector<int> (m, 1)); cout << "2D Vector" << endl; myprint(data); cout << "Modify 2D Vector" << endl; myfunc(data); // 內容變為 {{1, 1, 1, 1, 1}, {1, 1, 1, 1, 1}, {1, 1, -1, 1, 1}} myprint(data); return 0; } /* 自訂函式,呼叫後將索引值為[2][2]的元素改為-1 */ void myfunc(vector<vector<int>> &a) { a[2][2] = -1; } /* 自訂函式,印出 vector 內容,用空格分隔,印出每列最後一個元素時換行 */ void myprint(vector<vector<int>> a) { for(auto it = a.begin(); it != a.end(); it++) { for(auto it2 = (*it).begin(); it2 != (*it).end(); it2++) { cout << *it2 << " \n"[it2 == (*it).end()-1]; } } } ``` <br /> 編譯後執行時輸出 ```cpp 2D Vector 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 Modify 2D Vector 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 ``` <br /><br /> ## 結語 以上的技巧在 APCS 實作題中偶爾會用到,例如111年10月APCS實作題第2題[運貨站](https://hackmd.io/@yizhewang/SJeigpwga),我使用2維 array 儲存倉庫格子的資料,呼叫自訂函式檢查貨物是否能放入倉庫,如果可以放入倉庫則修改對應的格子狀態,需要透過自訂函式修改2維 array 的內容。希望這篇筆記能幫助到有需要的同學。 <br /><br /> --- ###### tags:`C++`、`Python`