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

C 語言 gets/puts 函數詳解:非格式化字符串輸入輸出與安全替代方案

     編輯:關於C語言

函數原型

#include <stdio.h>
char *gets(char *str);   // 已棄用,C11 移除
int puts(const char *str);

puts():輸出字符串並換行

  • 功能:向標準輸出寫入字符串,自動補 \n
  • 等價於 printf("%s\n", str)
  • 只能輸出字符串,無格式化能力
  • 返回值:成功非負,失敗 EOF

gets():讀取整行(含空格)

  • 功能:從標準輸入讀取一行,遇 \n 或 EOF 停止,不保留換行符,末尾加 \0
  • 與 scanf("%s") 區別:scanf 遇空白停止,gets 讀整行
  • 極度危險:無緩衝區長度檢查,輸入超長必導致棧溢出,C11 標準已移除

代碼示例

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

int main(void) {
    char a[20] = {0};
    char *p = a;
    
    printf("What's your name?\n");
    gets(a);          // 危險!
    puts(a);
    
    puts("How old are you?");
    gets(p);          // 危險!
    puts(p);
    
    return 0;
}

指針算術演示


static char str1[] = "An array example.";
static char str2[] = "A pointer example.";
puts(&str1[4]);  // 從 'r' 開始輸出 → "ray example."
puts(str2 + 4);  // 從 'i' 開始輸出 → "inter example."

原理:字符串以 \0 結尾,puts 從給定地址輸出至 \0。若字符數組缺少結尾 \0,將輸出亂碼直至偶然遇到 0 字節。

安全替代方案

函數用法優點
fgetsfgets(buf, sizeof(buf), stdin)指定最大讀取長度,保留 \n,安全標準
gets_sgets_s(buf, sizeof(buf))C11 附錄 K,檢查長度,不保留 \n
scanfscanf("%19[^\n]", buf)指定寬度,不保留 \n

fgets 最佳實踐


char buf[100];
if (fgets(buf, sizeof(buf), stdin)) {
    // 移除末尾換行符
    buf[strcspn(buf, "\n")] = '\0';
    puts(buf);
}

歷史殘留問題

  • 舊教材/代碼大量使用 gets,必須識別並替換
  • VC6.0 等舊編譯器仍提供 gets,編譯會警告但可通過
  • 現代編譯器對 gets 直接報錯或鏈接失敗

總結

puts 可安全用於簡單字符串輸出;gets 是臭名昭著的安全漏洞根源,絕對禁止在新代碼中使用。統一改用 fgets 或帶寬度限制的 scanf,並處理換行符殘留,是 C 語言字符串輸入的專業標準。

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