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

C語言輸入函數深度解析:scanf、gets 與緩衝區陷阱

     編輯:關於C

核心問題:混用 scanf 與 gets 導致輸入「跳過」

許多初學者在連續呼叫 scanf("%s", a) 和 gets(b) 時,發現程式未等待輸入直接跳過 gets(b)。根源在於兩者對「白字元」(空格、換行、製表符)的處理機制截然不同。

scanf("%s") 行為

  • 跳過前導白字元。
  • 讀取非白字元直到遇到下一個白字元為止。
  • 將結束的白字元(特別是 \n)留在緩衝區。
  • 在字串末尾自動補 \0。

gets() 行為

  • 直接從緩衝區讀取,不跳過白字元。
  • 讀取直到遇到 \n 或 EOF。
  • 丟棄 \n,並以 \0 結尾(不保留換行符)。

實例演示

char a[20], b[20], c[20];
scanf("%s", a);  // 輸入 "hello world\n" -> a="hello", 緩衝區剩 " world\n"
gets(b);         // 直接讀取 " world" (含前導空格),丟棄 \n,b=" world"
gets(c);         // 緩衝區已空,正常等待輸入 c

結果:b 讀到了「垃圾資料」(殘留的空格和 world),且未提示輸入。

緩衝區清理策略

錯誤做法:fflush(stdin)

C 標準未定義對輸入流的 fflush 行為。僅 MSVC 支援,GCC/Clang 會報錯或無效,嚴禁跨平台專案使用。

通用做法:fgets 替代

使用 fgets(buf, size, stdin) 讀取整行,再用 sscanf 解析,或手寫解析邏輯。fgets 會保留 \n(若空間允許),便於判斷輸入完整性,且標準保證跨平台一致。

字元輸入特例:scanf("%c")

%c 不跳過白字元,直接讀取緩衝區下一個字元(含 \n)。若需跳過白字元讀取非空白字元,請用 scanf(" %c", &ch)(格式字串前加空格)。

最佳實踐建議

  1. 統一使用 fgets + sscanf/手動解析,避免混用 scanf/gets。
  2. 若必須用 scanf,讀取數值/字串後,立即呼叫清理巨集 CLEAR_BUF()(見上文)。
  3. 棄用 gets(C11 已移除),改用 fgets 防止緩衝區溢位。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved