---
# System prepended metadata

title: C++ 程式設計
tags: [C/C++]

---

# C++ 程式設計

```cpp=
#include<iostream>
using namespace std;
int main(){
    //int i;
    for (int i=0;i<100;i++){
        int j;
    }
}
```


## 標頭檔
寫程式前，要先引入函式庫，這樣才可以使用函式庫內的function
```
#include<函式庫名稱>
```
像是要寫C++時，一定要引入`<iostream>`的函式庫
```
#include<iostream>
```

## 命名空間
命名空間又可以當作程式的識別碼，用來區分不同函式庫中相同名稱的function

以下程式碼為例，`cout`和`endl`前的`std`就式命名空間
```cpp=
#include<iostream>
int main(){
    std::cout<<"今天天氣真好"<<std::endl;
}
```
每次使用一次`cout`就要寫一次`std`，那這樣寫100次`cout`勢必很麻煩，因此可以直接全域定義程式碼會使用到`std`的命名空間
```cpp=
#include<iostream>
using namespace std;
int main(){
    cout<<"今天天氣真好"<<endl;
}
```


## 註解
註解可以用來解釋程式碼，提高程式碼的可讀性，有 **單行註解** 或是 **多行註解** ，註解中的所有文字都會被編譯器忽略。
### 單行註解
在`//`後的所有文字都會被當註解
```
//註解文字
```
### 多行註解
在`/*`到`*/`之間的所有文字都會被當註解
```
/*  
  註解文字
  註解文字
  註解文字
*/
```
## 數據類型
### 類型
C++常見的數據類型有6個

| 關鍵字 |     名稱     |
|:------:|:------------:|
|  bool  |    布林值    |
|  char  |     字元     |
| string |     字串     |
|  int   |     整數     |
| float  |    浮點數    |
| double | 雙精度浮點數 |
|  void  |     無值     |

### 修飾符
數據類型又有一個或是多個類型修飾符可以使用：
* singed 有號
* unsigned 無號
* short 短型
* long 長型

