K&R练习1-17:超长行输出程序错误排查与修正求助
问题分析与修复
练习要求
Exercise 1-17. 编写一个程序,打印所有长度超过80个字符的输入行。
我编写了如下代码:
#include <stdio.h> int main() { int c; int line[80]; while (c != EOF) { for (int i = 0; i < 80 && (c = getchar()) != EOF; ++i) { if (c == '\n') i = 0; else line[i] = c; } if (c != EOF) { for (int i = 0; i < 80; ++i) putchar(line[i]); while ((c = getchar()) != EOF && c != '\n') putchar(c); putchar('\n'); } } return 0; }
但运行时发现程序不仅输出长度超过80字符的行,还会输出长度≤80的行(比如79字符的行)。
测试示例
我创建了文件j,内容如下:
111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111 1111111111111111111111111111111111111111111111111111111111111111111111111111111 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
经vim统计,各行长度分别为99、49、79、89字符。执行命令cat j | ./a.out后,预期仅输出第1和第4行,但实际输出了第1、3、4行。
错误原因
- 未初始化变量:外层
while (c != EOF)中,c初始未赋值,触发未定义行为。 - 核心逻辑错误:for循环中遇到换行符时将
i重置为0,导致程序跨多行累计读取字符计数,而非跟踪单行长度。比如79字符的行读取完成后,遇到换行符重置i为0,接着读取下一行的第一个字符,此时i累加至1,循环继续直到i达到80,触发输出逻辑,错误地将前一行的79字符输出。 - 忽略行边界:代码没有判断单行是否结束,仅以累计80个非换行字符作为输出触发条件,完全违背了“输出单行长度超80”的需求。
修复方案
修复思路:跟踪单行的实际长度,仅当单行长度超过80时才输出整行。以下是两种修复方式:
方式一:用缓冲区存储整行,判断长度后输出
#include <stdio.h> #define MAX_BUF 1000 // 定义足够大的缓冲区容纳单行 int main() { char buf[MAX_BUF]; int len = 0; int c; while ((c = getchar()) != EOF) { if (c != '\n') { if (len < MAX_BUF - 1) { buf[len++] = c; } else { // 缓冲区满时仍计数,确保长度统计准确 len++; } } else { // 行结束,判断长度是否超80 if (len > 80) { buf[len] = '\0'; printf("%s\n", buf); } len = 0; // 重置长度,处理下一行 } } // 处理文件末尾无换行的情况 if (len > 80) { buf[len] = '\0'; printf("%s\n", buf); } return 0; }
方式二:针对原代码逻辑修改,避免跨行累计
#include <stdio.h> int main() { int c; int line[80]; int line_len = 0; // 跟踪当前行的长度 while ((c = getchar()) != EOF) { if (c == '\n') { // 行结束,长度不足80则跳过 line_len = 0; continue; } if (line_len < 80) { line[line_len] = c; } line_len++; // 当长度超过80时,输出整行 if (line_len > 80) { // 首次超过时,先输出缓存的前80个字符 if (line_len == 81) { for (int i = 0; i < 80; i++) { putchar(line[i]); } } putchar(c); // 输出剩余字符直到行尾 while ((c = getchar()) != EOF && c != '\n') { putchar(c); } putchar('\n'); line_len = 0; // 重置状态 } } return 0; }
内容的提问来源于stack exchange,提问作者hansoko
相关产品推荐
相关产品推荐

