# 東山高中程式研究社 複習講義 - C++篇
## 什麼是C++
> 暫時跳過不介紹,之後有時間再來慢慢補
## bit/byte
> bit叫做位元,是電腦的最基本單位,代表的值為0或1,byte叫做位元組,說白了就是8個位元,是電腦處理資料用的最小單位(其實不是最小,但基於效率考量,就算是沒有到1byte的資料還是會佔一個byte),由於一個bit可以有兩種型態(0或1),因此一個byte就能夠表示2^8^個不同的值
## 二進位(binary))
> 因為bit只能是0或1兩種值,所以電腦使用的不是我們平常常看到的十進位,而是用二進位,十進位的概念就是數到十就進位,二進位也是一樣,數到二就進位,因此只會有0跟1
> 十進位再計算的時候可以將第一位看成n * 10^0^,第二位是n * 10^1^以此類推,二進位也是一樣,第一位代表2^0^,第二位代表2^1^...,其實不會算也沒關係,重要的是要知道什麼是二進位以及二進位的基本概念
## include
> C++在做任何事之前,一定要先`include`一個標頭檔(header file),這些標頭檔中會包含一些函數(function),`include`進來,電腦才知道那些函數是什麼。最基本的標頭檔叫做`iostream`就是I/O stream也就是輸入輸出串流類似python的`import`
>
> ```c++=1
> #include <./iostream> //其實不用打./,只是編講義的格式需求
> ```
> 如果說是要打比賽或是考apcs之類的,就不要在那邊記標頭檔,通通都用`bits/stdc++.h`就好了,這個標頭檔裡面就幫你`include`了幾乎所有有可能用到的標頭檔了,要理解他的具體原理之類的有點複雜,如果只是為了打比賽之類的死記就好了
> ```c++=1
> #include <bits/stdc++.h>
> ```
## main()
> C++程式中最重要的就是`main()`,他是主程式,當成是開始執行的時候,就會從`main()`開始,然後在執行其他指令
> ```c++=1
> #include <bits/stdc++.h>
>
> int main(){
> return 0; //這一行是要讓main回傳0,讓程式結束
>}
> ```
## I/O
> 寫程式學的第一個東西當然就是輸出輸入,在C++中,輸出輸入分成兩種,一種是`cin cout`另一種是`scanf printf`,這兩種都可以用,但是`scanf printf`很難用,一般來說都會選擇用`cin cout`
> Cpp的`cin cout`在使用前要先打一行`using namespace std;`這樣電腦才知道`cin cout`是什麼
> Cpp的輸出一般來說是`cout`一次,就輸出一次,但是這樣在打比賽等有執行時間壓力的時候就會慢很多,因此可以將所有輸出的資料先堆起來,等程式結束一次輸出,具體寫法在下面
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0); //這兩行要記得,很重要
> cin.tie(0);
>
> cout << "hello world";
>
> return 0;
>}
> ```
> ### output
> ```
> Hello world
> ```
## 變數(variable)
> C++的變數在使用之前,要先向電腦宣告,具體語法是`type variable_name = value;`,其中`value`可空白
### 1.types
> C++中的各種type有嚴格的分類,中間幾乎是不通用的,以下幾種類型都很重要,也很常用
> 1.`int`全名integer,是整數,在記憶體中佔4byte,上限是2^31^-1,下限是-2^31^
> 1-1.`int`的另外一種形態叫做`long long`,叫做長整數,在記憶體中佔8byte,上下限從原本的2^31^變成2^63^,通常用來儲存大於2^31^-1的數
> 2.`double`是倍精準浮點數,其實浮點數還有一個`float`但是因為不好用,而且誤差偏大,所以無論是在做開發還是打比賽都會選擇用`double`,在記憶體中佔8byte
> 3.`string`是字串,說簡單點就是一串字,由複數個字元組成,沒有硬性的記憶體限制,具有疊加性,也就是兩個字串可以直接加起來,在程式中要用`""`括起來,用`''`的話,會變成字元
> 4.`char`是字元,就是單一一個的字,在記憶體中佔1byte,範圍是0~255,其值可由ascii table對照成字元,在程式中`char`要用`''`去括起來,不能用`""`不然會變成字串
> 5.`bool`是布林值,佔1byte,代表`true`或`false`,另外,除了0以外的所有數值,如果換成布林值都是`true`,只有0是`false`
### 2.變數的處理
> 變數的用處最直接就是存儲資料,但是居然都叫變數了,當然是可以動的,不然就變成常數了,所以要學怎麼給變數做改變
> 變數要改變,就直接就是用`=`,例如`a = 1;`就是將`a`存的資料變成1
> 數字的資料在改變的時候還有其他的方法,就是`a++`和`a--`,意思是`a = a + 1`,至於`a++`跟`++a`的差別在於先處理和後處理,用實際案例更好懂
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> int n = 3;
> cout << n++ << '\n'; //先輸出了n在執行了n = n + 1
> cout << ++n; //先執行n = n + 1後再輸出
>
> return 0;
>}
> ```
> ### output
> ```
> 3
> 5
> ```
## 判斷式
> 數學上經常會用到的`>`, `<`, `=`等,在程式中也經常用到,具體用法就是`a > b`之類的,使用後會有一個布林值的回傳,注意,數學上的`=`在程式中是給變數賦值,`==`才是數學上的`=`
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> cout << (1 <= 2) << '\n';
> cout << (2 == 2) << '\n';
> cout << (1 >= 2) << '\n';
>
> return 0;
> }
> ```
> ### output
> ```
> 1
> 1
> 0
> ```
## 條件判斷(if else)
> 在執行程式時經常需要進行條件的判斷,這時候就可以用`if`, `else`等做判斷
> 1.`if`的用法是`if (bool)`,通常會在`bool`的地方放判斷式
> 2.`else`是當前面的`if`判斷式為`false`時執行的
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> int n = 10;
>
> if (n < 10){
> cout << "n < 10";
> }else{
> cout << "n >= 10";
> }
>
> return 0;
> }
> ```
> ### output
> ```
> n >= 10
> ```
## 迴圈(loop)
> C++的迴圈有三種,分別是`for`, `while`, `do-while`,都是重複執行的一種做法
> 1.`for`迴圈的寫法是`for (第一圈執行的;持續條件;每一圈的執行的)`
> 2.`while`迴圈的寫法是`while (bool)`
> 3.`do-while`迴圈的寫法是`do{...}while(bool)`跟`while`差別在於至少會執行一次
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> for (int i = 0; i < 10; i++){ //這裡寫i++跟++i都可以
> cout << i << ' ';
> }
>
> cout << '\n';
>
> int a = 10;
>
> while (a){ //當a不等於0時就會持續運行
> cout << a-- << ' ';
> }
>
> cout << '\n';
>
> do{ //至少跑一圈
> cout << a << '\n';
> }while (a);
>
> return 0;
>}
> ```
> ### output
> ```
> 0 1 2 3 4 5 6 7 8 9
> 10 9 8 7 6 5 4 3 2 1
> 0
> ```
## 陣列(array)
> 陣列是一連串的同一類型的資料,就像是名單一樣,存儲著一連串的名字,其中的值可以用`[index]`去提取,跟變數一樣要用宣告的`type arr_name[lenth] = {data};`
> 其中`lenth`或是`data`其中一個可空白,如果說不給`lenth`的話,程式會自動從後面`data`的個數去判斷要多長,不打`data`的話,就是一個長度`lenth`的空陣列,但是`type arr_name[lenth];`和`type arr_name[lenth] = {};`是不一樣的,沒有大括弧的話,陣列的內容會是亂碼,有的話就會是0
> 另外,陣列的長度是固定的,想要改變的話要用記憶體配置,非常的麻煩
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> int arr[10] = {}; //宣告名為arr的陣列 長度為10
>
> for (int i = 0; i < 10; i++){
> arr[i] = i; //將arr的第i項設為i
> }
> for (int i = 0; i < 10; i++){
> cout << arr[i] << ' '; //輸出
> }
>
> return 0;
> }
> ```
> ### output
> ```
> 0 1 2 3 4 5 6 7 8 9
> ```
> ### 補充 二維陣列
> 前面講的是一維陣列,就像是數學的數列一樣
> 這裡要講的二維陣列就像是數學的行列式,由行跟列組成,是一種平面上的資料
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> int arr[10][10] = {}; //宣告名為arr的二維陣列 大小是10x10
>
> for (int i = 0; i < 10; i++){
> for (int j = 0; j < 10; j++){
> arr[i][j] = i+j; //將arr的第i行j列的值設成i+j
> }
> }
>
> for (int i = 0; i < 10; i++){
> for (int j = 0; j < 10; j++){
> cout << arr[i][j] << ' '; //輸出
> }
> cout << '\n';
> }
>
>
> return 0;
> }
> ```
> ### output
> ```
> 0 1 2 3 4 5 6 7 8 9
> 1 2 3 4 5 6 7 8 9 10
> 2 3 4 5 6 7 8 9 10 11
> 3 4 5 6 7 8 9 10 11 12
> 4 5 6 7 8 9 10 11 12 13
> 5 6 7 8 9 10 11 12 13 14
> 6 7 8 9 10 11 12 13 14 15
> 7 8 9 10 11 12 13 14 15 16
> 8 9 10 11 12 13 14 15 16 17
> 9 10 11 12 13 14 15 16 17 18
> ```
## vector
> vector這個單字在英文裡原本的意思是向量,但是在C++中`vector`就不是向量了,他是一種類似陣列的東西,不同的是的他可以自己改變長度
> 在新增資料的時候他就會自己變長,處理的時間依資料而定
> 當刪除資料的時候,他也會自己變短,處理的時間是固定的
> ```c++=1
> #inlcude <bits/stdc++.h>
> using namespace std;
>
> int main(){
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> vector< int> v{1,2,3,4}; //宣告就做v的vector
>
> for(int i = 0;i < 4;i++){
> cout << v[i] << '\n';
> }
> return 0;
>}
> ```
> ### output
> ```
> 1
> 2
> 3
> ```
## function
> `function`並不是一個叫做`function`的函數,而是一種用法,前面說過`main`是主程式,實際上應該叫做主函數更貼切,總之就是可以自訂一個函數,去處理事情
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> int func(int n, int m){ //前面的int是設定這個函數return的類型
> return n + m; //在int的函數裡面 return的type就要是int
> }
>
> int main(){
>
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> int ans;
>
> ans = func(1, 2); //讓ans等於func處理(0, 1)的結果
> cout << ans << '\n';
> }
> ```
> ### output
> ```
> 3
> ```
## struct
> `struct`可以建立一種自訂的`type`,然後再用去宣告自己要的結構,用以儲存一坨資料,注意不是像`array`那樣的多筆資料
> ```c++=1
> #incldue <bits/stdc++.h>
> using namespace std;
>
> int main(){
>
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> struct { //設定type
> int num;
> string str;
> } Struct1; //用定好的type去宣告名叫Struct1的結構
>
> Struct1.num = 1; //根據宣告的結構,把裡面的num設定成1
> Struct1.str = "Hello world";
>
> cout << Struct1.num << '\n' << Struct1.str << '\n';
>}
> ```
> ### output
> ```
> 1
> Hello world
> ```
## class
> `class`是一個物件的類型,一個`class`中可以包含多種函數,函數比平時多了一個屬性:`private`和`public` ||其實還有一個protected,但是我真的搞不懂那到底是怎樣,所以我這裡就不寫了|| `public`是可以讓程式再`class`外讀取的函數,`private`不行
> ```c++=1
> #include <bits/stdc++.h>
> using namespace std;
>
> class object{
> public: //public是class外面可以讀取的
> void plus_and_minus(int n, int m){
> cout << plus(n, m) + minus(n, m) << '\n';
> }
> private: //private是只有class才可以呼叫的
> int plus(int n, int m){
> return n + m;
> }
> int minus(int n, int m){
> return n - m;
> }
> }; //注意這裡一定要加分號
>
> int main(){
>
> ios::sync_with_stdio(0);
> cin.tie(0);
>
> object obj; //宣告名為obj的物件 class是前面定義的object
> obj.plus_and_minus(1, 2); //使用class裡面的plus_and_minus函數
> }
> ```
> ### output
> ```
> 2
> ```