---
# System prepended metadata

title: 第五堂社課

---

## 第五堂社課

---

## 複習

----

## C 風格陣列

```cpp=
#include<iostream>
using namespace std;
int main(){
    int a[3]={1,2,0};// 陣列的宣告與定義
    a[2]=3;// 陣列的改變
    for(int i=0;i<3;i++)cout<<a[i]<<endl;//陣列的引用
}
```

----

## C++ `std::vector` 

```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    // std::vector 的宣告與定義
    vector<int>a(3,0);
    vector<int>b({1,0,-1});
    // std::vector 的改變
    b[1]=1;
    b.at(2)=2;
    // std::vector 的引用
    cout<<a[0];
    cout<<b.at(1);
    
}
```

----

## C++ ```std::vector``` 的基礎操作

`push_back()` : 在陣列的最後新增元素
`insert()` : 在指定位置插入元素
`pop_back()` : 刪除陣列最後方的元素
`erase()` : 刪除指定位置或指定記憶體區間的元素
`clear()` : 清空 `std::vector` 陣列
`size()` : 讀取陣列長度
`resize()` : 調整陣列長度
`empty()` : 讀取陣列是否為空


----

## 範例

```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a;
    for(int i=0;i<10;i++)a.push_back(i);// 0 1 2 3 4 5 6 7 8 9
    a.insert(a.begin()+4,-1);// 0 1 2 3 -1 4 5 6 7 8 9
    a.pop_back();// 0 1 2 3 -1 4 5 6 7 8
    a.erase(a.begin()+4);// 0 1 2 3 4 5 6 7 8 
    a.erase(a.end()-2,a.end());// 0 1 2 3 4 5 6
    cout<<a.size()<<endl;// 7
    cout<<a.empty()<<endl;// 0
    a.resize(a.size()+2);// 0 1 2 3 4 5 6    
    cout<<a.size()<<endl;// 9
    cout<<a.empty()<<endl;// 0
    a.clear();//
    cout<<a.size()<<endl;// 0
    cout<<a.empty()<<endl;// 0
}
```

---

## ```char``` 字元

----

## 字元是什麼
```char``` 是 C++ 中最基本的字元型別，儲存單一字元
而這些字元的儲存會使用 ASCII 碼

----

## ASCII 碼
ASCII 碼是「美國資訊交換標準代碼」，是一種電腦編碼系統，用來將英文字母、數字和符號轉換成電腦能讀取的二進位代碼，以便進行資訊交換和傳輸。

----

## ASCII 碼對照表
![image](https://hackmd.io/_uploads/Hy-oR53eWl.png)


----

## 字元的運算
因為有了 ASCII 碼，我們可以對字元做簡單的運算
```cpp=
#include<iostream>
using namespace std;
int main(){
    char a='a',b='b',c='1',d='d',e='e',f='f';
    int C=c-'0';
    cout<<a-b<<endl;//-1
    cout<<C<<endl;//1
    cout<<int(d)<<endl;//100
    cout<<(e>f)<<endl;//0
}
```

----

## `cctype` 函式
在對字元進行操作時，有一些比較方便的函式在 `C++ <cctype>` 內:
```cpp=
#include<iostream>
#include<cctype>
using namespace std;
int main(){
    char a='a';
    cout<<isalpha(a)<<endl;//是否為字母
    cout<<isupper(a)<<endl;//是否為大寫字母
    cout<<islower(a)<<endl;//是否為小寫字母
    cout<<isdigit(a)<<endl;//是否為數字
    cout<<isalnum(a)<<endl;//是否為數字或字母
    cout<<isspace(a)<<endl;//是否為空格 ' '
    cout<<isblank(a)<<endl;//是否為空格 ' ' 或 '\t'
    cout<<toupper(a)<<endl;//將 a 從小寫轉換成大寫的 ASCII
    cout<<tolower(a)<<endl;//將 a 從大寫轉換成小寫的 ASCII
}
```

---

## C++ ```std::string```

----

## 為何要用 ```std::string```
```std::string``` 是 C++ 標準函式庫 ```<string>``` 中資料結構。與 ```char []``` 不一樣的地方是，他可以自動調整大小，不需要另外去做動態分配的部分，十分的方便，一定要學起來。

----

## 使用 ```char []```
```cpp=
#include<iostream>
using namespace std;
int main(){
    char a[10];//必須事先定義陣列長度
    for(int i=0;i<10;i++)cin>>a[i];
    cin>>a[10];//(X)
}
```
當我們需要的陣列長度大於一開始宣告的 ```char []``` 長度時，就沒辦法輸入了，如果真的硬要使用的話就會需要用到動態分配記憶體的概念

----

## 使用 `std::string`
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a;
    cin>>a;
    a.resize(a.size()+1);
    cin>>a[a.size()-1];
}
```
當我們想要增長 ```std::string``` 時，只需要用簡單的修飾器(後面會教)就可以完成;

----

## `std::string` 的宣告與定義

```cpp= 
std::string 字串名稱 = "字串值";
std::string 字串名稱("字串值");
```

字串值:可以是任意數字、字母和符號
**注意** : 單一字元使用單引號 ```' '```，字串則使用 ```" "```

----

## 範例
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="Xiaochengyi";
    string b="kaikai"
}
```

