# *2.4 C 語言的  printf( ) 格式化輸出函數

## 為什麼需要「格式化」輸出？

想像一下，如果你的程式計算出圓周率是 3.1415926，但你只想在螢幕上顯示 3.14；或者你希望輸出的成績單欄位能夠像表格一樣文字靠左對齊，數值靠右對齊。

這些都無法單純地將變數丟出來就辦到，我們需要「告訴」printf 應該用什麼「格式」來呈現資料，這就是格式化輸出的精髓。

### 標頭檔

要使用 printf，請務必在程式開頭引用標頭檔：

```cpp
#include <cstdio>
```

`cstdio` 是指 C語言的標準輸入輸出(c standard input output)。

## printf 語法與核心：「格式化字串」

printf 的語法結構如下：

```C++
printf("格式化字串", 變數1, 變數2, ...);
```

它的靈魂就在於第一個參數——**格式化字串**。這個字串由兩種內容組成：

1. 一般文字：會被原封不動地輸出到螢幕上。
2. 格式指定符 (Format Specifier)：以 % 符號開頭，作為一個「佔位符」，它會被後面依序對應的變數值給取代。

這是最基本也最常用的幾種，我們先從它們開始。



| 指定符 | 對應資料類型 | 說明 |
| -------- | -------- | -------- |
| Text     | Text     | Text     |
|%d|int(整數)|以十進位形式輸出整數。|
|%f|float, double (浮點數)|輸出浮點數 (小數)。|
|%c|char| (字元)	輸出單一字元。|
|%s|字串 (char 陣列)|輸出一整個字串。|
|%%|無|若你想顯示一個 % 符號，需使用 %%。|

**範例 1：基本應用**

```C++
#include <cstdio>

int main() {
    int student_id = 101;
    float score = 85.5;
    char level = 'B';
    printf("學生學號：%d, 分數：%.1f, 等級：%c\n", student_id, score, level);
    // %.1f 的意思是浮點數只顯示到小數點後第一位
    return 0;
}
```

**執行結果：**
<div class="coutput">
學生學號：101, 分數：85.5, 等級：B
</div>

---

## 格式化字串的各種變化與應用

接下來是今天的重頭戲。我們可以對 `%` 加上一些「修飾」，來精準控制輸出的樣式。

### **1. 控制輸出寬度 (Field Width)**

我們可以指定一個數字來表示該欄位最少要佔用的寬度。如果實際內容比指定的寬度窄，預設會在**左邊**用空白補滿（也就是**靠右對齊**）。

**語法**：`%[寬度]d`、`%[寬度]f` ...

**範例 2：讓數字整齊排列**

```C++
#include <cstdio>

int main() {
    int num1 = 123;
    int num2 = 45;
    int num3 = 6789;

    printf("原始輸出：\n");
    printf("%d\n", num1);
    printf("%d\n", num2);
    printf("%d\n", num3);

    printf("\n指定寬度為 5 輸出 (靠右對齊)：\n");
    printf("%5d\n", num1); // 在 123 左邊補 2 個空白
    printf("%5d\n", num2); // 在 45 左邊補 3 個空白
    printf("%5d\n", num3); // 寬度不足 5，但數字不會被切斷，會完整顯示
    return 0;
}
```

**執行結果：**
<div class="coutput">
原始輸出：
123
45
6789
<br>
指定寬度為 5 輸出 (靠右對齊)：
  123
   45
 6789
</div>

---

### **2. 控制對齊方式 (Alignment)**

如果我們想靠左對齊，只要在寬度數字前加上一個負號 `-` 即可。

**語法**：`%-[寬度]d`、`%-[寬度]s` ...

**範例 3：文字的靠左與靠右**

```C++
#include <cstdio>

int main() {
    char product1[] = "Apple";
    char product2[] = "Banana";

    printf("--- 商品清單 (寬度 10) ---\n");
    printf("靠右對齊: |%10s|\n", product1);
    printf("靠左對齊: |%-10s|\n", product2);
    printf("--------------------------\n");
    return 0;
}
```

**執行結果：**

<div class="coutput">
--- 商品清單 (寬度 10) ---
靠右對齊: |     Apple|
靠左對齊: |Banana    |
-------------------------
</div>

---

對於浮點數 (%f)，我們可以用 .數字 來指定要顯示到小數點後幾位。注意：系統會自動進行四捨五入。

語法：`%.[位數]f`

**範例 4：計算圓面積並控制精度**

```C++
#include <cstdio>

int main() {
    double pi = 3.1415926535;

    printf("原始數值：%f\n", pi);
    printf("顯示到小數點後 2 位：%.2f\n", pi); // 輸出 3.14
    printf("顯示到小數點後 4 位：%.4f\n", pi); // 輸出 3.1416 (注意看，有四捨五入！)
    printf("不顯示小數：%.0f\n", pi);          // 輸出 3
    return 0;
}
```

