---
# System prepended metadata

title: C++基本語法

---

# C++基本語法
:::info
:bulb: 這邊網羅了所有C++旁門左道、奇技淫巧、怪力亂神等基本語法，新手也能學的來。

:bulb: 另外這筆記是高速Rush基本語法，不會探討語言本身。
:::

關鍵字，供Ctrl+F使用

:small_blue_diamond:**型態轉換**  :small_blue_diamond:**位運算**
:small_blue_diamond:**vector**  :small_blue_diamond:**Loop** 
:small_blue_diamond:**function**  :small_blue_diamond:**函式庫** 
:small_blue_diamond:**二分搜索**  

## 前言
不積跬步，無以至千里；不積小川，無以成江海。任何知識都是一點一點累積的，切記不可有什麼學習要立竿見影的想法，日拱一卒，功不唐捐，每天寫一點程式，每周寫八題算法，久而久之寫程式就能當玩具了，無他，為手熟爾。

古來聖賢，皆寂寞；唯有飲者，留其名。天生我材必有用，千金散盡還復來。五花馬，千金裘，呼兒將出換美酒，與爾同銷萬古愁。寫程式要大方，大開大闔，切不可為一道難題難住而放棄。

大丈夫在世當代三尺劍立不世之功，大家寫程式應該要往遠了走，堅持努力，相信在未來，程式設計能當你三呎之劍，立天下不世之功。

大丈夫處事，當光明磊落，即使處逆境，也當屈伸守，分以待天時。無論學習何種東西一定都會有瓶頸，希望各位能穩扎穩打，爭取將自己的程式能力帶到更高境界。

大丈夫立於天地間，豈能郁郁久居人下?身為資源豐厚的時代，可以學時學習人家的知識，但切不可依賴，唯有將知識融會貫通，有自己的想法，才是根本。


## Hello World
萬丈高樓平地起，高階程式語言始於Hello World。
```
#include<iostream>
using namespace std;
int main(){
    cout << "Hello World" << endl;
    return 0;
}
```


## 基本I/O
輸入可以用cin 和 scanf
輸出可以用cout 和 printf
```
#include<iostream>
using namespace std;
int main(){
    //同時輸入數字與字串
    int N,
    string str;
    cin >> N;
    //⬇輸入這句就可以解除綁定，很重要，否則有bug
    cin.ignore();
    getline(cin,str);
}
```
```
#include<iostream>
using namepsace std;
int main(){
    int N;
    //輸入
    N = cin.get();
    scanf("%d",&N);
    //輸出
    cout << N;
    //條件輸出
    printf("%d%c",N,N==9?'\n':' ');
}
```
## 基本邏輯
三元運算符
```
bool cmp(const int a,const int b){
    return a == b ? true : false
}
其實就是
bool cmp(const int a,const int b){
    if(a == b) return true;
    return false;
}

且 : &&
或 : ||
不等 : !=
全等 : ==
以上都是判斷邏輯的，可以搭配位運算一起看。
```


## 資料型態
C++的資料型態大同小異
### 數字定義
```
int x;
float x;
double x;
long long x;
long long int x;
```
### 字串定義
```
//string x 型態其實就是 char *x || char x[];
string x;
char x[10];
```
### 類型轉換
```
//字串轉數字
//char []轉換
char str[20];
strcpy(str, "98993489");
val = atoi(str);

//字符轉數字
char a = '9';
int x = a-'0';

//數字轉字符
int a = 9;
char x = a+'0';

//string轉換
string str = "98993489";
atoi(str.c_str());

//數字轉字串
int a = 12345;
string a = to_string(a);
```
### 自訂函數
```
#include<iostream>
#define elif else if 這邊將else if定義成elif。
#define f(i,j,k) for(int i = 0 ; i < j ; k++) 將迴圈定義成f(i,j,k)看各位需求。
using namespace

int main(){
    條件式就可以寫成
    if(){...}
    elif{...}
    迴圈可寫成
    int i,j,k;
    f(i,j,k);
}
```
## 位運算

