函式原型回顧
char *fgets(char *str, int size, FILE *stream);
int fputs(const char *str, FILE *stream);
關鍵行為總結
- fgets:最多讀取
size-1 個字元,遇到 \n 或 EOF 停止;會保留 \n,並在字串末尾自動加 \0;
- fputs:將字串寫入流,**不會自動加 \n**,也**不會寫入字串末尾的 \0**;內部靠計數器決定寫入長度,而非尋找 \0。
實驗驗證代碼
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define MAXLINE 4
int main() {
char buf[MAXLINE];
char outbuf[BUFSIZ];
setbuf(stdout, outbuf); // 讓 stdout 使用我們的緩衝區
while (fgets(buf, MAXLINE, stdin)) {
if (fputs(buf, stdout) == EOF) {
perror("fputs");
exit(EXIT_FAILURE);
}
}
// 修改 outbuf 中的 \n 為 'k',下一字元為 'j'
outbuf[6] = 'k';
outbuf[7] = 'j';
// 程式結束時 stdout 刷新,實際輸出只到 'k',說明 fputs 依賴內部計數器
return 0;
}
實驗現象解讀
- 輸入
nihaoa\n,因 MAXLINE=4,每次只讀 3 字元 + \0;
- fputs 寫入 stdout 緩衝區時,不看 \0,而是根據 fgets 實際讀取的字元數寫入;
- 即使人為修改緩衝區中 \0 後的字元,fputs 輸出長度也不變,證明其有獨立計數機制。
常見坑點提醒
- fgets 讀滿
size-1 時**不會丟棄剩餘字元**,下次呼叫會繼續讀取同一行剩餘部分;
- 若需逐行處理,建議用動態緩衝區(如
getline)或自行拼接;
- fputs 失敗只回傳 EOF,需配合
ferror 判斷錯誤原因。