首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言輸入輸出格式控制大全:printf/scanf 格式符、標志、寬度、精度完整速查表

     編輯:關於C語言

C 語言格式化 I/O 核心參考:從 `%d` 到 `%n` 的完整屬性矩陣

格式化輸入輸出是 C 語言與外界交互的橋樑。`printf` 族與 `scanf` 族雖語法相似,但語義細節差異極大。本文匯總 **轉換說明符**、**標志字符**、**寬度/精度/長度修飾符**、**掃描集**、**特殊返回值 `%n`** 等完整規範,附帶優先級陷阱、掃描集高級用法、動態寬度技巧,作為桌面速查手冊。

一、轉換說明符完整對照表

二、標志字符 (Flag) —— 控制對齊、符號、前綴

符號printf 輸出scanf 輸入備註
`%d`, `%i`有符號十進制整數有符號十進制整數 ( `%i` 兼容八/十六進制前綴 )最常用
`%u`無符號十進制整數無符號十進制整數
`%o`八進制 (無前綴)八進制整數`#` 標志添加 `0` 前綴
`%x`, `%X`十六進制 (小寫/大寫)十六進制整數`#` 添加 `0x`/`0X` 前綴
`%f`, `%F`定點小數 (默認 6 位)浮點數 (float/double)
`%e`, `%E`科學計數法 (默認 6 位)浮點數
`%g`, `%G`自動選 `%f`/`%e` 短者,去尾隨 0浮點數不輸出無意義 0
`%a`, `%A`十六進制浮點數 (C99)浮點數 (C99)精確表示二進制浮點
`%c`單字符單字符 (不跳過空白!)`%c` 讀取空白需用 ` %c`
`%s`字符串 (至 `\0`)字符串 (跳過前導空白,至空白)**不含空白**,需配合掃描集
`%p`指針地址 (實現定義格式)指針地址對應 `void*`
`%n`**不輸出**,將**已輸出字符數**寫入對應 `int*` 參數**不讀取**,將**已讀取字符數**寫入對應 `int*` 參數**不計入返回值**,安全風險高 (格式化字符串漏洞)
`%%`輸出字面 `%`匹配字面 `%`

三、完整格式語法:`%[flags][width][.precision][length]specifier`

%-+0 10.4 l d
│ │  │  │  │  │
│ │  │  │  │  └─ 轉換符
│ │  │  │  └─ 長度修飾: hh/h/l/ll/j/z/t/L
│ │  │  └─ 精度: .數字 或 .*
│ │  └─ 寬度: 數字 或 *
│ └─ 標志: - + 空格 # 0
└─ 起始 %

寬度與精度語義差異

標志printf 效果scanf 效果
`-`左對齊 (默認右對齊)無效
`+`有符號數**總是顯示符號** (`+3` / `-3`)無效
`空格`正數前加空格,負數顯示 `-` (與 `+` 互斥)無效
`#``%o` 加 `0`、`%x/%X` 加 `0x/0X`、`%f/%e/%g` 強制顯示小數點、`%g` 保留尾隨 0無效
`0`**數值類型**左側填 `0` 而非空格 (配合寬度);`-` 覆蓋 `0`無效

長度修飾符對照

類型寬度精度
整數 (`d,i,o,u,x,X`)最小字符寬度,不足填充**最小數字位數**,不足左補 0 (不影響符號)
浮點 (`f,F,e,E`)最小字符寬度**小數點後位數** (默認 6)
浮點 (`g,G`)最小字符寬度**最大有效數字位數** (默認 6)
字符串 (`s`)最小字符寬度**最大字符數** (截斷)
字符 (`c`)最小字符寬度無效

四、scanf 獨有高級特性:掃描集 `[...]` / `[^...]`

**唯一能讀取含空白/特定分隔符字符串的機制**。

%[chars]   → 只讀取 chars 集合內字符,遇非集合字符停止
%[^chars]  → 讀取「非 chars 集合」字符,遇集合內字符停止
// 兩者自動在末尾添加 '\0',需確保緩衝區足夠大

