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

C語言 printf 與 scanf 完全指南:格式控制符、參數對應、高質量輸入輸出實踐

     編輯:關於C語言

printf — 格式化輸出

完整格式字符串語法

%[標誌][寬度][.精度][長度]類型
組件選項說明
標誌- + 0 空格 #左對齊、強制符號、零填充、正數前空格、替代形式 (0x/0/0X)
寬度m 或 *最小字符寬度,不足左/右填充;* 從參數獲取
精度.n 或 .*整數:最小位數 (前導 0);浮點:小數位數;字符串:最大字符數
長度hh h l ll j z t Lhh=char, h=short, l=long/double, ll=long long, L=long double
類型見下表決定參數解讀方式

常用類型字符對照表

類型對應參數輸出示例備註
d iint42 -7有符號十進制
uunsigned int42無符號十進制
ounsigned int52八進制 (無前綴)
x Xunsigned int2a 2A十六進制 (小寫/大寫)
#x #Xunsigned int0x2a 0X2A# 標誌添加前綴
f Fdouble3.140000定點小數,默認 6 位小數
e Edouble3.140000e+00科學計數法
g Gdouble3.14自動選 f/e 短者,去尾隨 0
cint (字符)A單字符
sconst char*hello字符串 (至 '\0')
pvoid*0x7ffe...指針地址 (實現定義格式)
nint*(無輸出)**寫入已輸出字符數** — 安全風險,慎用
%-%輸出字面 '%' (寫 %%)

精度與寬度實例

printf("%10d", 42);       // "        42" (右對齊,寬度 10)
printf("%-10d", 42);      // "42        " (左對齊)
printf("%010d", 42);      // "0000000042" (零填充)
printf("%.4d", 42);       // "0042" (精度 4:最小位數)
printf("%10.2f", 3.14159); // "      3.14" (寬度 10,小數 2 位)
printf("%.5s", "hello world"); // "hello" (最大 5 字符)
printf("%-10.5s", "hi");     // "hi       " (左對齊,寬度 10,最多 5 字符)

長度修飾符關鍵對應

  • %hd / %hhd — short / signed char。
  • %ld / %lld — long / long long。
  • %lf — double (printf 中 %f 也可接 double,因默認提升;但 scanf **必須** %lf 讀 double)。
  • %Lf — long double。
  • %zu — size_t;%td — ptrdiff_t。

scanf — 格式化輸入

核心差異

  • 參數**必須是地址** (指針):scanf("%d", &a);。
  • 格式字符串中**空白字符 (空格、換行、Tab) 匹配輸入中任意長度的空白** (包括 0 個)。
  • 非格式字符 (如 scanf("%d,%d", &a, &b);) **必須原樣匹配輸入**,否則匹配失敗停止。
  • 返回值:成功匹配並賦值的項目數;EOF 表示輸入結束/錯誤。

常見格式字符 (與 printf 類似,但無精度/標誌)

類型參數類型說明
d iint*有符號十進制 (i 也支持 0x/0 開頭的八/十六進制)
uunsigned*無符號十進制
o x Xunsigned*八/十六進制
f e gfloat*單精度浮點
lf le lgdouble*雙精度浮點 (**必須 l**)
Lflong double*長雙精度
cchar*讀單字符 (含空白),%1c 讀 1 字符
schar*讀字符串 (跳過前導空白,遇空白停止,**不安全**,易溢出)
[...]char*掃描集:%[^\n] 讀整行 (含空格),%[0-9] 只讀數字
pvoid**讀指針地址
nint*寫入已讀字符數

高質量輸入輸出實踐

1. printf 最佳實踐

  • **格式字符串不接受用戶輸入** — 防格式化字符串攻擊:printf(user_str); → printf("%s", user_str);。
  • **參數數量類型嚴格匹配** — 開啟編譯器警告 (-Wformat),C++ 用 std::format (C++20) 或 iostream 類型安全。
  • **輸出指針用 %p 配合 (void*)** — printf("%p", (void*)ptr);。
  • **浮點輸出控制精度** — printf("%.2f", val); 避免 3.140000。

2. scanf 避坑指南 (極其重要)

  1. 必須取地址:scanf("%d", &a); 而非 a。
  2. 避免在格式串放非格式字符,特別是 \n:scanf("%d\n", &a); 會導致需輸入非數字字符才能結束。
  3. 字符串輸入防溢出:char buf[20]; scanf("%19s", buf); (寬度 = size-1)。或用 fgets(buf, sizeof(buf), stdin); 讀整行再解析。
  4. 處理殘留換行符:連續 scanf("%d", &a); scanf("%c", &ch); 第二次讀到 '\n'。解決:scanf(" %c", &ch); (格式串前加空格跳過空白) 或循環清理 while (getchar() != '\n');。
  5. 檢查返回值:if (scanf("%d", &a) != 1) { /* 輸入錯誤處理 */ }。
  6. 掃描集讀整行:char line[100]; scanf("%99[^\n]", line); getchar(); // 吃掉換行。

3. 進階:scanf 返回值驅動循環

int x;
while (scanf("%d", &x) == 1) { // 成功讀 1 個整數
    process(x);
}
// 輸入非數字或 EOF 退出

總結對比表

特性printfscanf
方向輸出輸入
參數值地址 (指針)
空白處理按格式輸出格式串空白匹配任意輸入空白
非格式字符原樣輸出必須原樣匹配輸入
返回值輸出字符數成功賦值項目數 / EOF
安全風險格式化字符串攻擊緩衝區溢出、殘留換行、匹配失敗

精通 printf/scanf 格式控制、參數匹配、返回值檢查、殘留字符處理,是 C 語言工程師從「能跑」到「健壯」的分水嶺。現代 C++ 優先選擇 iostream 或 std::format (C++20) 獲得類型安全與擴展性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved