# <font color="1d206e">**C++程式語言教學講義**
## **海山高中 資訊研究社第六屆** </font>
> #### 作者 : 教學 曾沛芝
---
# 壹、基礎
## 零.標頭檔
```c=
#include<bits/stdc++.h>
using namespace std;
int main(){
//這裡寫程式碼
}
```
## 一、輸出輸入
### 1.輸入(cin)
```c=
int x;
cin >> x;
```
### 2.輸出(cout)
```c=
int x;
cout << x;
```
### 3.換行(endl vs '\n')
```c=
cout << endl;
cout << "\n"
cout << "apple\n"
//兩者作用一樣,但'\n'適合加在原本就要輸出字元或字串後面,比較快速
```
### 4.加空格
```c=
cout << " ";
```
> 很直覺,用包字元的雙引號包住空格就好了
## 二、自定義變數
### 0.宣告地點
未完待續
### 1.常見類型
```c=
int x = 10; // 整數
string x = "apple"; // 字串
char x = 'A'; // 字元
double x = 3.14; // 雙精準浮點數
float x = 3.14; // 單精準浮點數
bool x = true; // 布林值只有true/false
```
### 2.需要套用值 <font color="#f00"> 過大</font>(定義變數時用 long long)
```c=
long long x = 2000000;
```
### 3.布林值
* 宣告方法 :
```c=
bool a = true;
```
* 布林值不像整數變數`int`或是字串變數`string`可以自由放東西進去,<font color="red">布林值只會是兩個值 2 選 1 ,
真 ( true ) or 假 ( false )。</font>
(0 代表 false,1 代表 true,直接打英文也可以)
### 4.鎖定變數
```c=
const int x = 10; //之後x不能更改
```
### 5.自動推導(auto)
```c=
auto x = 10 //推斷為 int
auto y = 3.14 //推斷為 double
```
> 不建議使用auto定義,電腦可能判斷錯
### 6.陣列變數
> 一次存取多個相同型態的值
```c=
int a[3] = {1,2,3};
vector<int> a(3);
//以下二維陣列
int a[2][3] ={{1,2,3}{4,5,6}};
vector<vector<int>> a(2,vector<int>(3));
```
> 一般陣列對比vector的差別,請看之後章節
### <font color="1d206e">7.**結構(struct)**</font>
<font color="blue">適用需要將多種</font> <font color="red">不同類型資料 </font><font color="blue">處存於同一處時</font>
* 例如 : 一個學生同時有他的的名稱、年齡、成績
就可以這樣寫
```c=
struct Student{
string name = {};
int age;
float score;
//都保持空白
}
```
* 而要如何呼叫呢?
首先在`main`主函數裡面用<font color="blue">剛剛寫的 : `struct Student`的名稱</font>[`Student`]去定義一個變數
```c=
int main(){
Student s1[5];
//創建型態為Student的陣列
//意即每一格都有name age score三種資料
}
```
> 這其實跟`int string float`是一樣的用法,只不過你用`struct`自己創建了一個
* 要如何呼叫裡面`struct`的小點?
```c=
s1[0].name = "Tom";
s1[0].age = 19;
s1[0].score = 59.9;
//用 s1[0](變數名稱).name(結構內變數名稱)呼叫
}
```
### 8.如果 ( if )
```c=
if(//條件){
//程式碼
}
```
* 如果達成括弧`()`內條件,就執行大括弧`{}`內程式碼。
* 如需多項條件比較如下 :
**else 否則**
```c=
if(//條件){
//程式碼
}
else if(//條件){
//程式碼
}
else if(//條件){
//程式碼
}
else{
//程式碼
}
```
* `else if`代表<font color = "red">其他,意即如果上面沒有達成才往下</font>
* `else`最後一個沒有條件,如果上面的`if`和`else if`都沒有達成才會執行`else`
### 9. for迴圈
* i每一輪數值不同
* 可自定義幾輪
```c=
for(int i = 0;i < 2;i ++){
//程式碼
}
```
* 以上為一個執行2次的迴圈,執行方法如下 :
1. 第一輪判斷 : i = 0,i有小於2,所以執行一次,下一輪i++。
1. 第二輪判斷 : i = 0 + 1 = 1,i有小於2,所以執行一次,下一輪i++。
1. 第三輪判斷 : i = 1 + 1 = 2,i<font color = "red">沒有</font>小於2,所以不執行,結束迴圈
* <font color = "blue">由此可知此迴圈
1. 會跑`2`次
2. 第一次的時候`i = 0`第二次的時候`i = 1`</font>
---
### 10. while迴圈
```c=
while(//條件){
//要執行程式
}
```
### 11.條件
* 列舉一些常見的條件在底下 :
```c=
a > b
a >= b
a == b //a等於b?
a != b //a不等於b?
a > b && a > c //a > b "且" a > c(兩個同時達成才執行)
a > b || a > c // "或" (只達成一個就執行)
```
* 如果變數是布林值 ( **bool** ),可以直接寫變數名稱。
```c=
bool apple = true;
if(apple){//apple是否為真
}
if(!apple)}//apple是否為假
}
```
* 一個布林值apple,值為true。
* `if(apple)`代表:如果apple是`true`就執行
* `if(!apple)`代表:如果apple是`false`就執行
---
# 貳、判斷
## 一、字串 判斷 (string s;)
都以`string s;` 舉例
### 1.讀取<font color="red">整行</font>字串 (getline)
* cin有一個很大的特點,會在使用者輸入<font color="blue">空白鍵或是enter來當成結束的依據</font>
例如 : 想讓 "Teddy Liu" 這是一個字串,存在同一個變數中時,`string s; cin >> s `就做不到。<font color="red">電腦會自動將Teddy和Liu分開儲存</font>,因為中間含有空格。
* 若想將字串 "Teddy Liu" 存在一個變數中,請看底下示範
```c=
string s; //不可以
getline(cin,s); //可存含有空格字串
```
> 需要注意的是,`getline`只會把enter鍵當成結束的依據
### 2.判斷字串有幾個字母
* 例如:"apple"有5個,"toy"有3個
```c=
string s = "apple";
x = s.size();
cout << x;
//會得到 5
```
其他寫法為 :
```c=
int x;
x = s.length();
x = s.size();
```
* 兩者同樣意思,記自己喜歡的就好
### 3.`s[i]`(取字串中第i個字母)
```c=
string s = "apple"
char x = s[0] //"apple"的第一位字母'a'
char y = s[4] //"apple"的第五位字母'e'
```
> 注意! <font color="red">第一位從s[0]取
</font>若s陣列大小為5格,最後一位只到s[4],<font color="red">s[5]不存在</font>,若引用會爆錯。
### 4.從第x位開始取y個 (s.substr(x,y))
```c=
string s = "abcdef";
string t = s.substr(2,3);
cout << t
```
```c=
執行結果為:cde
(從第二個字'c',取3個字"cde")
```
### 5.找尋有沒有這東西/位置 (s.find)
```c=
s.find("abc");
```
* 如果**含有** "abc" :
```c=
string s = "sssabc";
cout << s.find(abc);
```
```c=
執行結果 : 3
//因為"abc"在 s = "sssabc"; 的第a[3]格
```
* 如果**沒有含有**"abc" :
```c=
string s = "ssssss";
cout << s.find(abc);
```
```c=
執行結果 : 18446744073709551615
//為亂數,實際上是 string::npos
```
---
## 二、字元 判斷 (char c)
都以`char c;` 舉例
### 1.基礎
* 首先必須要了解<font color="blue">每一個字元在電腦都有自己的代碼</font>