----

## `std::string` 的引用
我們可以使用 ```[]operator``` 和 ```at()``` 引用 ```std::string``` 的資料，也可以直接寫字串名稱引用整個字串

```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="Xiaochengyi";
    //字串的索引(項數)是從 0 開始的
    cout<<a[0]<<endl;//X
    cout<<a.at(1)<<endl;//i
    cout<<a<<endl;//Xiaochengyi
}
```

---

## C++ ```std::string``` 基礎操作

----

## 字串的相加 `+`
當我們想要將兩個字串串接在一起時，可以使用 `+` 
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="xiaoxiao",b="Xiaochengyi";
    cout<<a+b<<endl;//xiaoxiaoXiaochengyi
}
```

----

## 字串的相加 `append()`
除了使用 `+` 將兩個字串串接在一起，也可以使用 `append()`
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="xiaoxiao",b="Xiaochengyi";
    a.append(b);
    cout<<a<<endl;//xiaoxiaoXiaochengyi
}
```

----

## 整行輸入 ```getline()```
因為正常來說 ```std::string``` 的輸入在遇到空格後就會結束，所以我們可以使用 ```getline(輸入串流,字串名稱)``` 輸入整行的包含空格的字串
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a;
    getline(cin,a);//輸入整行包含空格的字串
}
```

----

## 新增元素 ```push_back()```
我們可以使用 ``` push_back()```在字串的最後新增元素
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a;
    for(int i=0;i<10;i++)a.push_back(i+65);
    cout<<a<<endl;//ABCDEFGHIJ
}
```

----

## 插入元素 `insert()`
我們可以使用 `insert(iterator,value)` 在指定位置插入元素
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="Xiaochengyi";
    a.insert(4,"xiao");//Xiaocxiaohengyi
}
```

----

## 刪除元素 `pop_back()`
我們可以使用 `pop_back()` 刪除字串最後方的元素
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    string a="Xiaochengyi";//Xiaochengyi
    a.pop_back();//Xiaochengy
    a.pop_back();//Xiaocheng
}
```

----

## 尋找子字串 `find()`
當我們需要在字串中尋找對應的子字串，則可以使用 `find()` 尋找該子字串第一個被發現的位置
```cpp=
#include<iostream>
using namespace std;
int main(){
    string a="Xiaochengyi";
    cout<<a.find("Xiao")<<endl;// 0
    cout<<a.find("xiao")<<endl;// 亂碼(找不到)
}
```

----

## 擷取子字串 `substr()`
當我們需要把某個字串的其中一部份擷取下來時，就可以使用 `substr(位置,長度)` 
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="Xiaochengyi";
    cout<<a.substr(4,7)<<endl;//chengyi
}
```

----

## 刪除元素 `clear()`
我們可以使用 `clear()`清空字串
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="Xiaochengyi";//0 1 2
    a.clear();//
}
```

----

## 讀取字串長度
## ```size()``` 和 ```length()```
我們可以使用 ```size()``` 和 ```length()``` 讀取字串長度
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="ABC";
    cout<<a.size();//3
    cout<<a.length();//3
}
```

----

## 調整字串長度 ```resize()```
我們可以使用 ```resize()``` 調整字串長度
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="Xiaochengyi";
    cout<<a.size();//11
    a.resize(a.size()+1);
    cout<<a.size();//12
}
```

----

## 讀取字串是否為空 ```empty()```
我們可以使用 ```empty()``` 讀取陣列是否為空
```cpp=
#include<iostream>
#include<string>
using namespace std;
int main(){
    string a="Xiaochengyi";
    cout<<a.empty();//0
    a.clear();
    cout<<a.empty();//1
}
```

---

## 變數的域

----

## 什麼是變數的域
在目前學習的變數中，基本上都處於主程式 `main` 中，但是實際上，變數的作用是有範圍的，主要是以大括號 `{}` 為分界

----

