---
# System prepended metadata

title: Others
tags: [' note', books]

---

---
tags: books, note
---

# Others

## Pair
> 用途: 一個有`first`和`second`兩個元素的容器
> 使用時需要引入標頭檔`utility`或`algorithm`

要把兩個元素綁在一起的時候如果嫌麻煩不想自己刻就可以用`pair`代替

`pair`有內建定義用來比較的`less`函數，所以可以直接排序，不用多載`operator`，比較方便一點


### 用法

#### 宣告

```cpp
pair<first_type, second_type> p;
pair<first_type, second_type> p(a, b);
```
- `a`為型態為`first_type`的一變數
- `b`為型態為`second_type`的一變數

#### 存取

```cpp
p.first, p.second;
```

### 範例

```cpp=
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main() {
	vector<pair<int, int>> v{{2, 2}, {3, 1}, {2, 1}};
	sort(v.begin(), v.end());
	for (const auto& i : v)
		cout << i.first << ' ' << i.second << endl;
	return 0;
}
```

```
result:
2 1
2 2
3 1
```

### make_pair函數

```cpp
pair<first_type, second_type> p = make_pair(a, b);
```

功能同`pair`的建構元

---

###

## Range based for loop (since C++11)
> 用途: 將iterable的容器整個遍歷

### 用法

```cpp
for (range_declaration : range_expression) {
	loop_statement
}
```

- `range_declaration`: 為一個變數，其型態要和`range_expression`內元素的型態保持一致或可轉換成一致
- `range_expression`: 為一個可迭代(iterable)，或者說具有`begin`跟`end`的容器
- `loop_statement`: 可以為任何敘述、運算式

e.g.
```cpp=
vector<int> vec{1, 5, 4, 2, 3};
for (int i : vec)
    cout << i << ' ';
```

這個程式碼的作用相等於
```cpp=
vector<int> vec{1, 5, 4, 2, 3};
for (size_t i = 0; i != vec.size(); i++)
    cout << vec[i] << ' ';
```
由此可見當使用方式簡單時，
用Range based for loop的程式碼易讀性比較高，寫起來也比較簡潔

---


## Auto (since C++11)
> 用途: 自行判斷變數型態

e.g.
```cpp=
vector<pair<int, int>> vec;
auto copied_vec = vec;
```

相等於
```cpp=
vector<pair<int, int>> vec;
vector<pair<int, int>> copied_vec = vec;
```


再看一個極端一點的例子

e.g.
```cpp=
template<typename T>
void sort(__gnu_cxx::__normal_iterator<T*, vector<T>> l, __gnu_cxx::__normal_iterator<T*, vector<T>> r) {
	//some code
}
int main() {
	vector<int> v{1, 5, 3, 2, 4};
	sort(v.begin(), v.end());
	return 0;
}
```

等同於
```cpp=
void sort(auto l, auto r) {
	//some code
}
int main() {
	vector<int> v{1, 5, 3, 2, 4};
	sort(v.begin(), v.end());
	return 0;
}
```

---

## Lambda expression
> 又名Anonymous function, 匿名函數

當我們在自訂一些函數(e.g. `sort`)的比較函數時
常常會需要在外部先寫出來再去引用
如果用Lambda expression就可以在**需要用的地方進行定義**

lambda函式的形參表比普通函式的形參表多了3條限制：
1. 參數不能有預設值
2. 不能有可變長參數列
3. 不能有無名參數


### 用法

```cpp
[capture](parameters) mutable exception attribute -> return_type { function_body }
```

其中```mutable``` ```exception``` ```attribute``` 通常都用不到，可省

```cpp
[capture](parameters) -> return_type { function_body }
```

e.g.
```cpp=
[](int x, int y) -> int { return x + y; } // 指定回傳值型態為int
```

其中```return_type```在回傳值型態明確時可省，變成

```cpp
[capture](parameters) { function_body }
```

e.g.
```cpp=
[](int x, int y) { return x + y; } // 從return語句中隱式獲得的返回值類型
[](int& x) { ++x; }   // 沒有return語句 -> lambda函數的返回值為void
```

`parameters`在沒有```return_type``` 或 ```mutable```, ```exception```, ```attribute``` 也可省

最簡化版:
```cpp
[capture] { function_body }
```

e.g.
```cpp=
[]() { ++global_x; }  // 沒有參數，僅僅是訪問一個全局變量
[]{ ++global_x; }     // 與前者相同，()可以被省略
```

- `capture`: 擷取列表，在lambda表達式中使用外部之變數都要經由擷取列表擷取，利用以下形式可以選擇要以值傳遞或是引用(參照)傳遞
- `parameters`: 參數，和一般函式的參數用法一樣，不過不能設初始值，也不能用`auto`代替(C++14以上可以)
- `return_type`: 回傳值型態
- `function_body`: 函式主體，可以是任何表達式