直接調用二進位來做運算
For Example:
```
int x = 20;
x = x >> 1; x shift right 一位，相當 x /= 2;
x = x << 1; x shift left 一位，相當 x *= 2;

&:AND
if(x & 1) 就是判斷x是否為奇數，相當於x % 2 == 1

|:OR
x |= 1;

^: XOR
x ^= 1;

!: NOT
if(x > 0) 可以寫成 if(x)
if(x <= 0) 可以寫成 if(!x)
//While(bool)
while(x) 同理
```

## 容器
### 固態容器Arr，無法擴容陣列，地址指向隨機，定義如下
```
一維陣列
int arr1[20];
二維陣列
int arr2[20][20];
初始化一維陣列
int arr[20] = {0};
獲取陣列長度(二維):
int len1 = sizeof(arr1);
int len2 = sizeof(arr1[0]);
初始化數組
memset(arr,0,sizeof(arr));
```
cout << arr1[0] << endl;

cout << 0[arr1] << endl;

兩者是一樣的。


### 動態容器Vector，可以擴容陣列，而且可朔性很高，定義如下。
標頭檔要引用 #include<vector>
```
一維陣列
vector<int> vec;

二維陣列
vector<vector<int>> vec;

定義長度的陣列
int N = 10;
vector<int> vec(N) 或者 vector<int> vec(10); 或者 vector<int> vec[10]; 

二維定義
vector<int> vec(N,vector<int>(N));

獲取陣列長度(二維):
int len1 = vec.size();
int len2 = vec[0].size();

初始化為0的方法
vector<int> vec(N,0);
vector<int> vec(N,vector<int>(N,0));

增加數字到最後面
vec.push_back(1);
移除最後面數字
vec.pop_back();

```
vector<int> vec[10] 這句不了解就是不要用，其他用法都很簡單。
    
Vector可以塞的東西很多，比如鏈結串列，樹形，類別等，像是
    
    class x{
        public:
        int a;
        int b;
    };

    vector<TreeNode*> 

    vector<Node*> 

    vector<x*>

    vector<pair(int,int)> 

    vector<tuple(int,int,int)> 
    
各取所需
    
### 如何調用?
一般調用方式
```
迭代器
vector<int> vec
for(vector<int>::iterator iter : vec){
    cout << iter << endl;
}
可以寫成
for(auto iter : vec){
    cout << iter << endl;
}
變數使用
for(int i = 0 ; i < vec.size() ; i++){
    cout << vec[i] << endl;                 
} 
vector型態為Class:
Class klas{
    public:
        int first;
        int second;
};

vector<klas*> vec;
cout << vec[0]->first << endl;
cout << vec[0]->second << endl;
```

### Stack
一樣能塞東西

    Stack<int> stk;

    Stack<char> stk;

    Stack<string> stk;
    
方法
    
    bool flag = stk.empty() 棧是否為空
    int a = stk.top() 得到棧頂
    stk.pop() 移除棧頂
    stk.push() 增加數字

### Queue
據我所知，能塞樹和鏈結串列
    
    queue<int> q;
    queue<TreeNode*> q;
    queue<tuple<int,int,int> q;

方法
    
    auto a = q.front() 取得最前面的
    auto a = get<1>(q) 指定取得，看你塞了甚麼
    q.pop 移除最前面的數
    q.push() 增加數字到後面

### 映射表(HashMap)
C++的映射表可以調用三種，unordered_map, map
底層實現不一樣，unordered_map是紅黑樹，速度較快；map則是哈希表，但是map和set一樣，會自動排序。
```
#include<map>
#include<unordered_map>
    
//map(key值,Value值) 透過key值查詢Value值
map<int,int> hash;
unordered_map<int,int> hash;
```
調用方式
```
for(auto iter : hash){
    cout << iter.first << endl; //取Key值
    cout << iter.second << endl; //取Value值
}
```
### 集合(set)
就是集合，有unordered_set,set
    
