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

C語言格式化輸入輸出函數族詳解:scanf/printf 進階用法與陷阱

     編輯:關於C語言

C語言格式化輸入輸出函數族詳解:scanf/printf 進階用法與陷阱

scanf 與 printf 是 C 語言最基礎也最易踩坑的 I/O 函數。本文系統梳理格式字串語法、返回值語義、緩衝區行為、常見錯誤與最佳實踐,助你寫出健壯的交互式程式。

格式字串完整語法

%[flags][width][.precision][length]specifier
元素說明範例
flags- 左對齊 + 符號 空格 正數前加空格 # 替代形式 0 零填充%-10d %+d %05d
width最小寬度,* 表示由參數指定%10s %*d
.precision小數位數/最大字串長度,* 由參數指定%.2f %.*s
lengthhh h l ll j z t L 對應 char/short/int/long/long long/intmax_t/size_t/ptrdiff_t/long double%hhd %ld %lld %zu %Lf
specifierd/i 整數 u 無符號 o/x/X 八/十六進制 f/F/e/E/g/G 浮點 c 字元 s 字串 p 指針 n 寫入已輸出字元數 %% 輸出 %%d %x %f %s %p %%

scanf 族函數關鍵差異

函數原型特點
scanfint scanf(const char*, ...)標準輸入,跳過空白字元(%c/%[ 除外)
fscanfint fscanf(FILE*, const char*, ...)指定流,檔案/管道通用
sscanfint sscanf(const char*, const char*, ...)從字串解析,安全無副作用
vscanf 等int vscanf(const char*, va_list)變參列表版,供封裝使用

scanf 返回值與錯誤處理

  • 返回成功匹配並賦值的項目數,可能少於格式字串預期
  • 返回 EOF(通常 -1)表示讀取失敗或檔案結束且未賦值任何項目
  • 必須檢查返回值,否則變數可能保留垃圾值
int a, b;
if (scanf("%d %d", &a, &b) != 2) {
    // 處理輸入錯誤:清空緩衝區、提示重輸、或退出
    while (getchar() != '\n');  // 簡易清行
}

經典陷阱與對策

  1. 換行符殘留
    scanf("%d", &n) 讀完整數後,\n 留在緩衝區。後續 scanf("%c", &c) 會直接讀到換行符。
    對策:scanf(" %c", &c)(格式字串前加空格跳過空白),或改用 fgets+sscanf。
  2. 緩衝區溢位
    scanf("%s", buf) 不限制長度,極危險。
    對策:scanf("%19s", buf)(寬度 = 緩衝區大小 - 1),或用 fgets。
  3. %c 讀取空白
    %c 不跳過空白,%1s 會跳過並讀一個非空白字元。需求不同選對格式。
  4. 掃描集合 %[ ]
    %[^\n] 讀整行(含空格),%[0-9] 只讀數字。結尾需配合 %*c 吃掉分隔符。
  5. 長度修飾符不匹配
    long x; scanf("%d", &x) 未定義行為。必須用 %ld。

printf 族函數精度與對齊技巧

printf("%+010.4f\n", 3.14);   // +00003.1400(符號、零填寬、4位小數)
printf("%-10s|\n", "left");   // "left      |"(左對齊)
printf("%*d\n", 5, 42);       // 寬度由參數 5 指定
printf("%.s\n", 3, "hello");  // 精度由參數 3 指定 -> "hel"

安全替代方案推薦

  • 輸入:fgets(buf, sizeof(buf), stdin) + sscanf / strto* 系列(strtol, strtod 可檢測錯誤位置)
  • 輸出:snprintf 防止緩衝區溢位,C11 printf_s(可選)
  • 高效能解析:手寫狀態機或使用 scanf 但嚴格限制寬度

最佳實踐清單

  1. 所有 scanf 呼叫必須檢查返回值
  2. 字串輸入務必指定寬度(%19s)
  3. 混合數值與字元輸入時,用 fgets+sscanf 逐行處理
  4. 浮點數輸出指定精度(%.2f),避免科學記號驚喜
  5. 指針輸出用 %p 配合 (void*) 強轉

掌握格式化 I/O 的精髓與陷阱,能讓你的 C 程式在交互、解析、日誌等場景既安全又高效。

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