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

C語言字符 I/O 函數對比:getchar/putchar vs scanf/printf 互換指南

     編輯:C 語言問答

字符級與格式化 I/O 的等價轉換與選型指南

核心等價關系

功能字符函數格式化函數等價形式關鍵差異
讀單字符c = getchar()scanf("%c", &c)scanf 跳過空白需 "%c" 前加空格 " %c"
寫單字符putchar(c)printf("%c", c)printf 返回輸出字符數,putchar 返回字符值
讀字符串fgets(buf, n, stdin)scanf("%99s", buf) / scanf("%99[^\n]", buf)scanf 停於空白,fgets 讀整行含換行
寫字符串puts(str)printf("%s\n", str)puts 自動換行,printf 需顯式 \n

經典循環模式對比

// 模式 1:getchar 讀取直到換行
int c;
while ((c = getchar()) != '\n' && c != EOF) {
    putchar(c);  // 處理字符
}

// 模式 2:scanf 等價(注意空格跳過空白字符)
int c;
while (scanf(" %c", &c) == 1) {  // 格式串前的空格跳過 \n 等空白
    if (c == '\n') break;
    printf("%c", c);
}

// 模式 3:fgets 讀整行(推薦,安全可控)
char line[1024];
while (fgets(line, sizeof(line), stdin)) {
    // 移除末尾換行
    line[strcspn(line, "\n")] = '\0';
    printf("讀到一行: %s\n", line);
}

關鍵差異深度解析

1. 空白字符處理


// getchar: 讀取所有字符,包括空格、制表符、換行符
// scanf("%c"): 默認也讀取空白字符
// scanf(" %c"): 格式串開頭的空格 = 跳過任意數量空白字符(\n \t 等)

// 實測差異:
// 輸入: "a b\n"
// getchar() 循環: 讀到 'a', ' ', 'b', '\n'
// scanf("%c") 循環: 同 getchar
// scanf(" %c") 循環: 只讀到 'a', 'b' (跳過空格和換行)

2. 返回值語義

函數成功返回失敗/EOF 返回典型判斷
getchar()字符值 (0-255)EOF (-1)c != EOF
scanf("%c", &c)匹配項數 (1)EOF (-1)== 1
fgets()緩衝區指針NULL!= NULL

3. 緩衝區與換行殘留問題

// 經典 Bug:scanf 讀數後殘留 \n,後續 getchar/fgets 直接讀到空行
int n;
scanf("%d", &n);  // 輸入 "42\n",緩衝區剩 "\n"
char c = getchar(); // 直接讀到 '\n',非預期!

// 解決方案:
// 1. 額外讀取一個字符
scanf("%d", &n);
getchar(); // 吞掉 \n

// 2. 格式串加空格
scanf("%d ", &n); // %d 後的空格跳過後續空白

// 3. 統一用 fgets + sscanf(推薦)
char buf[100];
fgets(buf, sizeof(buf), stdin);
sscanf(buf, "%d", &n);

工程選型建議

安全替代方案總結

// 替代 gets(已移除 C11):
// fgets(buf, sizeof(buf), stdin);
// buf[strcspn(buf, "\n")] = '\0';

// 替代 scanf 讀字符串(防溢出):
// scanf("%99s", buf);  // 限制寬度
// 或 fgets + sscanf

// 替代 scanf 讀單字符(避免空白困擾):
// " %c" 格式串前加空格
// 或 getchar() 直接控制
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景推薦方案理由
高性能字符流處理getchar/putchar + 大緩衝區無格式解析開銷,適合編譯器/解析器
交互式菜單/單字符命令getchar() 無緩衝模式 (termios/raw mode)即時響應,無需回車確認
格式化數據讀寫scanf/printf 族類型安全、格式靈活、標準化
整行文本讀取fgets + sscanf/strtok/手工解析安全可控、緩衝區保護、保留換行信息
二進制數據fread/fwrite無格式轉換、高性能、跨平台需注意端序