```
#include<unordered_set>
#incldue<set>

set<int> set1;
unordered_set<int> set2;
```
## 迴圈(Loop)
### for迴圈的定義
```
for(變數;條件;行為;)
可以有以下寫法
1. for(int i = 0 ; i < 5 ; i++)

2. int j = 0;
   for(; j < 5 ; j++)

3. bool flag;
   for(; flag ;)

4. for(; ; j++)
    
5. for(;;)

以上定義都是方便雕朔迴圈
```
### while迴圈的定義
```
while(bool flag);
//while(裡面的東西為真，就繼續執行迴圈)
int x;
while(x)
```
### 實戰: 判斷回文
```
string str;
for(int i = 0, j = str.length()-1 ; i < j ; i++, j--){
    if(str[i] != str[j]) return false;           
}
return true;
```
### 實戰: 數字的每一位相加
```
int x = 123456789;
int ans = 0;
while(x){
    ans += x % 10;
    x /= 10;
}
```
## 副函數(function)

```
回傳int
int solve(int x,int y){return x;}

不回傳
void solve(int x,int y){x = x+y;}

void dfs(int x,int y){return;}

回傳vector
vector solve(int x,int y){
    vector<int> vec;
    return vec;
}

回傳bool
bool solve(int x,int y){
    return x > y;    
}

改變陣列要加&
void dfs(vector<int> &vec,int x,int y)
```

## 函式庫

### using namespace std
寫這個
其實就是std::cin 簡寫成cin， std::cout 簡寫成 cout
    
### fstream
    
有很多用法，想要知道更多得去查。

```
    #include<iostream>
    #include<fstream>
    using namespace std;
    int main(){
        fstream ofs;
        //打開筆記本
        ofs.open("C://User//user//Desktop//output.txt");
        //輸出到筆記本上
        ofs << "Hello World" << endl;
        //關上筆記本
        ofs.close();
    }
```

### cstring

```
int arr[10][10];

memset(arr,0,sizeof(arr)); 初始化陣列為0

相當於arr[10][10] = {0};
    
判斷是否為字母 isalpha(char) //不須引用
字符轉大寫 toupper(char) //不須引用
字符轉小寫 tolower(char) //不須引用

```

### algorithm

相當好用的東西

1. 由小到大排序
```
#include<algorithm>
vector<int> vec(5) = {5,4,3,2,1};
sort(vec.begin(),vec.end());
```

2. 函數排序
```
#include<algorithm>
bool compare(const int a,const int b){
    return a > b;    
}
int main(){
    vector<int> vec(5) = {1,2,3,4,5};
    sort(vec.begin(),vec.end(),compare());
}
```
3. 數學運算
```
最大公因數，直接寫 int a = gcd(a,b);
最小公倍數，直接寫 int b =lcm(a,b);
如果你的編譯器不給你用
改寫如下
int a = __gcd(a,b);
int b = __lcm(a,b);
```

4. 二分搜尋
```
#include<algorithm>
int a = uppper_bound(vec,i);
int b = lower_bound(vec,i);
```
    
### sstream
    //

### functional
lambda表達式，秀操作，耍帥用，就是把function寫在function裡，讓funciton可以調用區域變數

像這樣
    
UVA1640
```
#include<iostream>
#include<vector>
#include<functional>
#include<cstring>
using namespace std;

int dp[12][12];
vector<int> dig;


int solve(int N,int num){
	dig.clear();
	memset(dp,-1,sizeof(dp));
	dig.push_back(-1);
	while(N){
		dig.push_back(N % 10);
		N /= 10;
	}	
	function<int(int,int,int,bool,bool)> dfs = [&](int pos,int pre,int ans,bool lead,bool is_limit)->int{
		if(!pos) return ans;
		if(!lead && !is_limit && ~dp[pos][ans]) return dp[pos][ans];
		int res = 0;
		for(int d = 0 , up = is_limit ? dig[pos] : 9 ; d <= up ; d++){
			if(lead && d==0) res += dfs(pos-1,pre,0,true,is_limit&&d==up);
			else res += dfs(pos-1,pre,ans+(d==pre),false,is_limit&&d==up);
		}
		if(!lead && !is_limit) dp[pos][ans] = res;
		return res;
	};
	return dfs(dig.size()-1,num,0,true,true);
}




int main(){
	int start,end;
	while(cin >> start >> end &&(start||end)){
		if(start > end) swap(start,end);
		for(int i = 0 ; i < 10 ; i++){
			printf("%d%c",solve(end,i)-solve(start-1,i),i == 9 ? '\n' : ' ');
		}
		
	}

}
```

