---
tags: C++,程式設計
---
# C++ 陣列與指標 (中)
## 一、多維陣列
### (一)宣告
```cpp=
int a[5]; //一維陣列 看起來像 1x5矩陣
int b[2][3]; //二維陣列 看起來像 2x3矩陣
b[0][0]= 10; //第一列第一個(行)元素為10
b[1][2]= 100; //第二列第三個(行)元素為100
```
### (二)設定初始值
```cpp=
int n[5] = {1,2,3,4,5}; //一維陣列 看起來像1x5矩陣
int c[2][3] = {1,2,3,4,5,6}; //二維陣列 看起來像2x3矩陣
int d[] = {1,2,3,4}; //一維陣列 看起來像1x4矩陣
int f[][3] = {1,2,3,4,5,6}; //二維陣列 看起來像2x3矩陣
//【錯誤示範】
//int g[2][] = {1,2,3,4,5,6}; //不知道一列可以存多少個整數
//【故左側可以省略但右側無法】
int h[3][4] = {1,2,3,4,5,6}; //一樣未指定的補零
//看起來像3x4矩陣
//output如下:
//1234
//5600
//0000
```
## 二、指標
### (一)宣告
```cpp=
int* p; //宣告一個指向(int資料型態)的指標p (ps:「*放在宣告表示宣告指標變數」)
p = &i; //p內容為i的地址(ps:「&」放在「變數」表示取address)
double d =3.8;
double* p2=&d; //宣告一個指向(double資料型態)的指標p2,p2內容為d的位址
```
### (二)指標記憶體大小
```cpp=
cout <<"sizeof(p)=" << sizeof(p) << "bytes" << endl; // sizeof(p) = 4 bytes
cout <<"sizeof(p)=" << sizeof(p2) << "bytes" << endl; // sizeof(p) = 4 bytes
```
### (三)指標內容
```cpp=
cout << "p=" << p << endl; //p = 123455ff (i的Address)
cout << "p2" << p2 << endl; //p2 = AA5678BB (d的Address)
//【位址】看當初電腦配置空間額定(配置方法也有差best fit、worst fit、first fit)
cout << "*P=" << *P <<endl; // *p = 10 (i的值)(ps: 【*】放在【變數】表示取值)
cout << "*p2" << *p2 <<endl; //*p2 = 3.8 (d的值)
```
### (四)指標間接存取
```cpp=
int age 18, * i_age;
float weight = 65.4, * f_weight;
char bloodType ='B', * c_bloodType;
i_age = &age;
f_weight = &weight;
c_bloodType = &bloodType;
cout << "年齡:" << *i_age << endl; // 年齡:18
cout << "體重:" << *f_weight << endl; // 體重:65.4
cout << "血型:" << *c_bloodType <<endl;// 血型:B
```
## 三、指標與陣列
### (一)指標與陣列的互換
``` cpp=
//step 1 :建立陣列
char str[]="How are you?";
cout << str[0] << endl; //H (【索引值0號】內的值)
cout << str[1] << endl; //o (【索引值1號】內的值)
cout << str[2] << endl; //w (【索引值2號】內的值)
cout << str[3] << endl; //(空白) (【索引值3號】內的值)
cout << str[4] << endl; //a (【索引值4號】內的值)
//step 2 :指向char陣列的指標
char* ptr = str; //宣告一個指向(字元型態資料)陣列的指標ptr, ptr內容為str的位址
//【單寫陣列名稱時】,它代表陣列中【第一個元素的位址】(非常重要)
//相當於 char* ptr = &str[0];
cout << *ptr << endl; //H (【索引值0號】內的值)
cout << *(ptr+1) << endl; //o (【索引值1號】內的值)
cout << *(ptr+2) << endl; //w (【索引值2號】內的值)
cout << *(ptr+3) << endl; //(空白) (【索引值3號】內的值)
cout << *(ptr+4) << endl; //a (【索引值4號】內的值)
//觀察得知:將指標+1,代表「索引值+1」,代表位址+1個指標所指型別大小
step 3 : 可將「*」運用在陣列上
cout << *str << endl; //H (【索引值0號】內的值)
cout << *(str+1) << endl; //o (【索引值1號】內的值)
cout << *(str+2) << endl; //w (【索引值2號】內的值)
cout << *(str+3) << endl; //(空白) (【索引值3號】內的值)
cout << *(str+4) << endl; //a (【索引值4號】內的值)
step 4 :可將[]運用在指標上
cout << ptr[0] << endl; //H (【索引值0號】內的值)
cout << ptr[1] << endl; //o (【索引值1號】內的值)
cout << ptr[2] << endl; //w (【索引值2號】內的值)
cout << ptr[3] << endl; //(空白) (【索引值3號】內的值)
cout << ptr[4] << endl; //a (【索引值4號】內的值)
//觀察得知:指標與陣列有著同樣的概念
//可以使用迴圈將上述列印
for (unsigned i =0; i < strlen(str); i++)
cout << *(str+i);
cout << endl;
for (unsigned i = 0; <strlen(str) ;i++)
cout << ptr[i];
cout << endl;
```
### (二)指標的加減
#### 1、以指向int陣列指標為例
```cpp=
int aa[5]={1,2,3,4,5};
int* pp = aa; //宣告一個指向(int資料型態)的指標pp,pp內容為 aa 的位址
//「單寫陣列名稱」時,它代表陣列中「第一個元素的位址」
//指標的加減差 4 Bytes
for (int i =0; i < 5 ; i++){
cout << "位址pp +" << i << "為" << (pp+i) << endl;
cout << "此位址存放的資料為:" << *(pp+i) << endl;
}
// 位址pp + 0為:00B2FDE4
// 此位址存放的資料為: 1
// 位址pp + 0為:00B2FDE8
// 此位址存放的資料為: 2
// 位址pp + 0為:00B2FDEC
// 此位址存放的資料為: 3
// 位址pp + 0為:00B2FDE0
// 此位址存放的資料為: 4
// 位址pp + 0為:00B2FDF4
// 此位址存放的資料為: 5
```
### 2、何時會輸出字串內容
#### 當 cout <<「指向『一個byte』的位址」時 //輸入字串內容
#### (1)陣列
```cpp=
char name1[]="John Smith";
cout << name1 << endl;
//John Smith (name1:「單寫陣列名稱時」,它代表陣列中「地一個元素的位址」)
//最難
cout << &name1[0] << endl;
//John Smith (&name1[0]:陣列中「第一個元素的位址」)
cout << &name1[5] << endl;
//Smith (&name1[5]:陣列中「第六個元素的位址」)
```
#### (2)指標
```cpp=
const char* nameP = "John Smith";
//因為"John Smith"是const ,有些沒加Complier也會過
cout << nameP << endl;
//John Smith (nameP:「J」的「位址」)
cout* pstr = name1; //指標存位址
cout << pstr << endl;
//John Smith (pstr:name1的「第一個元素的位址」)
cout << &pstr[0] << end ; // John Smith
cout << &pstr[5] << endl; //Smith
```
#### 1、以指向「二維char陣列」的「指標」
##### (1)一維陣列
```cpp=
char str[] = "How are you?";
char* ptr = str;
cout << str <<endl; // How are you? (str:「單寫陣列名稱時」,他代表陣列中「第一個元素位址」)
cout << ptr <<endl; // How are you? (ptr: str 的「第一個元素位址」)
```
##### (2)二維陣列
###### a、二維陣列基本概念
```cpp=
char a[3][4] = {"abc","def","ghi"};
```
| a | b | c | \0 |
| -------- | -------- | -------- | --- |
| d| e | f | \0 |
| g | h | i | \0 |
| 位址 | 0088F8F4 | 0088F8F5 | 0088F8F6 | 0088F8F7 | 0088F8F8 | 0088F8F9 | 0088F8FA | 0088F8FB | 0088F8FC | 0088F8FD | 0088F8FE | 0088F8FF |
| ------ | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| 內容值 | a | b | c | \0 | d | e | f | \0 | g | h | i | \0 |
```cpp=
cout << "sizeof(a) =" << sizeof(a) << endl; //sizeof(a) = 12
cout << "sizeof(a[0]) =" << sizeof(a[0]) << endl; //sizeof(a[0]) = 4
cout << "sizeof(a[0][0]) =" << sizeof(a[0][0]) << endl; //sizeof(a[0][0]) = 1
cout << a[0][0] << endl; //a
cout << a[0][1] << endl; //b
cout << a[0][2] << endl; //c
cout << a[0][3] << endl; //
cout << a[1][0] << endl; //d
cout << a[1][1] << endl; //e
cout << a[1][2] << endl; //f
cout << a[1][3] << endl; //
cout << a[2][0] << endl; //g
cout << a[2][1] << endl; //h
cout << a[2][2] << endl; //i
cout << a[2][3] << endl; //
cout << a[0] << endl; //abc
//(a[0] = &a[0][0],單寫陣列名稱時,他代表陣列中「第一個元素位址」)
cout << a[1] << endl; //def
//(a[0] = &a[1][0],單寫陣列名稱時,他代表陣列中「第一個元素位址」)
cout << a[2] << endl; //ghi
//(a[0] = &a[2][0],單寫陣列名稱時,他代表陣列中「第一個元素位址」)
cout << "&a=" << &a << endl; // &a = 0088F8F4 (a的位址)
cout << "&a=" << &a[0] << endl; // &a[0] = 0088F8F4 (a[0]的位址)
cout << "a=" << a << endl; // a = 0088F8F4 (a=&a[0],單寫陣列名稱,代表陣列中「第一個元素位址」)
cout << &(a[0][0]) << endl; //abc (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[0][1]) << endl; //bc (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[0][2]) << endl; //c (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[1][0]) << endl; //def (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[1][1]) << endl; //ef (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[1][2]) << endl; //f (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[2][0]) << endl; //ghi (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[2][1]) << endl; //hi (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
cout << &(a[2][2]) << endl; //i (當cout << 「指向「一個byte」的位址」時) 輸出字串內容
```
###### b、陣列指標
```cpp=
char(*s)[4] = a; //宣告一個指向「4個元素char陣列」的指標(*s)[4],內容維a的位址
//「單寫陣列名稱」時,他代表陣列中「第一個元素位址」
//相當於char(*s)[4] = &[0]
//是否可以寫成「char(*s)[4] = &[0][0]」? (不行!,因為&a[0][0] return字串)
```
| 位址 | 0088F8F4 | 0088F8F5 | 0088F8F6 | 0088F8F7 | 0088F8F8 | 0088F8F9 | 0088F8FA | 0088F8FB | 0088F8FC | 0088F8FD | 0088F8FE | 0088F8FF |
| ------ | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
| 內容值 | a | b | c | \0 | d | e | f | \0 | g | h | i | \0 |
```cpp=
cout << s << endl; //0088F8F4(a的位址)
cout << s+1 << endl; //0088F8F8(a的位址 + 4 Bytes)
cout << s+2 << endl; //0088F8FC(a的位址 + 8 Bytes)
cout << *s << endl; //abc (取4個char元素的值,從「a」印到結束字元)
cout << *(s+1) << endl; //def (取4個char元素的值,從「d」印到結束字元)
cout << *(s+2) << endl; //ghi (取4個char元素的值,從「g」印到結束字元)
//使用迴圈一次印
for (int i =0; i < 3 ; i++){
cout << "位址s + " << i << "為:" << (s+i) << "\t";
cout << "此位址存放的資料為:" << *(s+i) << endl;
}
//位址 s + 0為:0088F8F4 此位址存放的資料為:abc
//位址 s + 1為:0088F8F4 此位址存放的資料為:def
//位址 s + 2為:0088F8F4 此位址存放的資料為:ghi
//一樣的效果不同的寫法
for (int i =0; i < 3 ; i++){
cout << "位址s + " << i << "為:" << &a[i] << "\t";
cout << "此位址存放的資料為:" << a[i] << endl;
}
//位址 s + 0為:0088F8F4 此位址存放的資料為:abc
//位址 s + 1為:0088F8F4 此位址存放的資料為:def
//位址 s + 2為:0088F8F4 此位址存放的資料為:ghi
```
### (四)陣列指標 (指標組成的陣列)
#### 1、宣告
```cpp=
char b[4] = "xyz";
char cc = 'A';
const char* p[3]; //char* (p[3])
p[0] = "abc";
p[1] = b;
p[2] = &cc;
cout << p[0] << endl; //abc (cout << 「指向「一個 byte」的位址」)
cout << P[1] << endl; //xyz (p[1] = &b[0],cout << 「指向「一個 byte」的位址」)
cout << p[2] << endl; //A+亂碼(p[2] = &cc, cout << 「指向「一個 byte」的位址」)
```
#### 2、給初始值
```cpp=
const char* pntr[3] = {"happy","frieday","fun"};
//備註:只要「指向的內容是不能改變的」,就必須加const
```
## 四、動態記憶體配置
```cpp=
//在記憶體取得一塊空間給指標專用
//在程式執行時,隨時要求、隨時釋放
// (1)配置記憶體: new
int* ip = new int(100); //ip指向一個新的記憶體位址,初始值為100
// (2)釋放記憶體: delete
delete ip;
// (3)配置陣列空間
int* ap = new int[100] //配置「100個整數」的記憶體空間
//(4)釋放陣列空間
delete[] ap;
```
## 五、參照 (reference)
### (一)宣告
```cpp=
int age = 18;
int& old = age; //宣告一個參照old,此參照為age的綽號(一定要給初始值)
cout << age << endl; //18
cout << old << endl; //18
```
### (二)使用
```cpp=
age = 19;
cout << age << endl; //19
cout << old << endl; //19
old = 20;
cout << age << endl; //20
cout << old << endl; //20
//通常放在函式的參數中使用
return 0;
```
### (三)指標參照比較
| 位址 | 0088F8F4 | 0088F8F5 | 0088F8F6 | 0088F8F7 |
| ------ | -------- | -------- | -------- | --- |
| 內容值 | i = 10 | | | |
↑
p指標指向i的位址
| 位址 | 0090F8F0 |
| ------ | -------- |
| 內容值 | p指標 = 0088F8F4
``` cpp=
//宣告一個整數變數i並給予初始值10
int i ;
i = 10;
cout << i << endl; // 10
//宣告一個整數指標 p 並且指著 i
int* p;
p = &i; //指標是存位址
cout << p << endl; //0088F8F4
cout << *p << endl; // 10 (取出p所指的位址裡面的值)
*p = 20 ; // i = 20
//宣告一個參照
int& r = i;
cout << r <<endl; //20 (i=20)
r = 30 ;
cout << i <<endl; //30 (i=r=30)
```
## 六、練習
### (一)題目一:
請寫一個使用以下二維陣列:
char id[3][21] = { "Alice", "Bob", "Cindy" };
char pw[3][21] = { "aa11", "bb22", "cc33" };
完成一帳號、密碼比對程式。
先由使用者分別輸入「帳號」與「密碼」,
若名字或密碼錯誤,即顯示「帳號或密碼錯誤」。
若名字及對應的密碼正確,即顯示「XXX您好!歡迎光臨!」。
(Hint: 用7-2的cin.getline()與strcmp()。)
```cpp=
#include <iostream>
#include<cstring>
using namespace std;
/*題目1:請寫一個使用以下二維陣列:
char id[3][21] = { "Alice", "Bob", "Cindy" };
char pw[3][21] = { "aa11", "bb22", "cc33" };
完成一帳號、密碼比對程式。
先由使用者分別輸入「帳號」與「密碼」,
若名字或密碼錯誤,即顯示「帳號或密碼錯誤」。
若名字及對應的密碼正確,即顯示「XXX您好!歡迎光臨!」。
(Hint: 用7-2的cin.getline()與strcmp()。)*/
int main() {
char id[3][21] = { "Alice", "Bob", "Cindy" };
char pw[3][21] = { "aa11", "bb22", "cc33" };
//(1)strlen() cin.getline()
cout << "請輸入帳號:";
char id1[21];
cin.getline(id1, 21);
//cin.ignore();
cout << "請輸入密碼:";
char pw1[21];
cin.getline(pw1, 21);
int i, x, y, z1, z2, z3;
z1 = 1;
z2 = 1;
z3 = 1;
for (i = 0; i < 3; i++) {
int x = strcmp(id[i], id1);
int y = strcmp(pw[i], pw1);
if (i == 0) {
if (x == 0 & y == 0) {
cout << id[i] << "您好!歡迎光臨!";
break;
}
else
z1 = 0;
}
if (i == 1) {
if (x == 0 & y == 0) {
cout << id[i] << "您好!歡迎光臨!";
break;
}
else
z2 = 0;
}
if (i == 2) {
if (x == 0 && y == 0) {
cout << id[i] << "您好!歡迎光臨!";
break;
}
else
z3 = 0;
}
if (z1 == 0 && z2 == 0 && z3 == 0) {
cout << "帳號或密碼錯誤";
break;
}
}
}
```
### (二)題目二:
請寫一程式,利用一個「指標」指向陣列「array[5] = {1,2,3,4,5}」,
並透過此「指標」將此陣列的「內容」從螢幕輸出。 (只能透過此「指標」輸出。)
```cpp=
#include<iostream>
using namespace std;
/*題目2:請寫一程式,利用一個「指標」指向陣列「array[5] = {1,2,3,4,5}」,
並透過此「指標」將此陣列的「內容」從螢幕輸出。 (只能透過此「指標」輸出。)*/
int main() {
int A[5] = {1,2,3,4,5};
int i;
int* s=A;
for(i=0;i<5;i++)
cout << *(s+i);
}
```
### (三)題目三:
(3) 請寫一程式,利用一個「陣列指標」將以下陣列的「內容」與「位址」印出來。
(只能透過此「陣列指標」印出。)
char a[3][6] = {"Alice", "Betty", "Cindy"}
內容:Alice, Betty, Cindy
位址:分別是a[0]、a[1]、a[2]的位址。
```cpp=
#include<iostream>
using namespace std;
/*請寫一程式,利用一個「陣列指標」將以下陣列的「內容」與「位址」印出來。
(只能透過此「陣列指標」印出。)
char a[3][6] = {"Alice", "Betty", "Cindy"}
內容:Alice, Betty, Cindy
位址:分別是a[0]、a[1]、a[2]的位址*/
int main() {
char A[3][6] = { "Alice", "Betty", "Cindy" };
char(*p)[6] = A;
cout << "利用指標印出陣列A的內容";
cout << endl;
cout << p[0] << endl;
cout << p[1] << endl;
cout << p[2] << endl;
cout << "利用指標印出陣列A的位址";
cout << endl;
cout << &p[0] << endl;
cout << &p[1] << endl;
cout << &p[2] << endl;
}
```