---
# System prepended metadata

title: 第四堂社課

---

## 第四堂社課

---

## 複習

----

## 遞增(```++```)與遞減(```--```)運算子

```cpp=
#include<iostream>
using namespace std;
int main(){
    int a=1;//a=1
    a++;
    cout<<a;//a=2
    ++a;
    cout<<a;//a=3
    a--;
    cout<<a;//a=2
    --a;
    cout<<a;//a=1
}
```

----

## 前置(```++a```)與後置(```a++```)的區別
其實沒啥區別。
但在運算上會有些許的不同:
```cpp=
int a,count=5;
a=count+++5;//a=10
```
```cpp=
int a,count=5;
a=++count+5;//a=11
```

----

## for 迴圈基本語法
```cpp=
for (初始;判斷;運算) {
    陳述句;
}
```
初始:只在進入迴圈時執行
判斷:判斷是否繼續迴圈
運算:每次一個迴圈循環後執行

----

## scratch 解釋
![image](https://hackmd.io/_uploads/Sk4JZhEx-x.png)

----

## while 迴圈基本語法
```cpp=
while(判斷) {
    陳述句;
}
```
判斷:判斷是否繼續迴圈

----

## scratch 解釋

![image](https://hackmd.io/_uploads/SyrsM2ExZl.png)

----

## do...while 迴圈基本語法
```cpp=
do{
    陳述句;
}while(判斷);
```
判斷:判斷是否繼續迴圈

----

## scartch 解釋

![image](https://hackmd.io/_uploads/B187BnEg-g.png)

----

## 略過迴圈迭代
當有一個迴圈你不想要執行時
你可以使用```continue```來跳過

----

## 中斷迴圈
當有一個迴圈之後的迴圈你都想要跳過時
你可以使用```break```來跳過

----

## 巢狀敘述
當你將多個條件判斷式或迴圈一層一層組合在一起
即稱之為**巢狀敘述**

![image](https://hackmd.io/_uploads/H1NAV3VeWe.png)

---

## APCS 初級題目挑戰!!!
今天我們來練習歷屆 APCS 的第一題 !!!
二十分鐘內只要寫出一題 AC ，就可以來拿獎品 !!!
只限前六名喔 !!!

以防還有人不知道課程代碼就先打在這裡了:
```+cYejX```

---

## 陣列

----

## 陣列的意義
當我們需要存取許多性質與功用相同，且具有連續性的值時，我們可以使用陣列將他們整合在一起

----

## 不用陣列

```cpp=
#include<iostream>
using namespace std;
int main(){
    int a0,a1,a2,a3,a4,a5,a6,a7,a8,a9;
    cin>>a0>>a1>>a2>>a3>>a4>>a5>>a6>>a7>>a8>>a9;
    cout<<a0<<'\n'<<a1<<'\n'<<a2<<'\n'<<a3<<'\n'<<a4<<'\n'<<a5<<'\n'<<a6<<'\n'<<a7<<'\n'<<a8<<'\n'<<a9<<'\n';
}
```
很麻煩，手打得很酸

----

## 使用陣列

```cpp=
#include<iostream>
using namespace std;
int main(){
    int a[10];
    for(int i=0;i<10;i++)cin>>a[i];
    for(inti=0;i<10;i++)cout<<a[i]<<'\n';
}
```
簡潔有力，十分方便

---

## C 風格陣列

----

## 資料型別
在學習陣列之前，先複習一下之前教過的資料型別
| 名稱 | 儲存值 | 例子 |
| :--------: | :--------: | :--------: |
| int | 整數 | 1 |
| double | 浮點數(小數) | 1.1 |
| bool | 布林值(1或0) | true |
| char | 字母 | a |
| string | 字串 | XiaoChengYi |

----

## C 風格陣列的宣告與定義
```cpp=
資料型別 陣列名稱[陣列長度]={第零項,第一項,...,第(陣列長度-1)項};
```
舉例:
```cpp=
int a[3]={0,1,2};
bool b[4]={true,false,1,0};
char c[5]={'c','h','a','r','\0'};
//char 型態的陣列在末項以 '\0' 表示字串結束
double d[2]={3.14159,2.71828};
string e[3]={"Xiaochengyi","Rollingmaster","KaiKai"};
```

----

## C 風格陣列的改變
當我們需要改變 C 風格陣列中的資料時，可以使用賦值運算子 ```=``` 
```cpp=
#include<iostream>
using namespace std;
int main(){
    int a[3]={0,1,2};//0 1 2
    //陣列的索引(項數)是從 0 開始的
    a[0]=3;//3 1 2
    a[1]=4;//3 4 2
    a[2]=5;//3 4 5
}
```

----

## C 風格陣列的引用
當我們需要讀取資料的時候，就會需要引用 C 風格陣列中的值，所以我們會使用 ```[]operator```

```cpp=
#include<iostream>
using namespace std;
int main(){
    int a[3];
    //陣列的索引(項數)是從 0 開始的
    for(int i=1;i<=3;i++)cin>>a[i];
    //int a[3]={0,1,2}
    cout<<a[0]<<endl;//0
    cout<<a[1]<<endl;//1
    cout<<a[2]<<endl;//2
}
```

----

## 圖解 ```[]operator```
![image](https://hackmd.io/_uploads/S1l0_yDeWl.png)

----

## 小練習:找出該項對應的值
``` int a[5]={0,3,5,6,-1}```
1.``` a[1]```
2. ```a[3]```
3. ```a[5]```

----

## 解答
1.```a[1]``` =```3```
2.```a[3]```=```6```
3.```a[5]```=不存在

----

## C 風格陣列多維陣列
當我們的資料不只是一個維度的時候，我們就需要用到多維陣列

```cpp=
//假設我們需要九宮格，每一格都存取一個數字
#include<iostream>
using namespace std;
int main(){
    int a[3][3]={
        {1,2,3},
        {4,5,6},
        {7,8,9}
    }
    //使用巢狀結構輸出二微陣列 a 
    for(int i=0;i<3;i++){
        for(int j=0;j<3;j++){
            cout<<a[i][j]<<' ';
        }
    }
    //1 2 3 4 5 6 7 8 9 
}
```

---

## C++ `std::vector` 

----

## 為甚麼要用 `std::vector` ?
```std::vector``` 是 C++ 標準函式庫 ```<vector>``` 中資料結構。與 C 風格陣列不一樣的地方是，他是一種動態陣列，可以自動調整大小，不需要另外去做動態分配的部分，十分的方便，一定要學起來。

----

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

----

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

----

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

```cpp= 
std::vector<資料型別>陣列名稱(陣列長度)
std::vector<資料型別>陣列名稱(陣列長度，值)
std::vector<資料型別>陣列名稱({第 0 項,第 1 項,...,第 n-1 項})
```
長度:初始陣列長度
值:當寫入某一個值時，它會自動將 ```std::vector``` 的每一項都初始化成該值

----

## 範例
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a(3);
    vector<int>b(3,6);// 6 6 6
    vector<int>c({1,2,3,4,5,6})//1 2 3 4 5 6
}
```

----

## `std::vector` 的引用
我們可以使用 ```[]operator``` 引用 ```std::vector``` 的資料

```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a(3);
    //陣列的索引(項數)是從 0 開始的
    for(int i=1;i<=3;i++)cin>>a[i];
    //int a[3]={1,2,3}
    cout<<a[0]<<endl;//1
    cout<<a[1]<<endl;//2
    cout<<a[2]<<endl;//3
}
```

----

## 圖解 ```[]operator```
![image](https://hackmd.io/_uploads/r1tOFJDxbg.png)

----

## `std::vector` 的引用
除了 ```[]operator``` ，我們也可以使用 ```at()``` 
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a({1,2,3});
    cout<<a.at(0)<<endl;//1
    cout<<a.at(1)<<endl;//2
    cout<<a.at(2)<<endl;//3
}
```
與 ```[] operator``` 不一樣的地方在於， ```at()``` 在引用位置超出邊界時會報錯

----

## 圖解 ```at()```
![image](https://hackmd.io/_uploads/B1A0vJweWe.png)


---

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

----

## 迭代器 iterator ```begin()``` 和 ```end()```
我們可以使用 ```begin()``` 和 ```end()``` 來知道 ```std::vector``` 的起點位置與終點位置

----

## 圖解 ```begin()```
![image](https://hackmd.io/_uploads/BJsGp68gZg.png)

----

## 圖解 ```end()```
![image](https://hackmd.io/_uploads/B1yfEkwgZl.png)

----

## 新增元素 ```push_back()```
我們可以使用 ``` push_back()```在陣列的最後新增元素
```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
}
```

----

## 插入元素 ```insert()```
我們可以使用 ```insert(iterator,value)``` 在指定位置插入元素
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a({0,1,2});//0 1 2
    a.insert(a.begin(),3);//3 0 1 2
    a.insert(a.begin()+2,4);//3 0 4 1 2
}
```

----

## 刪除元素 ```pop_back()```
我們可以使用 ```pop_back()``` 刪除陣列最後方的元素
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a({0,1,2});//0 1 2
    a.pop_back();//0 1
    a.pop_back();//0
}
```

----

## 刪除元素 ```erase()```
我們可以使用 ```erase(iterator)``` 刪除指定位置的元素，也可以使用 ```erase(iterator1,iterator2)``` 刪除某記憶體區間的元素
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a({0,1,2});//0 1 2
    a.erase(a.begin());//1 2
    a.erase(a.begin(),a.end());// 
}
```

----

## 刪除元素 ```clear()```
我們可以使用 ```clear()``` 清空 ```std::vector``` 陣列
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a({0,1,2});//0 1 2
    a.clear();//
}
```

----

## 讀取陣列長度 ```size()```
我們可以使用 ```size()``` 讀取陣列長度
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a({0,1,2});
    cout<<a.size();//3
}
```

----

## 調整陣列長度 ```resize()```
我們可以使用 ```resize()``` 調整陣列長度
```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<int>a({0,1,2});
    cout<<a.size();//3
    a.resize(5);
    cout<<a.size();//5
}
```

----

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

----

## ```std::vector``` 多維陣列的宣告、定義以及引用
宣告及定義:
```cpp=
std::vector<vector<...<vector<資料型別>>...>>陣列名稱(第 0 維長度,{第 1 維陣列長度,{...,{第 n-1 維陣列長度,初始值}}});
std::vector<vector<...<vector<資料型別>>...>>陣列名稱({{...{值,值,...,值},...,{值,值,...,值}}});
```
引用:
```cpp=
陣列名稱[第 0 維索引][第 1 維索引]...[ 第 n-1 維索引];
陣列名稱.at(第 0 維索引).at(第 1 維索引).....at(第 n-1 維索引);
陣列名稱[第 0 維索引].at(第 1 維索引)...[第 n-2維索引].at(第 n-1 維索引)
```


----

## 範例

```cpp=
#include<iostream>
#include<vector>
using namespace std;
int main(){
    vector<vector<int>>a(3,{3,0});
    /*
     0 0 0
     0 0 0
     0 0 0
     */
    vector<vector<int>>b({
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12},
        {13,14,15,16}
    });
    cout<<b[0][0]<<endl;//1
    cout<<b.at(1).at(1)<<endl;//6
    cout<<b.at(2)[2]<<endl;//11
    cout<<b[3].at(3)<<endl;//16
}
```

---

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