## 類別(class)

vector那邊有用過，可以去搜尋
```
class p{
    public:
        int a;
        int b;
};
```

## 結構(struct)
    
可以參考我的結構體筆記 

[英雄可以受委屈](https://hackmd.io/@dFlMq8Y9SCyH8voQq01Ptg/BkkS4l-7_)
    
[但是你不能踩我的切爾西](https://hackmd.io/@dFlMq8Y9SCyH8voQq01Ptg/r1exBeZQ_)
```
typedef struct Point{
    int a,b;
}point;
```

## 密技
```
#intlcude <bits/stdc++.h>//所有引用，有這個，#include<algorithm>、#include<vecotr>、#include<iostream>，都不需要了。
```
錯的時候就喝口可樂鞭策自己，畢竟可樂傷身體。
## 組合拳
UVA. 10008
```
#include<bits/stdc++.h>
using namespace std;

class chcnt{
	public:
		char ch;
		int cnt;
};

int main(){
	int N;
	cin >> N;
	getchar();
	unordered_map<char,int> map;
	vector<chcnt*> vec;
	while(N--){
		string str;
		getline(cin,str);
		for(auto iter : str){
			if(isalpha(iter)) ++map[toupper(iter)];
		}
	}
	for(auto iter : map){
		if(iter.second){
			chcnt *p = new chcnt();
			p->ch = iter.first;
			p->cnt = iter.second;
			vec.push_back(p);
		}
	}
	sort(vec.begin(),vec.end(),[](chcnt *a,chcnt *b){
		if(a->cnt > b->cnt) return true;
		else if(a->cnt == b-> cnt && a->ch < b->ch) return true;
		return false;
	});
	for(auto iter : vec){
		cout << iter->ch << " " << iter->cnt << endl;
	}
}
```

UVA. 10336
```
#include<bits/stdc++.h>
using namespace std;

class chcnt{
    public:
        char ch;
        int cnt;
};

int main(){
    int N;
    cin >> N;
    for(int Case = 1 ; Case <= N ; Case++){
        int col,row;
        printf("World #%d\n",Case);
        cin >> col >> row;
        cin.ignore();
        vector<vector<char>> mat(col,vector<char>(row));
        vector<chcnt*> ans;
        map<char,int> map;
        for(int i = 0 ; i < col ; i++){
            string str;
            getline(cin,str);
            for(int j = 0 ; j < row ; j++){
                mat[i][j] = str[j];
            }
        }
        function<void(int,int,char)> inf = [&](int x, int y, char c){
		    if(x < 0 || x >= mat.size() || y < 0 || y >= mat[0].size() || mat[x][y] != c) return;
		    mat[x][y] = '*';
		    inf(x+1,y,c);
		    inf(x,y+1,c);
		    inf(x-1,y,c);
		    inf(x,y-1,c);
		};
        for(int i = 0 ; i < col ; i++){
            for(int j = 0 ; j < row ; j++){
                if(mat[i][j] != '*'){
                    map[mat[i][j]]++;
                    inf(i,j,mat[i][j]);
                }
            }
        }
        for(auto iter = map.begin() ; iter != map.end() ; iter++){
            if(iter->second){
                chcnt *p = new chcnt();
                p->ch = iter->first;
                p->cnt = iter->second;
                ans.push_back(p);
            }
        }
        sort(ans.begin(),ans.end(),[](chcnt *a,chcnt *b){
            if(a->cnt > b->cnt) return true;
            else if(a->cnt == b->cnt && a->ch < b->ch) return true;
            else return false;
        });
        for(int i = 0 ; i < ans.size() ; i++){
            cout << ans[i]->ch << ": " << ans[i]->cnt << endl;
        }
    }
}

```

