---
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;
}
```