#### 擷取列表
```cpp
[]        // 沒有定義任何變量，但必須列出空的方括號
[x, &y]   // x是按值傳遞，y是按引用傳遞
[&]       // 任何被使用到的外部變量都按引用傳入。
[=]       // 任何被使用到的外部變量都按值傳入。
[&, x]    // x按值傳入。其它變量按引用傳入。
[=, &z]   // z按引用傳入。其它變量按值傳入。
```

### 實際使用
e.g.
```cpp=
inline bool cmp(const int& a, const int& b) {
	return a > b;
}
int main() {
	vector<int> v{1, 5, 4, 2, 3};
	sort(v.begin(), v.end(), cmp);
	return 0;
}
```

等同於

```cpp=
int main() {
	vector<int> v{1, 5, 4, 2, 3};
	sort(v.begin(), v.end(), [](const int& a, const int& b) {
		return a > b;
	});
	return 0;
}
```

---

## I / O優化
C++的 `cin`/`cout` 相較於C的`printf`/`scanf`
基本上在一般情況下是慢蠻多的

所以需要一些**優化**來補足這個缺點

以下提供常見的優化方式供參考

### cin.tie + sync_with_stdio

這種最簡單，只要在`int main()`裡一開始放這兩行就能發揮作用

```cpp
cin.tie(nullptr);
ios::sync_with_stdio(false);
```

如果換行很多的時候可以在標頭檔下面加上`#define`

i.e.

```cpp=
#include <iostream>
#define endl '\n'
int main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    return 0;
}
```

:::info
> 更多的 I/O 優化可以參考 [$9^{th}$進階助教的 blog](https://happylearningcoding.blogspot.com/2020/04/c-io.html#more)
> [color=#4fff98][name=9th進階助教$][time=Sat, May 16, 2020 12:24 PM]
:::

---

## limits

有的時候我們會需要用到一些型態的最大最小值
像是`int`的最大$2^{31}-1$ aka $2147483647$之類的

那這時候就可以用`<limits>`裡的內建函式

i.e.
```cpp
numeric_limits<target_type>::max()
numeric_limits<target_type>::min()
```

- `target_type`: 需要求最大最小值的型態

那如果是字串大小的最大值，一般又會用另一種表示法

i.e.
```cpp
string::npos
```

這個常數代表的是`size_t`的 $-1$
不過`size_t`是一個無號整數，所以實際上等於$2^{32}-1$ aka $4294967295$

---

## 排版
#### 原則
- 每行對齊乾淨
- operator 前後加上 space
- 逗號前面不用 space, 後面要 space
- 大括號後要換行, 之後程式碼要縮排
- 小括號和大括號中間要一個空格 

e.g.
```cpp=
int main() {
    int tmp = 0, n;
    cin >> n;
    for (int i = 0; i < n; i++) {
        tmp += i;
    }
    cout << tmp << endl;
    return 0;
}
```
這樣的排版是不是很美觀呢?

舉個例子，$8^{th}$ 副班長，因為沒有排版習慣，去海高的時候被教授唸了一下 :poop:

總之，多看別人的 code 之後，寫的時候就會有排版的習慣了，排版是一個好的習慣，所以 space 不要太過節省哦!

:::info
> Sublime Text使用者可以參考[$9^{th}$進階教學的codebook](https://hackmd.io/@konchin/sublimeTutorial#附錄1-添加自動排版功能)
> [name=9th進階教學][time=Sat, May 16, 2020 12:30 PM]
:::

> [name=9th進階助教][time=Sat, May 16, 2020 12:43 PM]

---

## 一些技巧


### 輸出入by檔案

因為每次在測測資的時候都要一直複製貼上
而且輸出的東西又會跟輸入的東西混在一起
所以可以透過改變I/O stream來方便修改/存取
![](https://i.imgur.com/co561cF.png)

---

### 語法模板 + debug

懶人必備

```cpp!
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
using pll = pair<ll, ll>;
#define F first
#define S second
#define FOR(i, a) for(ll i = 0; i < a; i++)
#define REP(i, a, b) for(auto i = a; i != b; i++)
#define ALL(x) x.begin(), x.end()
#define GET(i, x) get<i>(x)
#define mkp make_pair
#define pb push_back

#define debug(...) do{\
	fprintf(stderr, "%s - %d : (%s) = ", __func__, __LINE__, #__VA_ARGS__);\
	_DO(__VA_ARGS__);\
}while(0)
template<typename T> void _DO(T&&x){cerr << x << '\n';}
template<typename T, typename... A> void _DO(T&&x, A&&...As){cerr << x << ", ";_DO(As...);}

int main() {
	cin.tie(nullptr), cout.tie(nullptr), ios::sync_with_stdio(false);
	return 0;
}
```

> [color=#FF0000][name=9th教學顧問][time=Sun, June 21, 2020 22:14]

---


> [color=#2329d1][name=9th進階教學][time=Sat, May 16, 2020 11:57 AM]

---