C++ 語法
yungyao
IDE
什麼是IDE
- Integrated Development Environment
其實不太重要
反正就是你用來寫code的程式
常見的 IDE
- Codeblocks
- Dev C++
- Visual Studio Code
- Sublime
- Vim
今天要教的
其實我平常使用的是 VS Code 或 Vim
不過對新手來說 Codeblocks 是最簡單好用的
安裝
選擇 Binary Release 然後按照指示安裝就好
Basics
Default Code
#include <iostream>
using namespace std;
int main(){
//Write your code here.
return 0;
}
輸入/輸出
- 輸入 cin
- 輸出 cout
cin >> a >> b;
cout << a << b;
變數
型別 | 範圍 | 大概範圍 |
int | -2147483648 ~ 2147483647 | -2e9 ~ 2e9 |
long long | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 | -9e18 ~ 9e18 |
float | 3.4e±38 | 精度過低 |
double | 1.7e±308 | 都用這個 |
char | 0 ~ 255 | 常用字元 |
bool | 0 ~ 1 | 0/1 |
If Else
選擇結構
if (/*條件成立*/){
//do ...
}
else if (/*否則這個條件成立*/){
//do ...
}
else{ //上面的條件都不成立
//do ...
}
- 一定會有一個if
- else if 可以有任一個
- else 最多一個
迴圈
- for/while
while (/*為真的話就跑*/){
//do something
}
for (/*第一次進迴圈時執行*/;/*跟while迴圈一樣*/;/*迴圈每執行完一次就執行一次這邊*/){
//do something
}
迴圈
for (int i=0;i<10;++i){
cout << i << ' ';
}
運算子
- 基本的 +-*/
- 模運算 %
- 位元運算 &|^~
- 加一個=直接指派 ex: += *=
- ++ --
- 布林反轉運算 !
陣列
- 一次宣告一排變數
- 可以二維的
int a[10];
for (int i=0;i<10;++i){
cin >> a[i];
}
int b[10][10];
for (int i=0;i<10;++i){
for (int j=0;j<10;++j){
cin >> b[i][j];
}
}
string
- 其實就是char陣列
- 確切來說是vector<char>(詳見STL)
- 可以直接輸入/輸出
小練習
從第一個數開始,如果下一個數比目前的小,就swap
並對下一個數執行一樣的事
那最大的數一定會在最後
這樣執行 \(n\) 次,陣列就會被排序好
函式
Function 的重要性
- 函式是C語言的基本
- C++ 為物件導向,但函式還是很重要
- 全部寫在 main 裡面可讀性很差
函式的架構
int add(int a, int b){//回傳型別和傳入值
//執行內容
int c = a + b;
return c;
}
型別可以是 void,表示沒有回傳值
傳參考
void swap(int &a, int &b){ //用 & 表示該變數是傳參考
int temp = a;
a = b;
b = temp;
}
遞迴
- 在函式中呼叫相同的函式
- 記得設終止條件
遞迴
void printNum(int n){
cout << n << ' ';
if (n > 1) printNum(n-1);
}
overload(重載)
將一個函式重複定義
只要傳入的型態不同,就能自動判斷使用哪個型態
int add(int a, int b){
return a + b;
}
int add(int a, int b, int c){
return a + b + c;
}
STL
引入標頭檔
- algorithm
- vector
- queue
- stack
- deque
- utility
之後才會遇到的
- set
- unordered_set
- map
- unordered_map
- bitset
還有黑魔法 pbds
algorithm
- sort
- min/max
- fill
sort
可以把一段陣列排序好
不加 compare function 預設會是由小到大排
sort (*begin, *end, compare_function/*optional*/);
sort (a, a+n);
可以把 \(a[0], a[1], ..., a[n-1]\) 排序好
sort\compare function
cmp function在順序正確時回答true
bool cmp(int a, int b){
return a > b;
}
int main(){
int arr[100];
sort(arr, arr+100, cmp);
}
lambda \(\lambda\)
也可以這樣表示
int arr[100];
sort(arr, arr+100, [](int a, int b){return a > b;});
min/max
- 簡單好用
int a = max(1, 2);
int b = min(1, 2);
fill
- 區間的表示法跟sort一樣
- 簡單好用
int arr[100];
fill(arr, arr+100, -1)
vector
- 可動態調整大小的陣列(類似 py 的 list)的 list
- 複雜度理論上和陣列相同,但常數較大
- 優點就是不需要預先決定好使用空間
vector
- .push_back(data)
- .pop_back()
- .resize(size)
- .size()
- .empty()
- .clear()
queue
- queue
- priority_queue
queue
- 就是一個隊列
- 資料會在裡面排隊,先進去的先出來
queue
- .push(data)
- .pop()
- .front()
- .size()
- .empty()
.clear()
priority_queue
- 動態維護一群資料
- 可以丟一個新資料進去
- 可以取出裡面最大/小的資料
priority_queue
- 常用的就這些
- 還有size() empty() 這些基本款函式
priority_queue <int> pq;
priority_queue <int, vector<int>, greater<int>> min_pq;
pq.push(1);
pq.push(2);
cout << pq.top() << '\n'; //2
pq.pop();
cout << pq.top() << '\n'; //1
stack
- 就是一個堆疊
- 最近被放進去的東西,最先被拿出來
stack
- .push(data)
- .pop()
- .top()
- .size()
- .empty()
.clear()
deque
- double-ended queue
deque
- .push_back(data)
- .push_front(data)
- .pop_front()
- .pop_back()
- .front()
- .back()
- .size()
- .empty()
utility
- 唯一有用的內容只有pair
- 兩個東西的struct(等等會介紹)
pair
- pair <Type1, Type2>
- .first/.second
- make_pair(Type1, Type2)
pair <int, int> p = make_pair(1, 2);
cout << p.first << ' ' << p.second << '\n'; //1 2
p.second = 3;
cout << p.first << ' ' << p.second << '\n'; //1 3
set
- 能動態排序資料(加入/刪除資料)
- 可以二分搜
- O(1) 存取頭尾
- 底層實作是紅黑樹(aka 交給C++幫你優化就好)
set
- 用了些酷酷的指標魔法
- 總之很好用
- 要注意不能戳到空指標
set <int> st;
st.insert(1);
st.insert(2);
st.erase(2);
if (st.find(x) != st.end()) cout << "x is in set.\n";
cout << *st.lower_bound(x) << '\n'; //binary search for x
map
- 類似py的dictionary
- set有的功能都有
- 有索引值(排序基準)跟儲存值
map
- 可以直接用中括號來操作
- 使用find或lower_bound時會找到一個pair
map <int, int> mp;
mp[1] = 2;
mp[2] = 3;
mp[1] += mp[2];
cout << mp[1] << ' ' << mp[2] << ' ' << mp[3] << '\n';//5 2 0
cout << mp.lower_bound(0)->first; //1
struct
struct
自定義的型態
struct data{
int a, b;
string name;
int index;
}a, b;
data arr[100];
a.a = 1;
a.name = "1234567890";
constuctor(建構子)
Text
struct data{
int a, b, c;
data(int x, int y){
a = x;
b = y;
c = x + y;
}
data(int a, int b, int c): a(a), b(b), c(c){}
};
function
- OOP的精隨
struct point{
int x, y;
int dis(point a){
return (x - a.x) * (x - a.x) + (y - a.y) * (y - a.y);
}
};
指標
存值/址
- 指標是一種特別的變數
- 儲存的是記憶體的位置
- 每個型態都有對應的指標變數
宣告
- 就是那麼簡單
int *a, *b;
long long *c;
使用
- 對一個指標x,*x 會得到該位址的值
- 對一個普通變數y, &y 會得到變數位址
使用
對於一個擁有子型態的指標x
可以用 x->y 取代 (*x).y
使用
int x;
int *p;
struct data{
int a, b;
}d, *pd;
p = &x;
*p = 1;
pd = &d;
pd->a = (*pd).b;
空指標
- 空指標是 nullptr
- 對 nullptr 存取值會Runtime Error
陣列
- 對於一個陣列a[],a其實是一個指標
- 陣列在記憶體中是一段連續空間
- a[x] 等價於 *(a+x)
STL
- set/map 的 find/lower/upper_bound() 找到的是指標
- .begin()/.end() 也是指標
- vector 可以跟陣列一樣用
- next(), prev()
- .end() 會指向空的位置
Linked List
- \(O(n)\) 存取特定項
- \(O(1)\) 加元素
struct LLNode{
LLNode *pre, *nex;
int val;
};
動態開點
- new
- 令指標變數為 new 型態
- 指標指向新叫出來的空間
- delete
- delete 指標
- 把該空間刪除,並使指標指向nullptr
重載運算子
自定義運算
pair <int, int> operator+(pair <int, int> a, pair <int, int> b){
return make_pair(a.first + b.first, a.second + b.second);
}
跟自定義函式的差別
- 基本上沒差
- 本質上是一樣的
- 注意operator吃的參數
C++基本語法
By yungyao
C++基本語法
- 209