---
# System prepended metadata

title: Program Design I HW2 Notes
tags: [C]

---

簡單紀錄一下這題的解題心得：

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`             |
