Try   HackMD

C++ 呼叫自訂函式修改二維 array 及 vector

作者:王一哲
日期:2023年10月6日

前言

由於 Python 的自訂函式可以回傳 list,如果要呼叫自訂函式修改 list 的內容相當簡單,只要將 list 的內容重設為回傳值即可,例如以下的程式碼:

# 修改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)

# 修改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)



但是 C++ 呼叫自訂函式時,無法回傳 array 或 vector,如果要使用自訂函式修改 array 或 vector 的內容,需要使用傳指標呼叫 (*) 或是傳參考呼叫 (&),以下是簡單的例子。


修改 array

1維 array

建立 array 時需要使用指標,再用 new 分配記憶體給 array,最後用 for 迴圈設定 array 的內容。呼叫自訂函式修改 array 內容時,要使用傳指標呼叫,不需要回傳值。

#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]; } }

編譯後執行時輸出

1D Array
1 1 1 1 1
Modify 1D Array
1 1 -1 1 1



2維 array

建立 2維 array 時需要使用雙重指標,再用 new 分配記憶體給 array,最後用 for 迴圈設定 array 的內容。呼叫自訂函式修改 array 內容時,要使用傳指標呼叫,不需要回傳值。

#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]; } } }

編譯後執行時輸出

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



修改 vector

1維 vector

依照一般的方式建立 vector 即可,呼叫自訂函式修改 vector 內容時,要使用傳參考呼叫,不需要回傳值。

#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]; } }

編譯後執行時輸出

1D Vector
1 1 1 1 1
Modify 1D Vector
1 1 -1 1 1



2維 vector

依照一般的方式建立 vector 即可,呼叫自訂函式修改 vector 內容時,要使用傳參考呼叫,不需要回傳值。

#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]; } } }

編譯後執行時輸出

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



結語

以上的技巧在 APCS 實作題中偶爾會用到,例如111年10月APCS實作題第2題運貨站,我使用2維 array 儲存倉庫格子的資料,呼叫自訂函式檢查貨物是否能放入倉庫,如果可以放入倉庫則修改對應的格子狀態,需要透過自訂函式修改2維 array 的內容。希望這篇筆記能幫助到有需要的同學。



tags:C++Python