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