在 C 語言中,單字符的輸入輸出是最基礎的 I/O 操作。getchar() 和 putchar() 作為標準庫 <stdio.h> 中的兩個核心字符處理函數,雖然功能單一,但理解其緩衝機制、返回值語義、EOF 處理、與 scanf/printf 的關係,對掌握 C 語言 I/O 體系至關重要。本文將從函數原型、使用細節、常見陷阱、進階模式四個維度深度解析。
int putchar(int c);
// 成功返回寫入的字符(作為 unsigned char 轉 int);失敗返回 EOF
- putchar('A'); // 輸出字符常量
- putchar(x); // 輸出字符變量值
- putchar('\101'); // 八進制轉義:輸出 'A' (ASCII 65=101₈)
- putchar('\n'); // 輸出控制字符:換行
EOF 表示輸出失敗(如磁盤滿、管道斷開)\n換行、\t製表、\b退格等不顯示圖形,執行對應控制
- #include <stdio.h>
- int main(){
- char a='B', b='o', c='k';
- putchar(a); putchar(b); putchar(b); putchar(c); putchar('\t');
- putchar(a); putchar(b);
- putchar('\n');
- putchar(b); putchar(c);
- return 0;
- }
輸出:Book Bo\nok
int getchar(void);
// 成功返回讀取字符(作為 unsigned char 轉 int,範圍 0-255);EOF(-1) 表示結束/錯誤
- char c;
- c = getchar(); // 讀取一字符賦給 c
- #include <stdio.h>
- int main(){
- char c;
- printf("input a character\n");
- c = getchar();
- putchar(c);
- return 0;
- }
getchar() 讀取的是 stdin 標準輸入流,通常為行緩衝:
getchar() 從流中逐個取出字符(含 \n)後果:程式執行到 getchar() 會阻塞,直到用戶按 Enter。
char c = getchar(); // 危險!
if (c == EOF) ... // EOF 通常為 -1,char 可能是有符號/無符號,比較失效
int c = getchar();
if (c == EOF) ... // 安全比較
char ch = (char)c; // 確認非 EOF 後再轉 char
getchar() 返回 EOF(通常 -1)表示流結束或錯誤
- int c;
- while ((c = getchar()) != EOF) {
- putchar(c); // 複製輸入到輸出
- }
int x; char c;
scanf("%d", &x); // 輸入 "123\n",'\n' 留在緩衝區
c = getchar(); // 直接讀到 '\n',而非下一個字符!
解決:getchar(); 讀走殘留 \n,或用 scanf(" %c", &c) 跳過空白。
輸入 abc + Enter,getchar() 只返回 'a',bc\n 留在緩衝區供下次讀取。
- int c, nl=0, nw=0, nc=0, in_word=0;
- while ((c = getchar()) != EOF) {
- nc++;
- if (c == '\n') nl++;
- if (c == ' ' || c == '\n' || c == '\t') in_word = 0;
- else if (!in_word) { in_word = 1; nw++; }
- }
- printf("行:%d 單詞:%d 字符:%d\n", nl, nw, nc);
- char line[1000]; int i = 0, c;
- while ((c = getchar()) != EOF && c != '\n' && i < 999) {
- line[i++] = c;
- }
- line[i] = '\0';
// 標準 C 無法關閉回聲,需用 termios (Linux) 或 conio.h (Windows)
putchar(getchar()); // 讀一字符即寫一字符
printf("%c", getchar()); // 同樣效果,但 printf 開銷大
| 維度 | getchar/putchar | scanf/printf |
|---|---|---|
| 操作單位 | 單字符 | 格式化數據 |
| 格式解析 | 無 | 複雜格式字串 |
| 性能開銷 | 極低 | 較高 |
| 類型轉換 | 無 | 自動轉換 |
| 錯誤處理 | 手動 (檢查 EOF) | 返回值檢查 |
| 適用場景 | 字符流處理、過濾、複製、統計 | 結構化數據輸入輸出 |