<style>
.reveal .slides {
text-align: left;
font-size:30px
}
</style>
# Advanced IO
----
- int/ long long
- char and ascii
- string compare
- getline
- stringstream
- setw
- setprecision
- ceil/floor/round
- IO 優化
----
## int / long long
int 所能儲存的範圍為 -2,147,483,648 至2,147,483,647
約為 $\pm 2\cdot 10^9$
long long 為 -9223372036854775808 ~ 9223372036854775807
約為 $\pm 9\cdot 10^{18}$
----
## char and ASCII
一個 char 變數 就是儲存 [ASCII](https://www.asciitable.com/) 裡的一個整數編號
char / int 轉換
```cpp=
char c = 'c';
cout << (int)c << endl;
cout << (char)66 << endl;
c -= 2;
cout << c << endl;
```
----
## 字串比較
兩個字串 $s$ 和 $t$ 比較大小,
會從頭開始比較,比較到第一個不同的字元為止,或者字串結束
s < t
```
s = "abdee"
t = "abfa"
```
s > t
```
s = "abdfee"
t = "abdfe"
```
s == t
```
s = "abc"
t = "abc"
```
----
## getline()
#include\<string\>
讀取一整行的輸入(包括空白)
用法
```cpp=
string str;
getline(cin, str);
```
----
## cin 與 getline 混用
```cpp=
int x;
string y;
cin >> x;
getline(cin, y);
```
如果讀以下輸入
```
123
abc
```
會發現 y 是空的
----
由於 cin 會讀到非整數的字元為止,所以會停在換行,
而 getline 會讀到換行,因此會只把 cin 剛剛的空白吃掉而已,
因此在 cin 後要使用 getline 的話,需要先把換行吃掉
解法可以直接 getline 兩次,先把前一行的換行吃掉就可以讀下一行了
```cpp=
int x;
string y;
cin >> x;
getline(cin, y);
getline(cin, y);
```
----
## stringstream
#include\<sstream\>
如果字串為一堆數字中間隔一堆空白所組成,
e.g. str = "123 52 3 66";
想把這些數字用陣列存起來,可以使用 stringstream 函式
```cpp=
int arr[10] = {};
string str, tmp;
getline(cin, str);
stringstream ss(str);
for(int i = 0; ss >> tmp; i++){
arr[i] = tmp;
}
```
----
## 數字中間用逗號隔開的 case
input
```
123,432,542,111
```
使用 stringstream 把數字存進陣列中
```cpp=
int arr[10] = {};
char c;
string str, tmp;
getline(cin, str);
stringstream ss(str);
ss >> tmp;
arr[0] = tmp;
for(int i = 0; ss >> c >> tmp; i++){
arr[i] = tmp;
}
```
----
## 數字與字串之間的轉換
stoi 可以把字串轉換成 int
stoll 可以把字串轉換成 long long 型態
to_string 可以把整數轉換成字串
```cpp=
string s = "123";
int x = stoi(s);
cout << x << endl;
cout << to_string(x) << endl;
```
----
## setw
#include\<iomanip\>
輸出的格式如果需要靠左/右對齊的題目,可以使用 setw 來輸出
預設是靠右對齊,如果想要靠左對其可以在前面加 left
```cpp=
cout << setw(4) << 3 << setw(4) << 12 << endl;
cout << setw(4) << 213 << setw(4) << 8 << endl;
cout << endl;
cout << left << setw(4) << 3 << left << setw(4) << 12 << endl;
cout << left << setw(4) << 213 << left << setw(4) << 8 << endl;
```

----
## setfill('0')
#include\<iomanip\>
setw 預設為靠右,setfill 會把空的位置都補成指定字元
```cpp=
int x = 3;
cout << setw(3) << setfill('0') << x << endl;//005
```
----
## setprecision
#include\<iomanip\>
控制小數點位數,最後一位會四捨五入
```cpp=
double x = 3.141559;
cout << fixed << setprecision(3) << x << endl;
cout << fixed << setprecision(4) << x << endl;
cout << fixed << setprecision(5) << x << endl;
```
----
## ceil/floor/round
控制小數,無條件進位/無條件捨去/四捨五入
至整數
```cpp=
double x = 3.141559;
cout << ceil(x) << endl;
cout << floor(x) << endl;
cout << round(x) << endl;
```
----
## 輸出特殊字元
要輸出特殊字元,要再特殊字元前面加反斜線
```cpp
cout << "\\ \' \"" << endl;
```
----
## IO 優化
```cpp
ios::sync_with_stdio(0), cin.tie(0);
```
這個函數是 C++ 為了相容 C,保證程式在使用了 printf 和 std::cout 的時候不發生混亂,將輸出綁到了一起。同步的輸出是安全的。
這其實是 C++ 為了相容而採取的保守措施,也是使 cin/cout 速度較慢的主要原因。我們可以在進行 IO 操作之前將 stdio 解除綁定
但是要注意不能同時使用 std::cin 和 scanf,以及 std::cout 和 printf。
----
## 更多語法
[cppreference](https://en.cppreference.com/w/)
---
## 作業
請各位先去 vjudge.net 辦帳號後點以下連結進入群組
[vjudge 群組連結](https://vjudge.net/group/toi--icpc-training?r=wG5DBzKmcopmEWn7sqQn)
之後作業會放在群組內
{"title":"進階輸入輸出","description":"字串輸入","contributors":"[{\"id\":\"19f09ccf-6b99-452f-971f-955cfc1657f3\",\"add\":3578,\"del\":105}]"}