## 範例
```cpp=
#include<iostream>
using namespace std;
int a=0;// 全域變數
int main(){
    cout<<a;// 0
    int a=1;// 區域變數
    {
        cout<<a;// 1
        int a=2;// 區域變數
        {
            cout<<a;// 2
            int a=3;// 區域變數
            cout<<a;// 3
        }
        cout<<a;// 2
    }
    cout<<a;// 1
}
```

---

## 函式

----

## 為甚麼要用函式 ?
在我們寫程式的過程中，難免會遇到很多需要使用同樣的架構，卻是使用不同變數的情況。雖然說有些情況可以直接用迴圈解決，但是在不可抗力且為了追求程式的可閱讀性之情況下，使用函式是一個不錯的選擇

----

## 不使用函式
```cpp=
/*This is a C++ code of 1A2B edited by Gemini 3 Pro*/
#include<iostream>
#include<cstdlib>
using namespace std;
int main(){
    int Ans[4],Giv[4],A{},B{},Times{};
    char choice;
    bool isDuplicate;
    cout<<"Write in 4 different numbers between 0~9\n";
    while(true){
        cout<<"Continue?(y/n)\n";
        cin>>choice;
        if(choice=='y'){
            system("cls");
            break;
        }
        else if(choice=='n'){
            system("cls");
            cout<<"GAME OVER\n";
            exit(0);
        }
        else cout<<"We're not sure what you meant\n";
    }
    for(int i=0;i<4;i++){
        while(true){
            isDuplicate=false;
            cin>>Ans[i];
            for(int j=0;j<i;j++) if(Ans[j]==Ans[i]||Ans[i]<0||Ans[i]>9){
                isDuplicate=true;
                break;
            }
            if(isDuplicate){
                cout<<"This number is unacceptable\nPlease think of another suitable number\n";
                while(true){
                    cout<<"Continue?(y/n)\n";
                    cin>>choice;
                    if(choice=='y'){
                        system("cls");
                        break;
                    }
                    else if(choice=='n'){
                        system("cls");
                        cout<<"GAME OVER\n";
                        exit(0);
                    }
                    else cout<<"We're not sure what you meant\n";
                }
            }
            else break;
        }
    }
    cout<<"Are you ready for the numbers?\n";
    while(true){
        cout<<"Continue?(y/n)\n";
        cin>>choice;
        if(choice=='y'){
            system("cls");
            break;
        }
        else if(choice=='n'){
            system("cls");
            cout<<"GAME OVER\n";
            exit(0);
        }
        else cout<<"We're not sure what you meant\n";
    }
    cout<<"Please guess 4 different numbers between 0~9\n\"A\" means how many correct ones are at the correct places\n\"B\" means how many correct ones are at the wrong places\n";
    while(true){
        cout<<"Continue?(y/n)\n";
        cin>>choice;
        if(choice=='y'){
            system("cls");
            break;
        }
        else if(choice=='n'){
            system("cls");
            cout<<"GAME OVER\n";
            exit(0);
        }
        else cout<<"We're not sure what you meant\n";
    }
    cout<<"Please write in the four different numbers you guess\n";
    while(true){
        Times++;
        for(int i=0;i<4;i++){
            while(true){
                isDuplicate=false;
                cin>>Giv[i];
                for(int j=0;j<i;j++) if(Giv[j]==Giv[i]||Giv[i]<0||Giv[i]>9){
                    isDuplicate=true;
                    break;
                }
                if(isDuplicate){
                    cout<<"This number is unacceptable\nPlease think of another suitable number\n";
                    while(true){
                        cout<<"Continue?(y/n)\n";
                        cin>>choice;
                        if(choice=='y'){
                            system("cls");
                            break;
                        }
                        else if(choice=='n'){
                            system("cls");
                            cout<<"GAME OVER\n";
                            exit(0);
                        }
                        else cout<<"We're not sure what you meant\n";
                    }
                }
                else break;
            }
        }
        A=0;
        B=0;
        for(int i=0;i<4;i++){
            for(int j=0;j<4;j++){
                if(Ans[i]==Giv[j]){
                    if(i==j) A++;
                    else B++;
                    break;
                }
            }
        }
        cout<<"\t|\t"<<A<<" A "<<B<<" B\n";
        if(A==4) break;
    }
    cout<<"You got the correct numbers!\nYou totally use "<<Times<<" times!";
    return 0;
}
```

----

