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

scanf 與 gets 關鍵差異深度解析

     編輯:關於C語言

核心差異總覽

特性scanf("%s", str)gets(str)
讀取終止條件空白字元 (空格、換行、Tab)換行符 \n 或 EOF
空白處理跳過前導空白,遇空白停止保留所有空白 (含前導/內嵌)
緩衝區保護可用 %99s 限制寬度無任何保護,極度危險
返回值成功轉換項目數 (1 或 EOF)字串指標 或 NULL (EOF/錯誤)
標準狀態C89/C99/C11 標準C11 已移除 (C99 標記廢棄)

程式碼示範

#include <stdio.h>

int main() {
    char buf1[20], buf2[20];
    
    printf("輸入含空格的字串: ");
    // scanf("%19s", buf1);  // 只讀 "Hello"
    
    // fgets 替代 gets
    if (fgets(buf2, sizeof(buf2), stdin)) {
        // 移除尾隨換行
        buf2[strcspn(buf2, "\n")] = '\0';
        printf("fgets 讀到: [%s]\n", buf2);  // 完整讀取 "Hello World"
    }
    
    return 0;
}

為何 gets 必須禁用?

  • 不檢查緩衝區大小,輸入超過陣列長度必然導致緩衝區溢位
  • 可被惡意利用執行任意代碼 (經典安全漏洞)
  • C11 標準 (ISO/IEC 9899:2011) 正式移除,現代編譯器編譯會警告/報錯

安全替代方案

  1. fgets(buf, size, stdin):指定最大讀取長度,保留換行符需自行移除
  2. scanf("%19[^\n]", buf):掃描集讀取整行 (不含換行),需處理殘留換行符
  3. getline() (POSIX):自動分配記憶體,無長度限制

scanf 進階技巧

// 讀取整行 (含空格),最多 19 字元
scanf("%19[^\n]", str);  
// 清除輸入緩衝區殘留換行
while (getchar() != '\n');  

// 跳過指定字元
scanf("%*c");  // 讀取並丟棄一字元
scanf("%*[^\n]");  // 讀取並丟棄整行

結語

永遠不要使用 gets。現代 C 程式應統一使用 fgets 或掃描集 scanf,並嚴格檢查返回值與緩衝區邊界,這是安全程式設計的基礎底線。

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