各類數據類型，占用大小，值的範圍參考下表
|  類型  |    修飾符+類型     | 占用大小(位元組) |             範圍             |
|:------:|:------------------:|:----------------:|:----------------------------:|
|  bool  |        bool        |        1         |       1是true 0是false       |
|  char  |        char        |        1         |          -128 ~ 127 參考[ASCII碼](https://zh.wikipedia.org/wiki/ASCII)          |
|        |    signed char     |        1         |          -128 ~ 127          |
|        |   unsigned char    |        1         |           0 ~ 255            |
|  int   |        int         |        4         |       -2^31^ ~ 2^31^-1       |
|        |     signed int     |        4         |       -2^31^ ~ 2^31^-1       |
|        |    unsigned int    |        4         |          0 ~ 2^32^           |
|        |     short int      |        2         |        -32768 ~ 32767        |
|        |  signed short int  |        2         |          0 ~ 65535           |
|        | unsigned short int |        2         |        -32768 ~ 32767        |
|        |      long int      |        4         |       -2^31^ ~ 2^31^-1       |
|        |  signed long int   |        4         |       -2^31^ ~ 2^31^-1       |
|        | unsigned long int  |        4         |          0 ~ 2^32^           |
| float  |       float        |        4         |  ±3.4×10^-38^ ~ ±3.4×10^38^  |
| double |       double       |        8         | ±1.7×10^-308^ ~ ±1.7×10^308^ |

### string
`string` 比較特別，他個概念就是多個字元組成的字串變數。
字元要使用單引號`''`，引號中間只能有一個字元
字串要用雙引號`""`，引號中間可以有多個字元
## 變數
### 定義
定義變數時，要先指定一個數據類型，再寫下變數名稱。
```
型態 名稱;
```
舉例：
```
int a;
float b;
double c;
string d;
```
如果有多個同數據類型的變數，可以寫在同行用逗號隔開。
```
int a,b,c;
```
### 初始化
在定義變數時可以指定一個初始值讓變數初始化，初始化由一個等號和一個常量組成。
```
型態 名稱 = 初始值;
```
舉例：
```
int a = 3, b = 4;
float c = 0.6;
char  d = 'x';
string  e = "test";
```
字元需用單引號`''`來表示

當變數沒有做初始化時，系統會自動初始化變數，參考下表：
|  類型  | 初始化默認值 |
|:------:|:------------:|
|  int   |      0       |
|  char  |     '\0'     |
|  string  |     "\0"     |
| float  |      0       |
| double |      0       |
### 常數
如果初始化定義的變數值不會更改時，可以使用`const`的修飾符，該變數值就無法有任何改變
```
const 型態 名稱 = 初始值;
const int a = 10;
```
### 算數運算符
| 運算符 |       描述       | 範例  |
|:------:|:----------------:|:-----:|
|   +    |     兩數相加     | a + b |
|   -    |    前數減後數    | a - b |
|   *    |     兩數相乘     | a * b |
|   /    |    前數除後數    | a / b |
|   %    | 前數減後數的餘數 | a % b |
|   ++   |     整數值+1     |  a++  |
|   -\-   |     整數值-1     |  a-\-  |

實作：
```cpp=
#include <iostream>
using namespace std;
 
int main(){
    int a = 20;
    int b = 10;
    int c ;
    
    c = a + b; //可以自行更換運算符
    cout << "c 的值是 " << c << endl ;
}
```
### 賦值運算符
| 運算符 |                  描述                  |           範例           |
|:------:|:--------------------------------------:|:------------------------:|
|   =    |         把右邊的值賦給左邊變數         |        c = a + b         |
|   +=   |    把左邊的值加上右邊值賦給左邊變數    | a += b (等同 a = a + b)  |
|   -=   |    把左邊的值減掉右邊值賦給左邊變數    | a -= b (等同 a = a - b)  |
|  \*=   |    把左邊的值乘上右邊值賦給左邊變數    | a \*= b (等同 a = a * b) |
|   /=   |    把左邊的值除上右邊值賦給左邊變數    | a /= b (等同 a = a / b)  |
|   %=   | 把左邊的值除上右邊值的餘數賦給左邊變數 |  a %= b(等同 a = a % b)  |

## 變數作用域
### 區域變數
變數只能在該區域才能使用，不同區域的變數可以有相同名稱。
```cpp=
#include<iostream>
using namespace std;
int main(){
    int a=10,b=5;
}
void test(){
    int a=5;
}
```
在`main`函式裡面的`a`和`test`函式裡面的`a`式兩個獨立的變數，互不影響。
`main`函式裡面的`b`不會在`main`函式以外的地方被讀到。
### 全域變數
變數在整個程式裡面式共通的，任何區域的程式碼的可以去更改全域變數的值
```cpp=
#include<iostream>
using namespace std;

int a = 20;

int main(){
    int b=5;
}
void test(){
    int c=5;
}
```
全域變數使用的名稱在區域變數宣告時就不能再次使用。
## 輸入輸出

### 標準輸出流cout
`cout`要與流插入運算符`<<`，使用，方式如下
```cpp=
#include <iostream>
using namespace std;
int main( )
{
   char name[50] = "aura";
   cout << name ;
}
```
不同的數據要一起輸出時要用`<<`隔開，方式如下
```cpp=
#include <iostream>
using namespace std;
int main( )
{
   char word[50] = "number = ";
   int num = 21;
   cout << word << num ;
}
```
變數也可以直接做運算
```cpp=
#include <iostream>
using namespace std;
int main( )
{
   int a = 21 , b = 13;
   cout << "a + b = " << a+b ;
}
```
換行可以用`endl`，等同`'\n'`
```cpp=
#include <iostream>
using namespace std;
int main( )
{
   cout << "一二三" << endl << "四五六";
}
```


### 標準輸出流cin
`cout`要與流提取運算符`>>`，使用，方式如下
```cpp=
#include <iostream>
using namespace std;
int main( )
{
   int a;
   cin >> a;
   cout << "a = " << a << endl ;
}
```
可以進行多數據輸入，每個變數用`>>`隔開
```cpp=
#include <iostream>
using namespace std;
int main( )
{
   int a, b ;
   cin >> a >> b;
   cout << "a = " << a << endl ;
   cout << "b = " << b << endl ;
}
```

## 判斷
### if
如果有符合條件，就會執行`if`內的程式碼
```
if(條件式){
    ...
}
```
### if...else
如果有符合條件，就會執行`if`內的程式碼，反之不符合的話，會執行`else`內的程式碼
```
if(條件式){
    ...
}
else{
    ...
}
```
### 多if
如果有符合條件，就會執行`if`內的程式碼，如果不符合，會去檢查`else if`的條件，不符合就在往下檢查，直到`else`或是沒判斷式。
`else if` 可以是多個但第一個一定要是`if`。
```
if(條件式){
    ...
}
else if(條件式2){
    ...
}
else{
    ...
}
```
### switch 
```
switch(變數名稱 或 運算式) {
    case 數字 或 字元:
        程式碼1
        break;
    case 數字 或 字元:
        程式碼2
        break;
    default:
        程式碼3
        break;
}
```

switch後面括號可以直接放變數或是運算式  
```
switch(a){
    ...
}

switch(x-y){
    ...
}
```

當你的變數或是運算有符合`case` 後面的數值，就會進入該`case`執行程式碼  
後面的`break`是用來跳出switch，不然會繼續找`case`  
```
switch(a){
    case 1:
        //當如果 a=1 就會執行這裡的程式碼
        break;
    case 2:
        //當如果 a=2 就會執行這裡的程式碼
        break;
}
```
如果你有多個條件要進入同一段程式碼，可以這樣寫
```
switch(a){
    case 1: case 3:
        //當如果 a=1 或 a=3 就會執行這裡的程式碼
        break;
    case 2:
        //當如果 a=2 就會執行這裡的程式碼
        break;
    default:
        //當如果 a不等於1或2 就會執行這裡的程式碼
        break;
}
```
`default`是當`case`都不成立時就會執行的段落，必須放在最後面
```
switch(a){
    case 1:case 3:
        //當如果 a=1 或 a=3 就會執行這裡的程式碼
        break;
    case 2:
        //當如果 a=2 就會執行這裡的程式碼
        break;
}
```

### 關係運算符
| 運算符 |         描述         |  範例  |
|:------:|:--------------------:|:------:|
|   ==   |     兩數是否相等     | a == b |
|   !=   |    兩數是否不相等    | a != b |
|   >    |   前數是否大於後數   | a > b  |
|   <    |   前數是否小於後數   | a < b  |
|   >=   | 前數是否大於等於後數 | a >= b |
|   <=   | 前數是否小於等於後數 | a <= b |

回傳值為1(`true`)或是0(`false`)

舉例：
```cpp=
#include <iostream>
using namespace std;

int main()
{
   int a = 20;
   int b = 10;
   int c ;

   if( a == b ){ //括號內可自行更換運算符
      cout << "a 等於 b" << endl ;
   }
}
```

### 邏輯運算符
| 運算符 |     描述     |       舉例       |           範例            |    程式碼    |
|:------:|:------------:|:----------------:|:-------------------------:|:------------:|
|   &&   |   且運算符   |  X條件 && Y條件  |     a大於b 和 b大於c      |  a>b && b>c  |
|  \|\|  |   或運算符   | X條件 \|\| Y條件 |     a小於b 或 a小於c      | a<b \|\| a<c |
|   !    | 否(非)運算符 |      !X條件      | 非a大於b(等同 a小於等於b) |    ! a>b     |


## 循環
### for 
```
for(起始式; 條件式; 更新式){
    ...
}
```

起始式：進入迴圈第一次會執行的動作  
條件式：每輪執行前，會做一次檢查，如果成立就繼續迴圈，直到條件式不成立  
更新式：每當執行完一輪，就會執行一次更新式  

實作：
```cpp=
#include<iostream>
using namespace std;

int i;

int main(){
    for(i=1;i<=10;i++){
        cout<<i<<endl;
    }
}
```
> i會從一開始(i=1)，如果小於等於10(i<=10)，就會執行i+1(i++)，直到i不小於等於10


### while 
```
while(條件式){
    ...
}
```
進入迴圈前會先檢查條件，成立後才會進入迴圈，迴圈會一直執行條件式不成立為止

實作：
```cpp=
#include<iostream>
using namespace std;

int i = 10;

int main(){
    while(i<10){
        cout<<"有進入迴圈"<<endl;
    }
}
```
> 在while迴圈裡，只要i一直小於10，那就會一直在迴圈裡面循環，直到i不小於10。

### do...while 
```
do{
    ...
}while(條件式)
```
迴圈會先執行一次，才會檢查條件，之後會一直執行條件式不成立為止

實作：
```cpp=
#include<iostream>
using namespace std;

int i = 10;

int main(){
    do{
        cout<<"有進入迴圈"<<endl;
    }while(i<10)
}
```
> 在while迴圈裡，只要i一直小於10，那就會一直在迴圈裡面循環，直到i不小於10。

### break 
在迴圈裡面執行到一半，要直接跳出迴圈時，可以使用`break`直接跳出，會跳離離他最近的迴圈
```cpp=
#include<iostream>
using namespace std;

int i = 1;

int main(){
    while(i<10){
        cout<<i<<endl;
        if(i == 4){
            break;
        }
        i++;
    }
}
```

## 函式
一般來說，除了有主函式`main()`以外，也可以自訂自己的函式，當如果有同一區段的程式會需要多次的重複執行，自訂函式就可以讓你的主函式美觀一點。
### 宣告
```
回傳型態 名稱(引數){
    副程式程式碼
}

Ex:
void test1(){
    副程式程式碼
}
```

### 回傳型態
一般用於回傳數值給呼叫的地方，如果沒有要回傳值可以用 void 。

常見型態：
| 程式碼 |     名稱     |
|:------:|:------------:|
|  void  | 不會回傳東西 |
|  int   |   回傳整數   |
|  char  |   回傳字元   |
| double |  回傳浮點數  |


### 名稱
副函式可以有多個，名稱可以自訂，但有些像是主程式的main名稱是不能用的，  
如果遇到不行使用的名稱編譯器會跟你講，不用擔心

### 參數&引數
引數可有可無，可以有多個引數，用於攜帶數值到副程式  
在主程式的變數和副程式的變數名稱互不影響，即使取相同名稱也是不一樣的東西  
呼叫函式時，提供給函式的資料叫做引數(argument)，接受引數的叫做參數(parameter)
```cpp=
#include<stdio.h>
#include<stdlib.h>

//一個引數
void test1(int a){ 
    //副程式程式碼
}

//多個引數
void test2(int a,char b,int c){ 
    //副程式程式碼
}

//沒引數
void test3(){ 
    //副程式程式碼
}

int main(){
    int k=10,v=30;
    char c='a';
    test1(k);
    test2(k,a,v);
    test3();
}
```
<font color=#FF0000>注意，副函式宣告需要在main函式之前</font>  
程式執行只會先從main函式執行，當有呼叫到副函式才會跳到副函式。

### 回傳值
回傳數值要用`return`，但要回傳的值資料型態要跟宣告副函式時的資料回傳型態一樣，
只要執行到`return`就會直接跳回到呼叫副程式的地方
參考以下程式碼。
```cpp=
#include<stdio.h>
#include<stdlib.h>

int add(int x,int y){ 
    int z=x+y;
    return z;
}

int main(){
    int a=10,b=30,d;
    d=add(a,b);
    //執行後d會等於40
}
```
## 數字
要使用這些數學函式時，需要引用數學頭文件
```
#include <cmath>
```
常用的數學函式：
|        函數        | 回傳值型態 |                 描述                 |
|:------------------:|:----------:|:------------------------------------:|
|    sin(double)     |   double   |                 正弦                 |
|    cos(double)     |   double   |                 餘弦                 |
|    tan(double)     |   double   |                 正切                 |
|    log(double)     |   double   |               自然對數               |
| pow(double,double) |   double   | 前數為x，後數為y，函數會回傳x的y次方 |
|    sqrt(double)    |   double   |                平方根                |
|   round(double)    |    int     |         將小數四捨五入成整數         |
|      abs(int)      |    int     |                絕對值                |
|    fabs(double)    |   double   |                絕對值                |
### 隨機數
要使用這些隨機函數時，需要引用時間頭文件，這樣隨機函數才會隨著時間有變化，不然`rand()`
結果會固定。
```cpp=
#include <iostream>
#include <ctime>

using namespace std;
 
int main ()
{
   int i,j;
 
   // 設定種子
   srand( (unsigned)time( NULL ) );

   // 執行10次
   for( i = 0; i < 10; i++ ){
      j= rand();// 產生隨機數字
      cout << j << endl;
   }

   return 0;
}
```
## 陣列
C++支援陣列數據結構，可以存放固定大小相同類型的集合。
### 宣告
宣告一個陣列，需要指定元素類型、數量
```
變數型態 陣列名稱 [ 陣列大小 ]
```
Ex.宣告一個類型為int，元素數量為5，名稱為a的陣列
```
int a[5];
```
陣列有 n 個空間，那編號就是是 0 ~ n - 1
| 編號 | a[0] | a[1] | a[2] | a[3] | a[4] |
|:----:|:----:|:----:|:----:|:----:|:----:|
| 數值 |  0   |  0   |  0   |  0   |  0   |
### 初始化
在C++中，可以逐個初始化陣列內的元素  
`{}`大括號內的元素數量，不能超過`[]`中括號內的數字  
```
int a[5] = { 2 , 1 , 4 , 5 , 3 };
```
| 編號 | a[0] | a[1] | a[2] | a[3] | a[4] |
|:----:|:----:|:----:|:----:|:----:|:----:|
| 數值 |  2   |  1   |  4   |  5   |  3   |


如果確定陣列內的元素數量和值，可以直接宣告，此時`[]`中可以不用打數字  
```
int a[] = { 2 , 1 , 6 , 8 , 4 , 3 };
```
| 編號 | a[0] | a[1] | a[2] | a[3] | a[4] | a[5] |
|:----:|:----:|:----:|:----:|:----:|:----:|:----:|
| 數值 |  2   |  1   |  6   |  8   |  4   |  3   |

### 數值修改
有一個陣列如下：
```
int a[] = {1,2,3};
```
| 編號 | a[0] | a[1] | a[2] |
|:----:|:----:|:----:|:----:|
| 數值 |  1   |  2   |  3   |

修改數字
```
a[1]=7;
```
| 編號 | a[0] |             a[1]             | a[2] |
|:----:|:----:|:----------------------------:|:----:|
| 數值 |  1   | <font color=#FF0000>7</font> |  3   |

## 字串
C++有兩種字串的表示法
* 字元陣列
* string 類型
### 字元陣列
字元字串是一些字元和結尾為`\0(又稱為null)`結尾組成的陣列
### * 定義
宣告一個類型為char(字元)，元素數量為6，名稱為word的陣列
```
char word[6] = { 'H', 'e', 'l', 'l', 'o', '\0' };
```
同樣的也可以寫成這樣：
```
char word[] = "Hello";
```
C++編譯器在初始化字元陣列時，會自動把`'\0'`放在尾端
| 編號 | word[0] | word[1] | word[2] | word[3] | word[4] | word[5] |
|:----:|:-------:|:-------:|:-------:|:-------:|:-------:|:-------:|
| 數值 |   'H'   |   'e'   |   'l'   |   'l'   |   'o'   |  '\0'   |

範例：
```cpp=
#include <iostream>
using namespace std;

int main ()
{
   char word1[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
   char word2[] = "Hello";
   cout << word1 << endl;
   cout << word2 << endl;
   return 0;
}
```
這兩種執行結果會一樣

有一些函式可以用來控制字串


| 函式 | 說明 |
|:----:|:----:|
| strcpy(s1, s2); | 複製字串2(s2)到字串1(s1) |
| strcat(s1, s2); | 把字串2(s2)連接到字串1(s1)的尾端 |
| strlen(s1); | 回傳字串1(s1)的長度 |
| strchr(s1, c); | 回傳字元c在字串1(s1)第一次出現的位置 |
| strstr(s1, s2); | 回傳字串2(s2)在字串1(s1)第一次出現的位置 |

### string 類型
string除了有上述字元陣列的功能，引入`<string>`的頭文件，還有增加其他更多個功能可以使用。
```cpp=
#include <iostream>
#include <string>
using namespace std;
int main ()
{
   string str1 = "Hello";
   string str2 = "World";
   string str3;
   int  len ;
   // 複製str1到str3
   str3 = str1;
   cout << "str3 : " << str3 << endl;
   // 連接str1和str2
   str3 = str1 + str2;
   cout << "str1 + str2 : " << str3 << endl;
   // str3的字串長度
   len = str3.size();
   cout << "str3.size() :  " << len << endl;
   return 0;
}
```

## 指標

### 指標是什麼?
平常程式執行時
```
int main(){
    int a = 18;
    int b = 7;
    int c = 50;
    int d = 100;
    int e = 12;
}
```

以 `int a = 18;` 為例，程式執行時，處理器會去跟記憶體要一塊空間，把18這個資料放進去。  

| 變數型態 | 位元組 |
|:--------:|:------:|
|   bool   |   1    |
|   char   |   1    |
|   int    |   4    |
|   long   |   8    |
|  float   |   4    |
|  double  |   8    |


一塊空間的大小，會隨著資料型態產生變化，把記憶體比喻成一棟大樓，一個位元組為一層樓，像是一個`int`變數就需要4層樓才能存放。  

以上述程式碼舉例，存放在記憶體內就長這樣  

| 記憶體位址(起始位址) |     數值     |
|:----------:|:-----------:|
| 0x0012FF6c |     ...      |
| 0x0012FF70 |      18      |
| 0x0012FF74 |       7   |
| 0x0012FF78 |      50   |
| 0x0012FF7c |      100   |
| 0x0012FF80 |      12   |
| 0x0012FF84 |     ...      |

註1：記憶體位址是由處理器分配的，每次執行程式時記憶體位址都可能不一樣。  
註2：記憶體位址為16進位。  
<br><br>
也就是說，當我們宣告一個變數時，會有三個元素：

| 變數位址(起始位址) |     變數數值     | 變數名稱 |
|:----------:|:-----------:| :---: |
| 0x0012FF70 |     18      | a |

除禮器會向記憶體要一塊空間來儲存變數，這個儲存空間有一個起始位址。加上這個變數的名稱a與變數值18。

通常會把變數的位址，稱為「指向該變數的指標」。

### 取址
在`C++`中取址的方式就是放`&`在變數前面  

```cpp=
#include<iostream>
using namespace std;

int main(){
    int a = 18;
    cout << "變數 a 的值：" << a << endl;
    cout << "變數 a 的記憶體位址：" << &a << endl;
}
```
這個程式中，宣告了一個 int 整數 a，並印出「&a」的值，知道 a 所在的記憶體位址

### 取值
利用`*pointer`的方式去讀取該位址的值
```cpp=
#include<iostream>
using namespace std;

int main(){
    int a = 18;
    cout << "變數 a 的值：" << a << endl;
    cout << "變數 a 的記憶體位址：" << &a << endl;
    cout << "變數 a 的位址的值：" << *&a << endl;
}
```
也可以說，`*&a`和`a`是等價的。

### 指標變數

當今天有了指標，就會需要存放指標的變數
平常程式執行時
```
int* pointer
```
宣告時，用`*`來表示 pointer 這個變數是個指標
```
int b; 
b = 2; 
int* pointer; 
pointer = &b; 
```
`&`是用來把變數的地址取出來，  
<font color=#FF0000>注意，不能寫成`pointer = b;`， pointer 是專門存放地址的變數。</font>  

```
pointer = &b; 
```

又稱：指標變數 pointer 指向了變數 b

當要取指標變數的值時，也等同於取變數b的值
```cpp=
#include<iostream>
using namespace std;

int main(){
    int b = 18;
    int* pointer = &b
    cout << "變數 b 的值：" << b << endl;
    cout << "變數 b 的記憶體位址：" << &b << endl;
    cout << "變數 pointer 的值：" << pointer << endl;
    cout << "取 pointer 位址的值：" << *pointer << endl;
}
```

## 數據結構


###### tags: `C/C++`


## 存儲