六大格式化 I/O 函數族覆蓋**標準流、文件流、字符串緩衝區**三大目標。本文統一梳理函數原型、格式字符串語法、返回值語義、安全陷阱與典型用法。
函數族速查總表
| 目標 | 輸出 | 輸入 |
| 標準流 (stdout/stdin) | printf | scanf |
| 文件流 (FILE*) | fprintf | fscanf |
| 字符串緩衝區 (char*) | sprintf / snprintf | sscanf |
一、格式字符串通用語法
%[flags][width][.precision][length]type
- flags:
-左對齊 +正負號 空格正數前空格 #前綴(0x/0) 0填零
- width: 最小寬度,
* 從參數獲取
- precision: 小數位數/字符串最大長度/有效位數,
* 從參數獲取
- length:
hh/h/l/ll/j/z/t/L 對應 char/short/long/long long/intmax_t/size_t/ptrdiff_t/long double
二、輸出類型完整表
| type | 參數類型 | 輸出形式 |
d/i | int | 有符號十進制 |
u | unsigned | 無符號十進制 |
o | unsigned | 八進制 |
x/X | unsigned | 十六進制 (小寫/大寫) |
f/F | double | 定點小數 (預設 6 位) |
e/E | double | 科學計數法 (小寫/大寫 e) |
g/G | double | 自動選 f/e (短者),去尾部 0 |
a/A | double | 十六進制浮點 (C99) |
c | int | 單字符 (轉 unsigned char) |
s | char* | 字符串 (至 \0) |
p | void* | 指針地址 (十六進制) |
n | int* | **不輸出**,寫入已輸出字符數 |
% | 無 | 字面 % |
三、輸入類型完整表
| type | 參數類型 | 讀取行為 |
d | int* | 有符號十進制 |
i | int* | 自動識別 0x/0 進制 |
u | unsigned* | 無符號十進制 |
o/x/X | unsigned* | 八/十六進制 |
f/e/g | float* | 浮點數 (同義) |
lf/le/lg | double* | 雙精度浮點 |
s | char* | 跳過空白,讀至空白 (危險!無長度限制) |
c | char* | 單字符 (含空白),%1c 讀 1 字符 |
[...] | char* | 掃描集:僅讀集合內字符,如 %[a-z] |
[^...] | char* | 排除掃描集:讀非集合字符,如 %[^\n] 讀整行 |
n | int* | 寫入已讀字符數 |
* (抑制) | 無 | 讀取但**不賦值**,如 %*d 跳過一個整數 |
四、六大函數詳細對比
1. printf / fprintf / sprintf / snprintf
- 返回值: 成功返回**輸出字符數** (不含 \0);
snprintf 返回**本應輸出的總字符數** (可檢測截斷)
- sprintf 危險: 無長度限制 → 緩衝區溢出,**必須用
snprintf(buf, n, fmt, ...)**
- fprintf: 同
printf 但目標為 FILE*,返回寫入字符數或 EOF
2. scanf / fscanf / sscanf
- 返回值: 成功返回**賦值項數**;失敗/輸入盡返回 EOF
- scanf 致命缺陷:
%s 無長度限制,**絕不直接用於不可信輸入**
- sscanf 安全: 源字符串固定,無溢出風險,適合解析協議/配置
- 掃描集讀整行:
sscanf(line, "%[^\n]", buf) 或 fgets 更簡潔
五、經典陷阱與避坑
scanf("%s", buf) → fgets(buf, n, stdin) + sscanf / 手動解析
sprintf(buf, "%s", src) → snprintf(buf, sizeof(buf), "%s", src)
- 格式字符串漏洞:
printf(user_input) → printf("%s", user_input)
%n 利用寫入任意地址 → 禁用或極度謹慎
- 浮點
float 傳給 %f 自動提升為 double,但 scanf 必須用 %lf 讀 double
- 上一篇文章: C語言 static 關鍵字深度解析:修飾變量與函數的雙重語義
- 下一篇文章: ASP.NET GridView 進階技巧匯總:數據綁定、模板列、事件處理與客戶端腳本
Copyright ©
程式碼之家 All Rights Reserved