# C 的格式化字串 我們輸出字串時,不一定只會是固定一堆字元,可能還會想把一些變數塞進去。那麼我們就需要在字串中加入一些記號,告訴電腦這裡需要插入變數,而那個記號稱為占位符。 在 C 語言中,我們會使用 `%` 來代表這個記號,後面會再加上一些符號,來告訴電腦要插入的變數的資料型態,以及要占多少寬度、置左還是置右、是否要補 0 之類的排版資訊。 ## 資料型態 | 符號 | 說明 | | :------------------ | :------------------------------ | | `%d` / `%i` | 十進位整數 | | `%u` | 無符號的十進位整數 | | `%o` | 無符號的八進位整數 | | `%x` / `%X` | 無符號的十六進位整數 | | `%f` / `%F` | 十進位的浮點數 | | `%e` / `%E` | 用科學記號表示浮點數 | | `%g` / `%G` | 依照浮點數大小使用 `%f` 或 `%e` | | `%a` / `%A` _(C99)_ | 十六進位的浮點數 | | `%c` | 字元 | | `%s` | 字串 | | `%p` | 指標的記憶體位址 | | `%n` | 什麼都不會輸出 | | `%%` | 百分比符號(`%`) | 備註: - 整數和浮點數格式化後,字母 (a-f) 的大小寫會根據符號的大小寫而定。 如: `%x` 會輸出 `6b`,而 `%X`會輸出 `6B`。 - `%f` 和 `%e` 會將小數點後的所有位數表示出來,即使全為 0 也會;而 `%g` 則會省略。 - `%a` 和 `%A` 於 C99 加入 - `%p` 只有小寫的形式,`%P` 不會轉成大寫字母,只會讓你編譯錯誤。 - `%n` 所需傳入的參數必須是 `int` 型別的指標。 - 由於 `%` 在這裡有著特殊的意義,所以要打兩次 (`%%`) 來讓電腦知道你只是想輸出 `%`,並沒有別的意思。 ### 範例 1 ```c= int a = 2042, b = -100; printf("%%d of a: %d\n", a); printf("%%o of a: %o\n", a); printf("%%x of a: %x\n", a); printf("%%X of a: %X\n", a); printf("\n"); printf("%%d of b: %d\n", b); printf("%%u of b: %u\n", b); ``` 輸出: ``` %d of a: 2042 %o of a: 3772 %x of a: 7fa %X of a: 7FA %d of b: -100 %u of b: 4294967196 ``` ### 範例 2 ```c= double c = 395.6, d = 123465790.123; printf("%%f of c: %f\n", c); printf("%%e of c: %e\n", c); printf("%%E of c: %E\n", c); printf("%%g of c: %g\n", c); printf("%%a of c: %a\n", c); printf("\n"); printf("%%f of d: %f\n", d); printf("%%e of d: %e\n", d); printf("%%g of d: %g\n", d); ``` 輸出: ``` %f of c: 395.600000 %e of c: 3.956000e+02 %E of c: 3.956000E+02 %g of c: 395.6 %a of c: 0x1.8b9999999999ap+8 %f of d: 123465790.123000 %e of d: 1.234658e+08 %g of d: 1.23466e+08 ``` ### 範例 3 ```c= char chr = 'C'; char str[] = "在外面%一次就好了"; printf("%c\n", chr); printf("這裡要兩次%%,%s\n", str); ``` 輸出: ``` C 這裡要兩次%,在外面%一次就好了 ``` ### 範例 4 ```c= int n = 1; printf("Address: %p\n", &n); printf("There is nothing %n.\n", &n); ``` 輸出: ``` Address: 0x7ffc8a370014 There is nothing . ``` ## 資料長度 有時候我們會加上一些符號,來表示資料型態的大小。例如 `%d` 加上 `ll` 後變成 `%lld`,表示`long long int` 而非 `int`。 下面是一些常用的符號: | 長度 | `d` / `i` | `u` / `o` / `x` / `X` | `f` / `e` / `g` / `a` | `n` | | :--------- | :-------------- | :-------------------- | :-------------------- | ---------------- | | (none) | `int` | `unsigned int` | `double` | `int*` | | hh _(C99)_ | `signed char` | `unsigned char` | | `signed char*` | | h | `short` | `unsigned short` | | `short*` | | l | `long` | `unsigned long` | `doulbe` _(C99)_ | `long*` | | ll _(C99)_ | `long long` | `unsigned long long` | | `long long*` | | j _(C99)_ | `intmax_t` | `uintmax_t` | | `intmax_t*` | | z _(C99)_ | signed `size_t` | `size_t` | | signed `size_t*` | | t _(C99)_ | `ptrdiff_t` | unsigned `ptrdiff_t` | | `ptrdiff_t*` | | L | | | `long doulbe` | | 備註: - `hh`、`ll`、`j`、`z`、`t` 於 C99 加入 ## 格式化 在 `%` 與表示資料型態的符號之間,還可以再加入一些東西,來指定輸出的格式。 | 符號 | 說明 | | :-------- | :---------------------------------------------------------------------------- | | - | 表示靠左對齊 (預設為靠右對齊) | | + | 強制顯示數值的正負號 (預設只有負數會顯示) | | _(space)_ | 如果沒有顯示正負號,就用顯示空格 | | # | 如果是八進位,在數字前面加上 `0`;如果是十六進位,在數字前面加上 `0x` 或 `0X` | | 0 | 表示在數字的左側補 0 | | _數字_ | 表示最少要顯示多少字元。長度不足的話會用空格填補;超過的話不會被截斷 | | _.數字_ | 表示浮點數在小數點後的位數 | ### 範例 1 ```c= int a = 12, b = 3465789; printf("|%d|%+d|% d|\n", a, a, a); printf("|%5d|%+5d|% 5d|\n", a, a, a); printf("|%05d|%+05d|% 05d|\n", a, a, a); printf("|%-5d|%-+5d|%- 5d|\n", a, a, a); printf("%5d\n", b); ``` 輸出: ``` |12|+12| 12| | 12| +12| 12| |00012|+0012| 0012| |12 |+12 | 12 | 3465789 ``` ### 範例 2 ```c= double c = 123.465789; printf("|%3f|\n", c); printf("|%.3f|\n", c); printf("|%8.3f|\n", c); printf("|%8.0f|\n", c); printf("%#.6a\n", c); ``` 輸出: ``` |123.465789| |123.466| | 123.466| | 123| 0x1.eddcf8p+6 ``` ## 延伸閱讀 其他更詳細的內容,可以參考說明文件: - https://cplusplus.com/reference/cstdio/printf/ - https://en.cppreference.com/w/c/io/fprintf