簡單紀錄一下這題的解題心得:
1. buffer 就是一個介於程式與硬體的記憶體,可以在輸出時作為暫時存放的空間,提高效率。
2. option 的部分需要檢驗 illegal input,當輸入為 test 等字串時,需要清空 buffer,不然會進入 infinite loop
* 首先輸入 test,此時 test 會留在 buffer 裡面
* `scanf("%d", &option)` 會嘗試讀取 int 型態變數,但讀取不到,便會進入下一個 loop
* 此時 test 依然留在 buffer,重複執行以上動作
* 所以必須將 buffer 清空,避免以上情形
3. C 並沒有標準的函式可以清空 input buffer,`fflush()` 在部分編譯器無法使用,屬於 compiler-dependent,
* 所以必須手寫一個函式:
```c
void clearBuffer()
{
int ch;
while ( ( ch = getchar() ) != '\n' && ch != EOF );
}
```
* 利用 `getchar()` 將 buffer 內殘存的 char 給讀取,這就等同於清除 buffer 內的資料,直到換行 or 檔案結束
4. `scanf("%d", &option) == 1` 表示 option 成功讀取到,此時再去判斷 otion 是否 $\in$ [1, 2, 3, 4, 5];`scanf("%d", &option) == 0` 表示沒有讀取到任何數字,因此清除 buffer 並 continue 到下一個 loop
5. 然而這樣會遇到一個問題:1234test 應當是 invalid input,但 `scanf()` 可以讀取到連續數字序列,也就是 1234,此時 test 依然會留在 buffer,因此我們必須再檢查 option 後面是否為 '\n'
6. 此時程式碼如下:
```c
int option = -1;
char extra = '0';
if ( scanf("%d%c", &option, &extra) != 2 )
{
// Invalid input
// Next loop
}
if ( extra != '\n' )
{
// Invalid input
// Next loop
}
```
後面就是利用 if-else 或是 switch 去判斷 option,若是不屬於 1~5,就一樣輸出 invalid input 並進入下一個 loop
7. 類似的概念可以套用至 option 2 的輸入格式檢驗,只不過改成 `scanf("\"%d,%d,%d\"%c")`,其餘部分跟上面程式碼差不多
8. option 1 的部分蠻簡單的,就按照題目所說的去做就好。其中,$2^{n}$ 可以用位元運算的左移運算子 `1 << n`
9. option 2 的輸入格式前面談過,後面部分也不難。需要注意的是 a,b,c 這樣的輸出格式,可以用一個 `bool firstOutput` 去紀錄,第一個輸出 `a`,後續輸出則是前面加上逗號,也就是 `,b`
10. option 3 也是按照題意即可,要注意測資的奇數似乎連負數都有算,而質數則必定大於 0
11. option 4 又是另一個看似很簡單,實際上必須要處理 overflow 的問題
* 題目 a, b 為 long long 型態,範圍為 $-2^{63}$ ~ $2^{63} - 1$
* 因此在處理一正一負時,long long 即可處理。不過要記得包含 0,我有一次出問題就在此處,忘記算 0
* 兩個都為正數時,則必須使用 unsigned long long 來處理,其範圍為 $0$ ~ $2^{64} - 1$
* 兩個都為負數時,就轉成正數,並在最後輸出時手動加上負號
* 最後還會遇到一個問題,就是 $(-2^{63}) + (-2^{63})$ 轉成正數相加會等於 $2^{64}$,已經超過 unsigned long long 的範圍,所以必須額外特判
* 然而,
```c
if ( a == ( -9223372036854775808 ) && b == ( -9223372036854775808 ) )
```
這樣會出問題,因為那個常數實際上是看成 9223372036854775808LL 再加上負號一元運算子,但 9223372036854775808LL 已經超過了 long long 的範圍,所以會出錯,正確寫法寫成 `-9223372036854775808ULL`;或是使用 limits.h 所定義的常數也可以
接下來補充一些東西:
1. 在 Unix/Linux 環境中,可以利用 `./main < test.in > test.out` 來達到輸出入重導向
2. 可以使用 `diff` 指令來比對兩個檔案
* `<`:左邊檔案(第一個檔案)有的內容
* `>`:右邊檔案(第二個檔案)有的內容
* `a`:add(在某行後要加東西)
* `d`:delete(刪掉某行)
* `c`:change(修改某行)
3. limits.h 常用的常數 (By ChatGPT)
| Type | Maximum | Minimum | Macro |
| -------------------- | -------------------------------------- | ---------------------------------- | ------------------------ |
| `char` | 127 | -128 | `CHAR_MAX`, `CHAR_MIN` |
| `signed char` | 127 | -128 | `SCHAR_MAX`, `SCHAR_MIN` |
| `unsigned char` | 255 | 0 | `UCHAR_MAX` |
| `short` | 32767 | -32768 | `SHRT_MAX`, `SHRT_MIN` |
| `unsigned short` | 65535 | 0 | `USHRT_MAX` |
| `int` | 2147483647 | -2147483648 | `INT_MAX`, `INT_MIN` |
| `unsigned int` | 4294967295 | 0 | `UINT_MAX` |
| `long` | 2147483647 or 9223372036854775807 (system-dependent) | -2147483648 或 -9223372036854775808 | `LONG_MAX`, `LONG_MIN` |
| `unsigned long` | 4294967295 or 18446744073709551615 | 0 | `ULONG_MAX` |
| `long long` | 9223372036854775807 | -9223372036854775808 | `LLONG_MAX`, `LLONG_MIN` |
| `unsigned long long` | 18446744073709551615 | 0 | `ULLONG_MAX` |