C++[0]
=
## Intro
### 程式語言是什麼
> 程式語言(英語:programming language)是用來表達電腦程式的電腦語言。它是一套標準化的交流技巧,一種能夠讓程式設計師準確地定義電腦所需資料的語言,以向電腦發出指令並精確地定義不同情況下應當採取的行動。 --[維基百科](https://zh.wikipedia.org/zh-tw/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80)
- 程式語言就是人類用來命令電腦做事情所用的語言
- 機器語言:
- 以二進位直接對電腦下指令
- 組合語言:
- 二進位好難寫->以文字代替二進位來表達指令
- 對應到機器語言
- 無法在不同處理器共通
- 高階語言:
- 讓同一個程式在不同處理器運行
- 易讀性up
- 翻譯成機器語言時可以
- 編譯(Compille):**執行前**透過編譯器一次翻譯所有程式碼,ex. C、C++、Java...
- 直譯(Interpret):**執行時**一邊翻譯一邊執行,ex. Python、JavaScript、PHP...


### C++ 是什麼?
#### C v.s. C++
- C
- 1970 年左右 D. Ritchie 和 K. Thompson 在貝爾實驗室開發出來的程式語言
- 由 B 語言演變而來,屬於編譯語言
- [ABC](https://www.zhihu.com/question/22826568/answer/65915408)
- 具有高階語言的特性,也有接近組合語言的速度
- C++
- 也是在貝爾實驗室開發出來的
- 目的:打造一種具有物件導向的C語言
- C語言寫的程式大部份都可以在C++執行
- 物件導向程式設計(**O**bject-**O**riented **P**rogramming)
> 物件導向程式設計(英語:Object-oriented programming,縮寫:OOP)是種具有物件概念的程式設計典範,同時也是一種程式開發的抽象方針。它可能包含資料、特性、程式碼與方法。物件則指的是類別(class)的實例。它將物件作為程式的基本單元,將程式和資料封裝其中,以提高軟體的重用性、靈活性和擴充性,物件裡的程式可以訪問及經常修改物件相關連的資料。在物件導向程式程式設計裡,電腦程式會被設計成彼此相關的物件。 --[維基百科](https://zh.wikipedia.org/zh-tw/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1)
- 具有「物件(Objects)」概念的程式語言設計模式
- C++ 的用途
- 相對複雜的語言
- 能夠寫出具有底層硬體控制功能的程式
- 加入了物件導向等許多現今語言的特性
- 處理更加貼近使用者的程式
- ex. Windows、iOS、Chrome、Firefox、英雄聯盟
### What is an Algorithm?
" 由有限步驟所構成的集合,可以用於解決某一個特定的問題。 "
- 把西瓜做成一杯西瓜汁?
1. 把西瓜剖半
2. 挖出剛剛剖半的西瓜中的果肉並去籽
3. 將經過 2. 處理的西瓜果肉放入果汁機
4. 按下果汁機的啟動按鈕
5. 將果汁機裡榨好的西瓜汁倒入一個杯子
- 電腦科學中,演算法就是為了解決特定問題而設計的一組明確、有限的運算規則或步驟。
### What are Online Judges?
#### 線上解題系統
- 題目測試:提供各種演算法相關的題目,讓使用者撰寫程式解答
- 自動評測:使用測試數據來檢查程式的正確性與效能,並給予回饋
- 即時反饋:提交程式後,OJ 會迅速回報結果,如「通過」、「錯誤」、「超時」等
#### Online Judges
- ZeroJudge:台灣的 OJ,電腦老師很喜歡
- TIOJ:建中資訊社維護
- ISCOJ:建北電資 OJ
- CSES:有很多演算法題目可以練習
- Codeforces:全球最大的 OJ,常常有比賽
- Atcoder:第二大 OJ,在日本
- NEOJ:台大資芽的 OJ
- LeetCode:收集軟體工程師面試考古題的 OJ
#### OJ Results
| Result | Meaning |
| --- | --- |
| AC (Accepted) | 答案正確,通過所有測資 |
| WA (Wrong Answer) | 輸出結果與標準答案不符 |
| TLE (Time Limit Exceeded) | 程式執行時間超過限制 |
| MLE (Memory Limit Exceeded) | 程式使用的記憶體超過限制。 |
| RE (Runtime Error) | 程式執行時發生錯誤 |
| CE (Compilation Error) | 程式語法錯誤,無法編譯 |
## Setup
| EDITOR 文字編輯器 | IDE 整合式開發環境 |
| --- | --- |
| 高度自定義 | 功能完整 |
| 啟動速度快 | 吃效能,速度慢 |
| 需自行安裝編譯器 | 內附編譯器 |
| ==VSCode== | ==Code::Blocks== |
### 編譯器
- 編譯器(Compiler)會將某種程式語言寫成的原始碼轉換成電腦能解讀的語言
- IDE 不需安裝編譯器
- 文字編輯器安裝的方法:[VSCode 的 C++ 安裝教學](https://hackmd.io/@liaojason2/vscodecppwindows)
### 程式開發軟體們
- [Dev-C++](https://alwaysfreesir.blogspot.com/2017/05/devcpp-install.html):免費且非常好使用,不過它是一個比較古老的IDE,連編譯器也是好幾年前的(不過前陣子好像有別的公司接手)
- [Code::Blocks](https://ithelp.ithome.com.tw/articles/10273955):真的很醜,但學校們很喜歡
- [onlinegdb](https://www.onlinegdb.com/):除了他是線上這點很方便外完全沒道理用
- [等等](https://www.hostinger.com/tutorials/best-code-editors)
## Hello World!
```cpp
#include <iostream>
using namespace std;
int main() {
cout << "Hello World!\n";
return 0;
}
```
### 第 1 行:導入 \<iostream\> 這個標準函式庫
> #include \<iostream\>
- \#include 可將函式庫導入程式
- \<iostream\> 是函式庫名稱:專門處理程式的輸入輸出
### 第 2 行:使用標準函式庫
> using namespace std;
- std:C++ 標準函式庫的代號 (**st**an**d**ard library)
- 告訴電腦,我們想在程式中使用 C++ 標準函式庫
- 不加的話就要在用到的時候在前面加`std::` ex. `std::cout`、`std::endl`
### 第 3 行:空行
- 會被電腦自動跳過
- 目的是為了讓程式碼可讀性更高
- 不用不會怎麼樣只是可能會被覺得很醜
### 第 4 & 7 行:主函式
- main 函式是 C++ 定義一個程式的起點
- 大括號 {} 內就是 main 函式的內容
- 電腦執行的程式就要寫在這個大括號內
### 第 5 行:Hello World!
- `cout`:輸出
- `<<`:把右邊的資料傳給 cout
- ``\n``:跳脫字元,換行
- `<< endl`:也可以換行
- ==一行程式結束後記得要加 `;`==
### 第 6 行:回傳
- 告訴電腦這個函式成功執行了
- 可有可無,因為編譯器會自動在結尾補上 `return 0;`
- `return 0`:正常退出
- `return 1`:異常退出
### 函式庫
- 函式庫中會有預先定義好的函式、類別和工具,可直接使用
- `iostream`:輸入輸出
- `algorithm`:常用演算法
- `cmath`:數學函式庫
- 萬用標頭檔:`bits/stdc++.h`
- 包含絕大部分會用到的函式庫
- 引入一大包東西雖然你可能只有用到一點點
- macOS 要用有點蠻煩 顯然我怕麻煩
- 等等我還是會講他們分別屬於什麼函式庫
### 命名空間
- 命名空間(namespace)是 C++ 提供的一種機制,用來避免名稱衝突
```cpp
#include <iostream>
#include <string>
using namespace std;
string name = "C++";
string name = "Python";
int main() {
cout << name;
}
```
- 兩個 name 沒有區分開來,導致編譯錯誤
``` cpp
#include <iostream>
#include <string>
using namespace std;
namespace A {
string name = "C++";
}
namespace B {
string name = "Python";
}
int main() {
cout << A::name << '\n'; //C++
cout << B::name; //Python
}
```
- 使用命名空間即可避免錯誤
- 但其實在寫程式時應該避免重複命名
#### namespace std
- C++ 標準函式庫的所有函式、類別(如 cout, cin, vector, string 等)都定義在 std 命名空間內
```cpp
#include <iostream>
int main() {
std::cout << "Hello World!" << std::endl;
}
```
- 未使用 using namespace std;需要在 cout, endl 前加上 std::
- ==using namespace std; 會導致 std 內的所有函式和類別變成全域可用,可能會與其他函式名稱衝突,因此在大型專案中建議避免使用==
### 換行
| `\n` 跳脫字元 | `endl` 輸出流 |
| --- | --- |
| 換行 | 換行並刷新緩衝區 |
| 速度快 | 速度慢 |
| 競程用 | 專案用 |
| 推薦 | 不推薦 |
## Variables and Data Types
### 變數
- 數值會改動的數
- 程式用來存放資料的空間
- 占有電腦的記憶體
- 執行的過程中可以對變數進行處理和運算
#### 宣告
- 宣告格式:`資料型態 變數名稱;`
```cpp
#include <iostream>
using namespace std;
int main() {
int a;
}
```
- 宣告一個命名為 a 的整數(int)變數,其資料型態為 int
#### 資料型態
| 名稱 | 型態(type)| 範圍(range)| 記憶體大小 |
| --- | --- | --- | --- |
| `int` | 整數 | -2^31^ ~ 2^31^-1 | 4 bytes |
| `unsigned int` | 正整數 | 0 ~ 2^32^-1 | 4 bytes |
| `long long` | 整數 | -2^63^ ~ 2^63^-1 | 8 bytes |
| `unsigned long long` | 正整數 | 0 ~ 2^64^-1 | 8 bytes |
| `bool` | 布林值 | 真假值(True/False)| 1 byte |
| `char` | 字元 | 一個字元 | 1 byte |
| `string` | 字串 | 多個字元 | 可變 |
| `float` | 浮點數 | 十進位精度約 6~7 位 | 4 bytes |
| `double` | 浮點數 | 十進位精度約 15~16 位 | 8 bytes |
#### 賦值
- 賦予變數一個值
- 賦值格式:`資料型態 變數名稱 = 值;`
```cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
//宣告一個整數變數 a
//將 a 的值設為 1
int a = 1;
//宣告一個字元變數 c
//將 c 的值設為 'a'(單引號)
char c = 'a';
//宣告一個字串變數 s
//將 s 的值設為 "str"(雙引號)
string s = "str";
}
```
#### 變數命名
- 需與變數內容相關
- 只能用大小寫字母、數字、_、$
- 數字**不可**作為變數名開頭
- 大小寫意義不同(為不同變數)
- 不可使用==保留字==
#### 保留字
- 給編譯器做特殊判斷用

## Input & Output
- C++的輸入和輸出是使用`cin`和`cout`來進行
- 使用它們的時候需要引入`<iostream>`函式庫
### 輸入
- `cin >> 變數(已宣告過的);`
- 讀到空白或換行會結束讀取
- 輸入多個值:`cin >> 變數 >> 變數;`
### 輸出
- `cout << 要輸出的物件;`
- 可輸出變數或是輸出一個值
- 輸出多個值:`cout << 變數 << 變數;`
```cpp
#include <iostream>
using namespace std;
int main() {
string s;
cin >> s; // Hello World
cout << s; // Hello
string a, b;
cin >> a >> b; // Hello World
cout << a << '\n'; // Hello
cout << b << '\n'; // World
}
```
### getline
- 讀取整行
- `getline(cin, 變數)`
```cpp
#include <iostream>
using namespace std;
int main() {
string s;
getline(cin, s);
cout << s;
}
```
## Operators
- 運算子
- 對變數或數值做運算
### 指定運算子`=`
- 先對`=`右邊進行運算
- 將運算結果存入左邊
- 左邊要可以存值 ex. 變數
```cpp
#include <iostream>
using namespace std;
int main() {
int x;
x = 2 + 1;
cout << x << '\n'; // 3
x = x + 1;
cout << x << '\n'; // 4,先計算右邊再存入左邊
}
```
### 算術運算子
- 數學的運算符號
- 先乘除後加減
- 括號優先
```cpp
#include <iostream>
using namespace std;
int main() {
int a = 5, b = 3, c = 2; // 逗號左右可以分別賦值
cout << a + b << '\n'; // 8,加
cout << a - b << '\n'; // 2,減
cout << a * b << '\n'; // 15,乘
cout << a / b << '\n'; // 1,除
cout << a % b << '\n'; // 2,模除(取餘數)
cout << c + a * b << '\n'; // 17,先乘除後加減
cout << (c + a) * b << '\n'; // 21,括號內優先
}
```
- line 9:a 和 b 都是整數,對兩個整數做除法`/`時自動向下取整
```cpp
#include <iostream>
using namespace std;
int main() {
int a = 1;
a += 1; // a = a + 1
cout << a << '\n'; // 2
a -= 2; // a = a - 2
cout << a << '\n'; // 0
}
```
### 遞增遞減
- 前置遞增遞減`++x`/`--x`:加減之後的值
- 後置遞增遞減`x++`/`x--`:加減之前的值
```cpp
#include <iostream>
using namespace std;
int main() {
int a = 0;
cout << ++a << '\n'; // 1,先加再用
cout << a++ << '\n'; // 1,先用
cout << a << '\n'; // 2,再加
cout << --a << '\n'; // 1,先減再用
cout << a-- << '\n'; // 1,先用
cout << a << '\n'; // 0,再減
}
```
### 比較運算子
- 回傳 true(1) 或 false(0) 兩種結果
```cpp
#include <iostream>
using namespace std;
int main() {
int a = 4, b = 7, c = 4;
cout << (a == b) << '\n'; // 0
cout << (a == c) << '\n'; // 1
cout << (a != b) << '\n'; // 1
cout << (a > b) << '\n'; // 0
cout << (a > c) << '\n'; // 0
cout << (a >= b) << '\n'; // 0
cout << (a >= c) << '\n'; // 1
cout << (a < b) << '\n'; // 1
cout << (a <= b) << '\n'; // 1
}
```
### 邏輯運算子
- 邏輯運算也只有 true(1) 或 false(0) 兩種結果
- 邏輯 AND `&&`
- `A`、`B`皆為true時, `A && B` 為`true`
- 否則 `A && B` 為 `false`
| A && B | B = true | B = false |
| ------------ | -------- | --------- |
| **A = true** | true | false |
| **A = false**| false | false |
- 邏輯 OR `||`
- `A`、`B`皆為`false`時, `A || B` 為`false`
- 否則 `A || B` 為 `true`
| A \|\| B | B = true | B = false|
| ------------ | -------- | -------- |
| **A = true** | true | true |
| **A = false**| true | false |
- 邏輯 NOT `!`
- 當 `A` 為 `true` 時,`!A` 為 `false`
- 否則 `A` 為 `false` 時,`!A` 為 `true`
### 型別轉換
- 把某個型別轉換成另一個型別
- 隱含型別轉換
- C++ 會自動做的轉換
- 選擇運算式中所有型別中儲存空間較大的型別
```cpp
#include <iostream>
using namespace std;
int main() {
cout << 3 / 2 << endl; // 1
cout << 3 / 2.0 << endl; // 1.5
}
```
- 使用指定運算子`=`就會以指定運算子左邊的資料型別為準
```cpp
#include <iostream>
using namespace std;
int main() {
int x;
x = 3 / 2.0;
cout << x << endl; // 1
}
```
- 強制型別轉換
- 程式運算過程中對型別做強制的轉換
- 轉換格式:
```
(轉換型別) 變數;
(轉換型別) 數值;
```
```cpp
#include <iostream>
using namespace std;
int main() {
int x = 3;
cout << (double)x / 2 << endl; //輸出 1.5
cout << (char)97 << endl; //輸出「a」, 97是字元'a'在ASCII碼中的編號
}
```
## Array & Vector
### 陣列
- 多個相同資料型別的變數所組成
- 每個元素都是一個變數
- ==陣列索引值(index)是從 0 開始(0-based)==
| index | 0 | 1 | 2 | 3 | 4 | 5 |
| --- | --- | --- | --- | --- | --- | --- |
| value | 123 | 53 | 42 | 4 | 1920 | 4 |
- 陣列宣告格式:
- `資料型態 陣列名稱[陣列大小];`
- `資料型態 陣列名稱[] = {初始值1, 初始值2...};`
- 用中括號`[]`加上索引值`陣列名稱[索引值]`表示陣列的某個變數
```cpp
#include <iostream>
using namespace std;
int main() {
int a[5]; // 可儲存 5 個整數變數
int b[] = {1, 3, 4}; // 陣列中有 1, 3, 4 三個整數,長度為 3
cout << b[0] << ' ' << b[2] << '\n'; // 1 4
cout << b[3] << '\n'; // 噴錯,陣列 b 長度只有 3
a[] = {1, 2, 3, 4, 5};
cout << a[0] << '\n'; // 1
a[0] = 9;
cout << a[0] << '\n'; // 9
char c[10], d[2]; // 也可儲存其他資料型態
}
```
### 二維陣列
- n x m 的陣列
- 陣列宣告格式:
- `資料型態 陣列名稱[n][m];`
- `資料型態 陣列名稱[][] = {{初始值1-1, 初始值1-2...},{初始值2-1, 初始值2-2...},...};`
- a[n][m]:
| index | 0 | 1 | 2 | ... | m-1 |
| --- | --- | --- | --- | --- | --- |
| 0 | a[0][0] | a[0][1] | a[0][2] | ... | a[0][m-1] |
| 1 | a[1][0] | a[1][1] | a[1][2] | ... | a[1][m-1] |
| 2 | a[2][0] | a[2][1] | a[2][2] | ... | a[2][m-1] |
| ... | ... | ... | ... | ... | ... |
| n-1 | a[n-1][0] | a[n-1][1] | a[n-1][2] | ... | a[n-1][m-1] |
### Vectors
- #include <vector>
- 動態陣列
- 跟陣列很像,但長度可改變
- 動態陣列宣告:`vector<資料型態> 動態陣列名稱`
`vector<資料型態> 動態陣列名稱(陣列長度)`
`vector<資料型態> 動態陣列名稱(陣列長度, 所有元素預設值)`
- 二維動態陣列宣告:`vector<vector<資料型態>> 動態陣列名稱`
`vector<vector<資料型態>> 動態陣列名稱(陣列高度m)`
`vector<vector<資料型態>> 動態陣列名稱(陣列高度m, vector<資料型態>(陣列長度n))`
`vector<vector<資料型態>> 動態陣列名稱(陣列高度m, vector<資料型態>(陣列長度n, 所有元素預設值))`
```cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> v, t, k;
v.push_back(1);
v.push_back(3);
cout << v[0] << ' ' << v[1] << '\n'; // 1 3
cin >> v[0]; // 2
cin >> v[1]; // 4
cout << v[0] << ' ' << v[1] << '\n'; // 2 4
vector<int> a(5, 0);
cout << a[0] << ' ' << a[3] << '\n'; // 0 0
a.pop_back();
cout << a.size() << '\n'; // 4
a.clear(); // 移除所有元素
a.empty(); // 1,回傳是否為空
t.resize(5);
cin >> t[4] >> t[3]; // 1 3
cout << t[3] << ' ' << t[4] << '\n'; // 3 1
k.assign(5, 0);
cout << k[0] << ' ' << k[2] << '\n'; // 0 0
}
```
## Conditionals
## Loops
## Practices
## References
- https://hackmd.io/@Scott-Chou/rkbl5dzCO
- https://zh.wikipedia.org/zh-tw/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80
- https://vocus.cc/article/66232973fd89780001355768
- https://hackmd.io/@Co-E5uCjTiSXhCaEXduquA/ryepv8F7U9
- https://zh.wikipedia.org/zh-tw/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1
- https://medium.com/@p81122g/%E6%B7%BA%E8%AB%87%E7%89%A9%E4%BB%B6%E5%B0%8E%E5%90%91%E7%A8%8B%E5%BC%8F%E8%A8%AD%E8%A8%88-object-oriented-programming-81355c85484b
- https://jason-chen-1992.weebly.com/home/-whats-algorithm
- https://ithelp.ithome.com.tw/m/articles/10233392
- https://www.reddit.com/r/learnprogramming/comments/sga9ey/is_there_really_such_a_big_difference_between/?tl=zh-hant
- https://alwaysfreesir.blogspot.com/2017/05/devcpp-install.html
- https://ithelp.ithome.com.tw/articles/10273955
- https://hackmd.io/@liaojason2/vscodecppwindows
- https://blog.csdn.net/m0_37187717/article/details/104631305
- https://hackmd.io/@LukeTseng/H1P1nSt7yl
- https://medium.com/@leonardian14/c-vector-%E7%B0%A1%E5%96%AE%E8%AA%AA%E6%98%8E%E8%88%87%E7%94%A8%E6%B3%95-946c975bd526