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

C 語言輸入函數大比拼:scanf、gets、getchar 緩衝區陷阱與最佳實踐

     編輯:關於C語言

三大函數核心差異

函數讀取單位結束條件緩衝區處理安全性
scanf格式化字段匹配失敗 / EOF留下換行符低(緩衝區溢出風險)
gets整行換行符 / EOF吞掉換行符,**不檢查長度**極低(C11 已移除)
getchar單字符EOF逐字符讀取高(需自行組裝)

經典陷阱:殘留換行符導致「跳過輸入」


int age;
char name[20];
scanf("%d", &age);   // 輸入 "25\n",scanf 讀 25,\n 留在緩衝區
gets(name);          // 直接讀到 \n → name 為空串!

清理緩衝區的正確姿勢

方法 1:scanf 格式字串吃掉空白(推薦)


scanf("%d", &age);
scanf(" %19[^\n]", name);  // 開頭空格吃掉任意空白(含 \n),%19 防溢出

方法 2:循環讀取並丟棄


int c;
while ((c = getchar()) != '\n' && c != EOF);  // 清空當前行

方法 3:fgets 統一讀行 + sscanf 解析(最穩健)


char line[100];
fgets(line, sizeof(line), stdin);  // 讀整行含 \n
sscanf(line, "%d", &age);

fgets(line, sizeof(line), stdin);
sscanf(line, "%19s", name);  // 或用 strtok 解析

優勢:輸入與解析分離,行緩衝區大小固定,杜絕溢出,換行符自動處理。

方法 4:fflush(stdin) —— 非標準,勿用

  • C 標準規定 fflush 僅適用於輸出流或更新流。
  • MSVC 允許 fflush(stdin) 清空輸入緩衝區,但**不可移植**,嚴禁在跨平台代碼中使用。

gets 的替代品:fgets


char buf[100];
fgets(buf, sizeof(buf), stdin);  // 最多讀 99 字符 + \0
// 移除末尾 \n(若有)
buf[strcspn(buf, "\n")] = '\0';
  • C11 標準已**移除 gets**,編譯器會報警。
  • fgets 保留 \n,需手動去除;讀滿緩衝區時不會丟失數據(下次調用繼續讀)。

完整範例:安全讀取整數與字串


#include <stdio.h>
#include <string.h>

int read_int(const char *prompt) {
    char line[64];
    int val;
    while (1) {
        printf("%s", prompt);
        if (!fgets(line, sizeof(line), stdin)) return -1;  // EOF
        if (sscanf(line, "%d", &val) == 1) return val;
        puts("Invalid integer, try again.");
    }
}

void read_str(const char *prompt, char *buf, size_t sz) {
    printf("%s", prompt);
    fgets(buf, sz, stdin);
    buf[strcspn(buf, "\n")] = '\0';
}

int main() {
    int age = read_int("Age: ");
    char name[20];
    read_str("Name: ", name, sizeof(name));
    printf("Hello %s, age %d\n", name, age);
    return 0;
}

總結建議

  1. 棄用 gets,改用 fgets。
  2. 減少直接用 scanf 讀字串,改用 fgets + sscanf。
  3. 格式化讀取整數/浮點數時,scanf 可接受,但需檢查返回值並清理殘留換行符。
  4. 統一採用「讀行→解析」模式,徹底解決緩衝區殘留、溢出、格式錯誤等問題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved