## 第四堂社課
---
## 複習
----
## 遞增(```++```)與遞減(```--```)運算子
```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 解釋

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

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

----
## 略過迴圈迭代
當有一個迴圈你不想要執行時
你可以使用```continue```來跳過
----
## 中斷迴圈
當有一個迴圈之後的迴圈你都想要跳過時
你可以使用```break```來跳過
----
## 巢狀敘述
當你將多個條件判斷式或迴圈一層一層組合在一起
即稱之為**巢狀敘述**

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

----
## 小練習:找出該項對應的值
``` 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```

----
## `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()```

---
## C++ ```std::vector``` 的基礎操作
----
## 迭代器 iterator ```begin()``` 和 ```end()```
我們可以使用 ```begin()``` 和 ```end()``` 來知道 ```std::vector``` 的起點位置與終點位置
----
## 圖解 ```begin()```

----
## 圖解 ```end()```

----
## 新增元素 ```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 碼對照表

----
## 字元的運算
因為有了 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
}
```