You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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行。


错误原因

  1. 未初始化变量:外层while (c != EOF)中,c初始未赋值,触发未定义行为。
  2. 核心逻辑错误:for循环中遇到换行符时将i重置为0,导致程序跨多行累计读取字符计数,而非跟踪单行长度。比如79字符的行读取完成后,遇到换行符重置i为0,接着读取下一行的第一个字符,此时i累加至1,循环继续直到i达到80,触发输出逻辑,错误地将前一行的79字符输出。
  3. 忽略行边界:代码没有判断单行是否结束,仅以累计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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 10:34:51