--- tags: C++,程式設計 --- # C++ 陣列與指標 (下) ## 一、傳址呼叫 ### (一)傳值呼叫(Call by Value) ```cpp= void swap (int p ,int q){ //2個參數皆為值 int temp; temp = p; p = q; q = temp; } int main(){ int a = 5 , b = 10; cout << a << endl; //5 cout << b << endl; //10 swap(a,b); //傳值 cout << a << endl; //10 cout << b << endl; //5 } ``` ### (二)傳址呼叫(Call by Address) #### 1、變數交換 ```cpp= void swap (int* p ,int* q){ //2個參數皆為指標(位址) int temp; temp = *p; *p = *q; *q = temp; } int main(){ int a = 5 , b = 10; cout << a << endl; //5 cout << b << endl; //10 swap(&a,&b); //傳位址 cout << a << endl; //10 cout << b << endl; //5 } ``` #### 2、傳入矩陣 ```cpp= //第一種寫法 (全指標) void swap1 (int* p){ int temp; temp = *p; *p = *(p+1); *(p+1) = temp; } //第二種寫法 (參數指標,內容是陣列) void swap2(int* p){ int temp; temp = p [0]; p[0] = p[1]; p[1] = temp; } //第三種寫法 (全部都是陣列) void swap2(int p[]){ int temp; temp = p[0]; p[0] = p[1]; p[1] = temp; } int main(){ int x[2] = {3,8}; cout << x[0] << endl; //3 cout << x[1] << endl; //8 swap1(x); //單寫矩陣名稱時,他代表矩陣中第一個元素位址。 cout << x[0] << endl; //8 cout << x[1] << endl; //3 } ``` ### (三)傳參數呼叫(Call by Reference) ```cpp= void swap (int& i,int& j){ int temp; temp = i; i = j; j = temp; } int main(){ int a = 3, b = 8; cout << a << endl; //3 cout << b << endl; //8 swap(a,b); //傳本尊 cout << a << endl; //8 cout << b << endl; //3 } ``` ### (四)統整 ```cpp= // 變數宣告 int i = 10; double d = 1.1; // 指標宣告(存位址) int* p = &i; double* f = &d; // 參照宣告 int& r = i; double& m = d; // 呼叫函式 //Call by Value void fun1 (int a, double b) //呼叫函示 fun (i,d); //Call by Address void fun2 (int* a, double* b) //呼叫函示 fun (&i,&d); //Call by reference void fun3 (int& a,double& b) //呼叫函示 fun (i,d); void fun4 (int* a,double& b) //呼叫函示 fun (&i,d); ``` ## 二、以「指標」或「參考型別」為「回傳值」 ### (一)return 指標https://hackmd.io/Oh1M1eMZQX2vw_tRLxEYMw?edit# #### 1、定義:函式return指標內容(一個「位址」) #### 2、作用1:可以傳回字串或陣列(多個變數)的位址 #### 3、作用2:回傳結果可以直接在程式中使用 ### (二)return 參考型別 #### 1、定義:函式return一個「參考」(reference) #### 2、作用1:可以傳回字串或陣列(多個變數)的位址 #### 3、作用2:回傳結果可以直接在程式中使用 ### (三)說明 #### 1、[參考前筆記四、](/1erlebEZSRyEw1y7gmHYdw) ```cpp= //以「指標」或「參考型別」為「回傳值」 //以「指標」為「傳回值」的函式撰寫 //複習 int* ip = new int (100); //ip指向一個新的記憶體位址,初始址為100 int* ap = new int [100]; //配置「100個整數」的記憶體空間,ap指向此空間 int* np = new char [100]; //配置「100個字元」的記憶體空間,np指向此空間 ``` #### 2、以「指標」為「回傳值」 ```cpp= #includ <iostream> #includ <cctype> //為了使用toupper() using namespace std; //函式部分 char* toUpper(const char* ptr){ //return 指標 unsigned int len =strlen(ptr); char* newStr = new char[len+1]; //配置「len + 1個字元」的記憶體空間,newStr指向此空間 //必須配置「char[len+1]」(而不是char[len]),因為需要包含結束字元 for (unsigned int i = 0; i < len + 1 ; i++){ //必須將結束字元填入newStr指的最後一個字元,所以「i < len」 *(newStr + i ) = toupper(*(ptr + i)) //呼叫<cctype的「toupper(*)」函式:先(#includ <cctype>) } return newStr; //return指標內容(配置記憶體的位址) } //函式回傳資料形式為char*,宣告char* newStr,故回傳 newStr //main()的部分 int main(){ //以「指標」或「參考型別」為「回傳值」 cout << toUpper("happy birthday") << endl; //HAPPY BIRTHDAY //相當於 cout << newStr; (cout << 指向一個byte的位址,輸出字串內容) } const char* p = "Good Moring"; cout << p << endl; //Good Moring cout << toUpper(p) << endl; //GOOD MORING cout << p << endl; //Good Moring //使用不同的兩個指標,故沒有取代原本的指標 char n[] = "John Smith"; cout << n <<endl; //John Smith (cout << &n[0]) cout << toUpper(n) << endl; //JOHN SMITH cout << n <<endl; //John Smith ``` ##### a、ptr指向開始的位址 | h | a | p | p | y | | b | i | r | t | h | d | a | y | \0 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ##### b、配置相同大小的記憶體空間 (以newStr指向開始的位址) |   |   |   |   |   | |  |   |   |   | |   |   | |   | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ##### c、利用迴圈將ptr位址的內容一一放入newStr | h | a | p | p | y | | b | i | r | t | h | d | a | y | \0 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | #### 3、以「餐考型別」為「回傳值」 ```cpp= //函式部分 int& addTen(int& a){ //return 參考型別 a+=10; return a; } //main()部分 int i = 10; cout << i <<endl; // 10 addTen(i); //(回傳值為20) 不過沒有任何動作故不會有輸出 cout << i <<endl; // 20 cout << i 此時才會印出 addTen(i) = 50 ; // 相當於 a = 50 (將算完的回傳值使用50取代) cout << i <<endl; // 50 cout << i 此時才會印出 addTen(addTen(i)); // (回傳值為70) 不過沒有任何動作故不會有輸出 cout << i <<endl; // 70 ``` ## 三、練習 ### (一)題目一: 分別利用「call by address」與「call by reference」撰寫兩個函式: setTriple(int *a), setTriple(int &b) 可以將輸入的值變3倍。 並在main()中呼叫這兩個函式。 ```cpp= #include <iostream> using namespace std; /*題目1:分別利用「call by address」與「call by reference」撰寫兩個函式: setTriple(int *a), setTriple(int &b)可以將輸入的值變3倍。並在main()中呼叫這兩個函式。*/ void address(int* i) { *i = *i * 3; cout << *i << endl; } void reference(int &i) { i = i * 3; cout << i << endl; } int main() { int a; cout << "請輸入一個數字:"; cin >> a; address(&a); int c; cout << "請輸入二個數字:"; int &b = c; cin >> b; reference(c); } ``` ### (二)題目二: 已知一陣列 a[10] = {45, 65, 24, 49, 68, 78, 45, 12, 32, 40}。 撰寫一個排序函式,將此陣列a為參數輸入此函式,讓最後a陣列的元素由小排到大。 ```cpp= #include <iostream> using namespace std; /*題目2: 已知一陣列 a[10] = {45, 65, 24, 49, 68, 78, 45, 12, 32, 40}。 撰寫一個排序函式,將此陣列a為參數輸入此函式,讓最後a陣列的元素由小排到大。*/ //要回傳函示 int sort(int* c ,int k) { int temp; for (int i = 0; i < k; i++) { for (int j = i + 1; j < k ; j++) { if (c[i] > c[j]) { temp = c[i]; c[i] = c[j]; c[j] = temp; } } } return *c; } int main() { int a[10] = { 45, 65, 24, 49, 68, 78, 45, 12, 32, 40 }; int* b = a; int i,j; j = sizeof(a) / sizeof(a[0]); sort(b,j); for (i=0 ; i < 10 ; i++) cout << b[i] <<','; return 0; } ```