---
# System prepended metadata

title: 進階輸入輸出與資料型態
tags: [內湖高中程式競賽]

---

# 進階輸入輸出與資料型態

這篇來講講實用的輸入以及輸出技巧。由於很多輸入輸出都跟使用的資料型態有關，所以也會帶到一點資料型態的部分

## 常用資料型態的輸入輸出

### 整數
#### 資料大小範圍
| 資料型態 | 範圍 | 估計值 |
| ----- | ----- | ----- |
| int |$-2,147,483,648$ ~ $2,147,483,647$| $\pm2\times10^9$ |
|long long| $-9223372036854775808$ ~ $9223372036854775807$ | $\pm9\times10^{18}$ |
| \_\_int128 | $-2^{127}$ ~ $2^{127} - 1$ | 很大 |

#### 使用範例
```cpp
int a;
cin >> a;
cout << a << endl;
```

```cpp
long long b;
cin >> b;
cout << b;
```

`__int128` 無法被直接輸入輸出，通常是運算較大的數字才會用到

### 浮點數
浮點數就是指有小數點的數字

| 資料型態 | 範圍 | 精度 |
| ----- | ----- | ----- |
| float | $3.4e\pm38$ | 小數點後七位 |
| double | $1.7e\pm308$ | 小數點後十五位 |

#### cin/cout 範例
```cpp
float a;
double b;
cin >> a >> b;
cout << a << ' ' << b;
```

#### 小數點後第幾位
記得要有標頭檔 `<iomanip>`
```cpp
// #include <iomanip>
double n = 3.1415;
cout << fixed << setprecision(2) << n;
```

#### 控制小數
記得要有標頭檔 `<cmath>`
`ceil()` : 無條件進位
`floor()` : 無條件捨去
`round()` : 四捨五入

```cpp
// #include <cmath>
double x = 3.1415926535
cout << ceil(x) << ' ';
cout << floor(x) << ' ';
cout << round(x);
```

### 字元與字串
一個 `char` 變數就是儲存 [ASCII](https://zh.wikipedia.org/zh-tw/ASCII) 表裡面的一個整數編號

#### 使用範例
```cpp
char c = 'c';
cout << (int)c << endl;
cout << (char)66 << endl;
c -= 2;
cout << c << endl;
```

#### 輸出
```cpp
99
B
a
```

### 字串
這裡使用 C++ 的方法來處理字串，C 語言的可以看[這篇](https://hackmd.io/@ShanC/ByV3i9bUC)
首先要先引入標頭檔 `<string>`

#### cin/cout 範例
```cpp
// #include <string>

string s;
cin >> s;
cout << s;
```

#### 讀入整行範例
`getline()` 可以讀入整行
```cpp
// #include <string>

string s;
getline(cin, s);
cout << s;
```

#### cin/getline 範例
要注意 `getline()` 會把 `'\n'` 處理掉，但是 `cin` 不會處理掉 `'\n'` (`'\n'` 還是存在輸入流裡面)。因此兩者混著使用時須要再多一行 `getline()` 來處理掉 `'\n'`

```cpp
string s, tmp;
int n;
cin >> n;
getline(cin, tmp); // 這一行專門把 '\n' 給處理掉
getline(cin, s);
```

#### 數字與字串做轉換
```cpp
string s = "123";
int n = stoi(s);
cout << n << '\n';
cout << to_string(n) << '\n';
```

#### stringstream 處理空白
記得要有標頭檔 `<sstream>`

```cpp
// #include <sstream>
stringstream ss;
string tmp, s = "12 31415 15 1357";
int arr[10], n = 0;

ss << s; // 將字串丟入 stringstream
while (ss >> tmp) // 一個一個將字串丟入 tmp
    arr[n++] = stoi(tmp); // 把字串轉成數字、再存進 arr[]

for (int i = 0; i < n; i++) // 印出來
    cout << arr[i] << '\n';
```

## 輸出格式調整
### 向右對齊
記得要有標頭檔 `<iomanip>`
#### 使用範例
```cpp
cout << setw(4) << 3 << setw(4) << 12 << '\n';
cout << setw(4) << 213 << setw(4) << 8 << '\n';
```
#### 輸出
```tex
   3  12
 213   8
```

### 向左對齊
記得要有標頭檔 `<iomanip>`
#### 使用範例
```cpp
cout << left << setw(4) << 3 << left << setw(4) << 12 << '\n';
cout << left << setw(4) << 213 << left << setw(4) << 8 << '\n';
```
#### 輸出
```tex
3   12  
213 8
```

### 填入特定字元
記得要有標頭檔 `<iomanip>`
```cpp
int x = 3;
cout << setw(3) << setfill('0') << x << '\n'; // 003
```

## endl 與 '\n' 的差別
`endl` 除了暫存之外，還會  flush 掉 output buffer
`'\n'` 只會單純換行，因此會比較快
```cpp
cout << "hello, world" << endl;
cout << "It's MyGo!!!!! " << 123 << '\n';
```

## IO 優化
競程選手們習慣在主程式第一行就寫上
```cpp
ios::sync_with_stdio(false);
cin.tie(0);
```
這樣速度會快很多
有時候原本 **<font color="purple">TLE</font>** 的題目就會因此 **<font color="#008E00">AC</font>**

### sync_with_stdio()
先說 `sync_with_stdio()` 這個函數是什麼意思

這個函數是說「同步 C 與 C++ 的輸入/輸出流」。原本 C++ 的 `cin` 和 `cout` 是很快的，但是為了在混著使用時與 `scanf` 和 `printf` 同步，因此讓 C++ 的慢一點。原本 `sync_with_stdio()` 默認的數值是 `true`，所以我們上述那一行 `sync_with_stdio(false)` 就會把它關掉

### cin.tie()
在原本 C++ 的 `cin` 中，都會自動呼叫 `cout.flush()` 函數，這會導致 output buffer 每次出入都刷新一次，非常沒效率，因此需要 `cin.tie(0)` 把它關掉

### 避免 scanf/printf 與 cin/cout 混用
如果加了上面那兩行，可想而知，原本為了協調 C 與 C++ 的輸入輸出就會被破壞。一旦混用了就會出現不可預期的後果 (順序會亂掉)，這部分請讀者自行體會幾次就會知道了

## 參考資料
- [海大競程 - 進階輸入輸出](https://hackmd.io/@LeeShoWhaodian/AdvancedIO)
- [cppreference - std::endl](https://en.cppreference.com/w/cpp/io/manip/endl)
- [std::endl ??](https://hackmd.io/@magical/ryMaPoaQ_)
- [stackoverflow - "std::endl" vs "\n"](https://stackoverflow.com/questions/213907/stdendl-vs-n)
- [Codeforces - Why is the ios_base::sync_with_stdio(false);cin.tie(NULL); not making speed of cin = scanf??](https://codeforces.com/blog/entry/89212)

----

> [ShanC 程式競賽筆記](https://hackmd.io/@ShanC/B1ouGxqcC)
> 作者: ShanC
> 更新: 2024/1/10