修改打印最長文本行的程序主函數 `main`,使其能打印任意長度輸入行的長度,並盡可能多地打印文本內容。
#include <stdio.h>
#define MAXLINE 10 // 故意設小以演示截斷邏輯
// 讀取一行,返回實際長度(含換行符),緩衝區最多存 MAXLINE-1 字符 + '\0'
int getline(char line[], int maxline);
int main() {
int len, max = 0;
char line[MAXLINE];
char *longest = NULL; // 動態分配存儲最長行
while ((len = getline(line, MAXLINE)) > 0) {
printf("行長度: %d, 內容: %s", len, line);
if (len > max) {
max = len;
// 重新分配空間存儲完整最長行
longest = realloc(longest, len + 1);
// 因 getline 可能截斷,這裡需重讀或改進 getline 返回完整行
// 簡化演示:僅複製緩衝區內容
strncpy(longest, line, MAXLINE - 1);
longest[MAXLINE - 1] = '\0';
}
}
if (max > 0) {
printf("\n最長行長度: %d\n", max);
printf("最長行內容(可能截斷): %s\n", longest);
free(longest);
}
return 0;
}
// 關鍵改進:返回實際行長度,而非存儲長度
int getline(char s[], int lim) {
int c, i, actual_len = 0;
for (i = 0; (c = getchar()) != EOF && c != '\n'; ++i) {
actual_len++;
if (i < lim - 1) // 緩衝區未滿才存儲
s[i] = c;
}
if (c == '\n') {
actual_len++; // 計入換行符
if (i < lim - 1)
s[i++] = c;
}
s[i] = '\0';
return actual_len; // 返回真實長度
}
int actual_len = 0;
for (...) {
actual_len++; // 無條件計數
if (i < lim - 1) s[i] = c; // 條件存儲
}
return actual_len;
這是練習的核心:計數與存儲解耦。
使用 `realloc` 動態擴展 `longest` 緩衝區,避免預設固定大小限制。
若需**完整存儲**任意長度行(而非僅計數),需改用動態緩衝區:
char *read_line_dynamic() {
size_t cap = 128, len = 0;
char *buf = malloc(cap);
int c;
while ((c = getchar()) != EOF && c != '\n') {
if (len + 1 >= cap) {
cap *= 2;
buf = realloc(buf, cap);
}
buf[len++] = c;
}
if (c == '\n') buf[len++] = c;
buf[len] = '\0';
return buf; // 調用者 free
}
K&R 練習 1-16 通過「小緩衝區 + 大邏輯」強迫學習者面對緩衝區邊界、真實長度 vs 存儲長度、動態記憶體這三個 C 語言核心難點。掌握「計數與存儲解耦」模式,是編寫健壯輸入處理代碼的基石。