簡單紀錄一下這題的解題心得: 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` |