* 輸入`'0'`他的代碼是`48`
* 依此類推`'1'`代碼是`49`,`'2'`代碼是`50`。
會有連續性`A B C`和`a b c`也是一樣
<font color="blue">注意 ! 大小寫要分開計算,代碼是不一樣的</font>
<font color="AC19C9">[例題]</font>
```
輸入一個字串
輸出字串中所有的數字
例如輸入5ab9cd168eqq4qq
則輸出591684
```
既然是數字,那麼它的代碼應該會介於'0'到'9'之間
```c=
string s;
cin >> s;
for(int i=0;i<s.size();i++){
if(s[i]<='9' && s[i]>='0') cout<<s[i];
}
```
<font color="AC19C9">[例題2]</font>
```
呈上題
找到字串中的所有數字後,把他們加起來
例如 : 5+9+1+6+8+4 = 33
```
先想想看現在他們是字元狀態的`'5'`和`'9'`,<font color="AC19C9">他們相加會變成`'59'`,而不是`5 + 9 = 14`</font>。
! 因此要把字元轉換成數字 !
<font color="E68C27">**數字就減`'0'`,大寫英文就減`'A'`,小寫減`'a'`**</font>
像是 :`'1'-'0' = 1` `'5'-'0' = 5`,再相加就可以了。
### 2.判斷一個字元 (用函數)
#### (1).是否是數字 在'0'~'9'內
```c=
char c;
cout << isdight(c);
```
#### (2).是否是字母 (大小寫都算) 在'A'~'Z' 和 'a'~'z'內
```c=
char c;
cout << isalpha(c);
```
* 兩者回傳均<font color="blue"> 1 表示是 、 0 表示否</font>
#### (3).判斷字母是小寫 ? 在'a'~'z'間
```c=
cout << islower('a');
```
#### (4).判斷字母是大寫 ? 在'A'~'Z'間
```c=
cout << isupper('A');
```
* 兩者回傳均<font color="blue"> 1 表示是 、 0 表示否</font>
### <font color="1d206e">**3.轉換字母大小寫**</font>
```c=
char c1 = 'A';
char c2 = 'b';
cout << tolwer(c1) << endl; //大寫轉小寫
cout << toupper(c2) << endl; //小寫轉大寫
```
```c=
輸出 :
a
B
```
> <font color="1d206e">常用在「忽略大小寫比較」的題目中</font>
## 四、陣列 判斷
### <font color="1d206e">1.一般陣列 vs vector</font>
| 比較項目 | 一般陣列 | vector |
| -------------------- | ----------- | ----------------------- |
| 宣告 | int a[5] | vector<int> a |
| 大小是否可變 | X | ✓ 可動態增加 |
| 是否能在執行中改大小 | X | ✓ push_back() |
| 取元素方式 | a[i] | a[i] |
| 是否自動記錄長度 | X | ✓ a.size() |
| 安全取值 | X | ✓ a.at(i) |
| 排序 | sort(a,a+5) | sort(a.begin(),a.end()) |
<font color="1d206e">總而言之 vector 對比一般陣列,較為安全、方便 </font>
### 2.給陣列初始值
#### (1).一維陣列 :
* 一般陣列只能在定義時初始化 (給予數值) :
```c=
int a[3] = {1,2,3};
```
* vector 可以在其他時間給予數值 :
```c=
vector<int> a(3);
a = {1,2,3};
```
#### (2).二維陣列也是一樣 :
```c=
int a[2][3] = {1,2,3,4,5,6};
```
```c=
vector<vector<int>> a(2,vector<int>(3));
a = {{1,2,3}{4,5,6}};
```
### 3. 初始值設0和最大值
#### (1).30 未完待續
#### (2).31 未完待續
### 4.將陣列排序 (由小排到大) `sort`
* 一般陣列跟 vector 用法不一樣
```c=
int a[5];
sort(a,a+5);
```
```c=
vector<int> a;
sort(a.begin(),a.end())
```
### <font color="1d206e">5.陣列的大小</font>
* <font color="red"> 只有 vector 可以用</font>
```c=
vector<int> a;
cout << a.size();
```
### <font color="1d206e">6.翻轉的陣列</font>
```c=
vector<int> a = {1,2,3};
reverse(a.begin(),a.end());
for(int i = 0;i < 3;i ++){
cout << a[i] << " ";
}
```
```c=
輸出 :
3 2 1
```
# 叁、常用函數
### 1.取大值、取小值 (max、min)
比較兩個值留最大或最小的值
```c=
int x = 3,y = 4;
int z = max(x,y);
int z2 = min(x,y);
cout << z < " " < z2;
```
```c=
輸出 :
4 3 //3跟4比保留較大的4,保留較小的3;
```
### 2.數出現次數 (count)
數陣列某一範圍中 x 值的出現次數
```c=
vector<int> a = {1,2,2,2,3};
cout << count(a.begin(),a.end(),2);
```
```c=
輸出 :
3 //共有3個2
```
### 3.找第一個出現位置 (find)
找到 x 值在陣列某一範圍中的位置
```c=
vector<int> a = {4,6,8};
auto it = find(a.begin(),a.end(),6);
cout << "位置 : " << it - a.begin();
//it是位置訊息所以要減初始位置
```
```c=
位置 : 1 //位置在a[1]
```
### 4.交換 (swap)
交換兩個變數的值
```c=
int a = 5,b = 7;
swap(a,b);
cout << a << " " << b;
```
```c=
輸出 :
7 5
```
* 原本做法
```c=
int a = 5,b = 7;
int x = a;
a = b;
b = x;
cout << a << " " << b;
//不可直接 a = b; 等號為把右邊的值往左邊丟。
```
```c=
輸出 :
7 5
```
### <font color="1d206e">5.二分搜尋 (binary_search)</font>
<font color="red">注意 ! 要先用`sort`排序完才能用二分搜尋法</font>
```
未完待續
```
### 6.數學
#### (1).四捨五入
```c=
double x = 3.6;
cout << round(x); //4
```
| 數值 | 結果 |
| ---------- | ---- |
| round(3.4) | 3 |
| round(3.5) | 4 |
| round(-3.5) | -4 |
#### (2).無條件進位 (ceil,天花板)
```c=
cout << ceil(3.1) //4
cout << ceil(-3.1) //-3
```
#### (3).無條件捨去
* 其實變成`int`就好了
```c=
double a = 3.14;
int b = a;
cout << b; //3
```
> 因`int`存放"整數",所以會自動去掉
#### (4).絕對值
```c=
cout << abs(1-3); //2
```
#### (5).平方次方 (pow)
```c=
int a = 5;
cout << pow(a, 2) << endl; // 5² = 25
cout << pow(a, 3) << endl; // 5³ = 125
```
#### (6).開根號 (sqrt)
```c=
int x = 16;
cout << sqrt(x) << endl; // √16 = 4
```
#### (7).數字轉字串 (to_string)
未完待續