一、C 語句五大類別
| 類別 | 形式 | 範例 |
| 表達式語句 | 表達式 + `;` | `a = b + c;` `func();` `i++;` |
| 函數調用語句 | 函數名 + 實參 + `;` | `printf("Hello");` `scanf("%d", &x);` |
| 控制語句 | 條件/迴圈/跳轉 | `if` `switch` `for` `while` `do-while` `break` `continue` `goto` `return` |
| 復合語句 | `{ ... }` 包裹多語句 | 函數體、`if` 區塊、迴圈體 |
| 空語句 | 單獨 `;` | `while (getchar() != '\n');` 清空輸入緩衝 |
二、鏈式賦值與右結合性
a = b = c = d = e = 10;
等價於(右結合):
e = 10;
d = e;
c = d;
b = c;
a = b;
所有變數最終皆為 10。
三、字符輸入輸出:getchar / putchar
| 函數 | 原型 | 說明 | 範例 |
getchar | int getchar(void) | 從 stdin 讀一字符,返回 int(含 EOF) | int c = getchar(); |
putchar | int putchar(int c) | 向 stdout 寫一字符,返回寫入字符 | putchar('A'); |
注意:返回型別為 `int` 而非 `char`,以容納 `EOF`(通常為 -1)。
四、格式化輸出:printf 完全指南
調用形式
printf("格式控制字串", 輸出項列表);
格式字串完整語法
%[旗標][寬度][.精度][長度]類型
類型字符對照表
| 類型 | 輸出形式 | 範例 |
d, i | 有號十進制整數 | `printf("%d", -42);` → `-42` |
u | 無號十進制整數 | `printf("%u", 42u);` → `42` |
o | 八進制(無前綴) | `printf("%o", 42);` → `52` |
x, X | 十六進制(小寫/大寫) | `printf("%x", 42);` → `2a` |
f | 十進制小數 | `printf("%.2f", 3.14159);` → `3.14` |
e, E | 指數記號 | `printf("%e", 1234.5);` → `1.234500e+03` |
g, G | f/e 較短者 | 自動選擇 |
c | 單字符 | `printf("%c", 'A');` → `A` |
s | 字串 | `printf("%s", "Hello");` → `Hello` |
p | 指標位址 | `printf("%p", (void*)&x);` → `0x7ffe...` |
% | 字面 `%` | `printf("%%");` → `%` |
旗標字符
| 旗標 | 效果 |
- | 左對齊(預設右對齊) |
+ | 正數也顯示 `+` 號 |
空格 | 正數前加空格,負數加 `-` |
# | 八進制加 `0`、十六進制加 `0x`、浮點數強制顯示小數點 |
0 | 寬度不足時前導補 `0`(而非空格) |
寬度與精度
%10d:最寬 10,不足左補空格。
%.5f:小數點後 5 位。
%10.3f:總寬 10,小數 3 位。
%.*f:精度由引數指定:`printf("%.*f", 3, 3.14159);` → `3.142`。
長度修飾
| 修飾 | 對應類型 |
hh | signed char / unsigned char |
h | short / unsigned short |
l | long / unsigned long / double (for %f) |
ll | long long / unsigned long long |
L | long double |
z | size_t (C99) |
t | ptrdiff_t (C99) |
五、格式化輸入:scanf 完全指南
調用形式
scanf("格式控制字串", 地址列表);
核心規則:地址列表必須是**變數位址**(`&var`),字串陣列名本身即位址(`str` 等價 `&str[0]`)。
格式字串語法
%[*][寬度][長度]類型
關鍵差異對照 printf
| 特性 | printf | scanf |
| 精度控制 | 支援 .精度 | 不支援(如 `%.2f` 非法) |
| 非格式字符 | 原樣輸出 | 不可出現(會匹配輸入) |
| 跳過輸入 | 無 | * 抑制賦值:`%*d` 讀取但不存儲 |
| 空白處理 | 無特殊 | `%d` 等自動跳過前導空白;`%c` **不跳過** |
常見陷阱與正確用法
- 忘記 `&`:`scanf("%d", a);` → 錯誤。正確:`scanf("%d", &a);`
- `%c` 讀取空白/換行:`scanf("%c%c%c", &a, &b, &c);` 輸入 `d e f` → `a='d', b=' ', c='e'`。
解法:格式字串加空白 `scanf(" %c %c %c", ...)` 或用 `getchar()`。
- 寬度截斷:`scanf("%5d", &a);` 輸入 `123456` → `a=12345`,剩餘 `6` 留給下次讀取。
- 長度修飾:`long x; scanf("%ld", &x);`;`double y; scanf("%lf", &y);`(`%f` 為 `float`)。
六、綜合範例:安全讀取整數並輸出
#include <stdio.h>
int main(void) {
int a, b, c;
printf("請輸入三個整數(空白分隔):");
if (scanf("%d %d %d", &a, &b, &c) != 3) {
printf("輸入格式錯誤\n");
return 1;
}
printf("讀取結果:a=%d, b=%d, c=%d\n", a, b, c);
printf("十六進制:a=0x%x, b=0x%x, c=0x%x\n", a, b, c);
printf("寬度 8 右對齊:%8d%8d%8d\n", a, b, c);
return 0;
}