// 經典用例:
scanf("%[^\n]", line);        // 讀整行 (含空格),遇 \n 停
scanf("%[^,]", field);        // 讀 CSV 字段,遇 , 停
scanf("%[0-9]", digits);      // 只讀數字
scanf("%[^;,]", token);       // 讀至 ; 或 ,
scanf("\"%[^\"]\"", str);     // 讀雙引號內容

安全必加寬度限制:`%31[^\n]` 防止緩衝區溢出 (留 1 字節給 `\0`)。

五、動態寬度/精度:`*` 占位符

// 寬度/精度由參數傳入,而非寫死格式串
printf("%*.*s\n", width, precision, str);  // 等價 "%10.5s" 若 width=10, precision=5
scanf("%*d %d", &x);                       // `%*d` 讀取並**丟棄**一個整數,不賦值
// * 表示「抑制賦值」,不計入返回值,用於跳過輸入字段

六、特殊返回值 `%n`:記錄已處理字符數

int n;
printf("hello%n world", &n);  // 輸出 "hello world",n = 5 (hello 長度)
scanf("abc%n def", &n);       // 輸入 "abc def",n = 3 (abc 長度)

// 應用:解析定長協議、計算字段偏移
// 風險:格式化字符串攻擊利用 %n 任意寫內存,現代編譯器默認禁用或需特定標志啟用

七、printf 返回值與錯誤處理

  • 返回**輸出字符總數** (不含結束 `\0`),負值表示輸出錯誤 (如磁盤滿、管道破裂)。
  • `snprintf` 返回**本應輸出的字符數** (可能大於實際寫入),負值表示編碼錯誤。

八、常見陷阱速查

修飾printf 對應類型scanf 對應類型
`hh``signed char` / `unsigned char``signed char*` / `unsigned char*`
`h``short` / `unsigned short``short*` / `unsigned short*`
`l``long` / `unsigned long` / `double` (對 `%f`) / `wchar_t*` (對 `%c/%s`)`long*` / `unsigned long*` / `double*` / `wchar_t*`
`ll``long long` / `unsigned long long``long long*` / `unsigned long long*`
`j``intmax_t` / `uintmax_t``intmax_t*` / `uintmax_t*`
`z``size_t``size_t*`
`t``ptrdiff_t``ptrdiff_t*`
`L``long double``long double*`

九、C99/C11 新增格式 (需 `` ``)

// 定寬整數打印 (可移植)
printf("int32: %" PRId32 ", uint64: %" PRIu64 "\n", i32, u64);
// 掃描
scanf("%" SCNd32 "%" SCNu64, &i32, &u64);

// bool 類型 (C99 _Bool, C23 bool)
printf("bool: %d\n", flag);  // 0/1
scanf("%d", &flag);          // 讀 0/1 非零視為真

總結

掌握格式化 I/O 的核心在於:**區分輸出與輸入語義差異、精確控制寬度精度長度、善用掃描集處理複雜輸入、防範緩衝區溢出與格式串漏洞**。建議打印此表貼近顯示器,或配置編輯器 Snippet 快速插入常用模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
陷阱錯誤代碼正確代碼原因
`scanf` 讀字符吃掉換行`scanf("%c", &c);``scanf(" %c", &c);``%c` 不跳過空白,前加空格跳過 `\n`
`%s` 緩衝區溢出`scanf("%s", buf);``scanf("%31s", buf);`必須限制寬度 = buf_size - 1
`printf` 格式串漏洞`printf(user_input);``printf("%s", user_input);`用戶輸入含 `%n` `%s` 導致任意讀寫
浮點 `printf` 傳 `float``printf("%f", f);``printf("%f", f);` ✅可變參自動提升 `float→double`,`%f` 兼容兩者
`scanf` 浮點傳 `float``scanf("%f", &f);` ✅`scanf("%f", &f);` ✅`%f` 對應 `float*`,`double` 需 `%lf`
優先級:`==` 高於 `&``if (x & y == 0)``if ((x & y) == 0)``==` 先結合,必須加括號