## 使用函式
```cpp=
/*This is a C++ code of 1A2B written by Darrenw1004*/
#include<iostream>
#include<cstdlib>
using namespace std;
void Continuer();
void Input(int Func[],bool UsingJudge);
void Judge(int Ans[],int Giv[],int &A,int &B);
int main(){
    int Ans[4],Giv[4];
    int A{},B{},Times{};
    cout<<"Write in 4 different numbers between 0~9\n";
    Continuer();
    Input(Ans,1);
    cout<<"Are you ready for the numbers?\n";
    Continuer();
    cout<<"Please guess 4 different numbers between 0~9\n\"A\" means how many correct ones are at the correct places\n\"B\" means how many correct ones are at the wrong places\n";
    Continuer();
    cout<<"Please write in the four different numbers you guess\n";
    while(true){
        Times++;
        Input(Giv,1);
        Judge(Ans,Giv,A,B);
        cout<<"\t|\t"<<A<<" A "<<B<<" B\n";
        if(A==4){
            break;
        }
    }
    cout<<"You got the correct numbers!\nYou totally use "<<Times<<" times!";
    return 0;
}
void Continuer(){
    char choice={};
    cout<<"Continue?(y/n)\n";
    cin>>choice;
    if(choice=='y'){
        system("cls");
    }
    else if(choice=='n'){
        system("cls");
        cout<<"GAME OVER\n";
        exit(0);
    }
    else{
        cout<<"We're not sure what you meant\n";
        Continuer();
    }
}
void Input(int Func[],bool UsingJudge){
    for(int i=0;i<4;i++){
        while(true){
            bool isDuplicate{};
            cin>>Func[i];
            if(UsingJudge){
                for(int j=0;j<i;j++){
                    if(Func[j]==Func[i]||Func[i]<0||Func[i]>9){
                        isDuplicate = true;
                        break;
                    }
                }
                if(isDuplicate){
                    cout<<"This number is unacceptable\nPlease think of another suitable number\n";
                    Continuer();
                }
                else{
                    break;
                }
            }
            else{
                break;
            }
        }
    }
}
void Judge(int Ans[],int Giv[],int &A,int &B){
    A=0;
    B=0;
    for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
            if(Ans[i]==Giv[j]){
                if(i==j){
                    A++;
                }
                else{
                    B++;
                }
                break;
            }
        }
    }
}
```

----

## 函式的宣告
```cpp=
資料型別 函式名稱(參數);
```
參數 : 函式內部的區域變數，各個參數之間以 `,` 隔開

----

## 函式的定義
```cpp=
資料型別 函式名稱(參數){
    定義
}
```

----

## 函式的引用
```cpp=
函式名稱(引數);
```
引數 : 傳入函式的實際數值或變數，各個引數之間以 `,` 隔開

----

## 函式規則
1. 函式的宣告必須先於函式的引用
2. 函式的定義可以與宣告拆開，並且不一定需要先於函式的引用
3. 函式不一定會有參數
4. 函式不一定會有回傳值
5. 函式的引用不一定會有引數


----

## 函式架構
```cpp=
資料型別 函式名稱(參數){
    陳述句;
    return 回傳值;
}
```
回傳值 : 回傳值須與函式的資料型別相同。若無，則回傳值設為 `0` 表函式結束或直接省略

----

## 範例
```cpp=
#include<iostream>
using namespace std;
// 函式的宣告
void myCout(int a);// 函式的定義先於函式的引用
int main(){
    int x=1;
    // 函式的引用
    myCout(x);
}
// 函式的定義
void myCout(int a){
    cout<<a<<endl;
}
```

----

## 函式的參數
函式的參數主要是定義只在該函式中出現的區域變數。我們可以在引用時，使用引數將值傳入函式參數中，以達到對函式參數賦值的效果

----

## 範例
```cpp=
#include<iostream>
using namespace std;
// 函式的宣告
int myPlus(int a,int b);// 函式的定義先於函式的引用
int main(){
    int x=1,y=2;
    // 函式的引用: 因為函式是 int 型態的，所以我們把它當作一個 int 型態的變數使用，故可以輸出
    cout<<myPlus(x,y)<<endl;
}
// 函式的定義
int myPlus(int a,int b){
    return a+b;
}
```

---

## 遞迴

----

## 什麼是遞迴
遞迴就是函式中一直套函式，然後在達到某一個條件後停止開始回傳值。這與迴圈有部分相似，但是也有它不同之處。

----

## 使用遞迴
```cpp=
#include<iostream>
using namespace std;
int Fib(int n){
    if(n==0)return 0;
    if(n==1)return 1;
    return Fib(n-1)+Fib(n-2);
}
int main(){
    int n;
    cin>>n;
    cout<<Fib(n)<<endl;
}
```

----

## 使用迴圈
```cpp=
#include<iostream>
using namespace std;
int main(){
    int a=0,b=1,c,n;
    cin>>n;
    for(int i=0;i<n;i++){
        c=b;
        b+=a;
        a=c;
    }
    cout<<b<<endl;
}
```