執行結果：
<div class="coutput">
原始數值：3.141593
顯示到小數點後 2 位：3.14
顯示到小數點後 4 位：3.1416
不顯示小數：3
</div>

---

我們也可以將寬度和精度結合起來，創造出更完美的排版。

語法：`%[總寬度].[小數位數]f`

**範例 5：顯示商品價格**

```C++
#include <cstdio>

int main() {
    float price1 = 5.99;
    float price2 = 123.5;

    // 總寬度為 8，小數點後 2 位
    printf("價格清單 (總寬度 8)：\n");
    printf("|%8.2f|\n", price1);
    printf("|%8.2f|\n", price2);
    return 0;
}
```

**執行結果：**
<div class="coutput">
價格清單 (總寬度 8)：
|    5.99|
|  123.50|
</div>

**解說：** 

總共佔 8 個字元寬，並且小數點後面固定顯示 2 位，不足的會補 0。

---

### **3. 補零 (Zero Padding)**

如果希望在靠右對齊時，不是補空白而是補 `0`，只要在寬度數字前加上 `0` 即可。這常用於學號、時間等場合。

**語法**：`%0[寬度]d`

**範例 6：顯示學號**

```C++
#include <cstdio>

int main() {
    int id1 = 7;
    int id2 = 123;
    printf("三年一班 座號列表：\n");
    printf("補空白：%3d\n", id1);
    printf("補零：%03d\n", id1); // 寬度 3，不足處補 0
    printf("補零：%03d\n", id2);
    return 0;
}
```

**執行結果：**
<div class="coutput">
三年一班 座號列表：
補空白：  7
補零：007
補零：123
</div>

---

## 總結與速查表

以下表格提供同學們需要時查詢使用：

|分類|語法|說明與範例|
|---|---|---------|
|基礎類型|	%d|	輸出十進位整數 (int)。 `printf("%d", 100);` → `100`|
||%f|	輸出浮點數 (float, double)。 `printf("%f", 12.34);` → `12.340000`|
||%c|	輸出單一字元 (char)。 `printf("%c", 'A');` → `A`|
||%s|	輸出字串 (char 陣列)。 `printf("%s", "Hi");` → `Hi`|
||%%|	輸出 % 符號本身。 `printf("100%%");` → `100%`|
|寬度控制|	%[n]d|	輸出寬度至少為 n 的整數，靠右對齊。`printf("%4d",12);` → `  12`|
||%- [n]d|	輸出寬度至少為 n 的整數，靠左對齊。`printf("%-4d",12);` → `12  `|
|精度控制|	%.[n]f|	輸出浮點數，顯示到小數點後 n 位。`printf("%.2f", 3.14159);` → `3.14`|
|組合使用|	%[w].[p]f|	總寬度為 w，小數點精度為 p。 `printf("%6.2f", 3.14159);` →  `  3.14`|
|特殊旗標|	%0[n]d|	輸出寬度為 n 的整數，不足處在左邊補 0。 `printf("%04d", 55);` → `0055`|

這些符號放在字串中會有特殊功能。

|序列|名稱|功能|
|---|---|----|
|\n	|換行符|將游標移至下一行的開頭。|
|\t	|定位符|(Tab)	將游標移至下一個定位點，常用於對齊欄位。|
|\\	|反斜線|顯示一個 \ 符號。|
|\"	|雙引號|在字串中顯示一個 " 符號。|

## 練習題作業

請同學動手實作，加深對 printf 格式化的理解。

###### 練習題 1：我的個人檔案

* **目標：** 練習 %s, %d, %.1f 的基本使用。
* **說明：** 請宣告變數來儲存姓名、年齡、身高(公尺)，並依照以下格式輸出。

**輸出範例：**

<div class="coutput">
姓名：陳月光
年齡：17 歲
身高：1.7 公尺
</div>

---

###### 練習題 2：商品價目表

* **目標：** 練習使用寬度、對齊與小數點精度，製作對齊的表格。
* **說明：** 有三樣商品及其價格如下：
    + "Milk": 65.5 元
    + "Bread": 42 元
    + "Juice": 51.25 元

請使用 printf 格式化功能，輸出如下對齊的價目表。商品名稱欄位寬度為 10 且靠左對齊，價格欄位總寬度為 8 且顯示到小數點後 2 位。

**輸出範例：**

<div class="coutput">
+------------+----------+
| Item       | Price    |
+------------+----------+
| Milk       |    65.50 |
| Bread      |    42.00 |
| Juice      |    51.25 |
+------------+----------+
</div>

---

###### 練習題 3：數位時鐘

* 目標：練習使用補零 0 的技巧。
* 說明：請宣告三個整數變數 h, m, s 分別代表時、分、秒，並賦值 (例如 h=8, m=5, s=30)。請使用 printf 輸出 HH:MM:SS 的格式，也就是不足兩位數時要補零。

**輸出範例：**

<div class="coutput">
目前時間為：08:05:30
</div>




<link rel=stylesheet type="text/css" href="https://nlmoodle.ddns.net/css/h.css">