【问题标题】:Why is this C program printing line longer than MAXLINE?为什么这个C程序打印线比MAXLINE长?
【发布时间】:2020-04-04 20:12:34
【问题描述】:

程序应打印所有长度大于MINLINE 5 且小于MAXLINE 10 的输入行。参考。 K&R 书练习 1.17

#include <stdio.h>
#define MAXLINE 10
#define MINLINE 5

int getlines(char lines[], int maxline);

int main()
{
    int length;
    char lines[MAXLINE];

    while ((length = getlines(lines, MAXLINE)) > 0)
    {
        if (length > MINLINE)
            printf("%s", lines);
    }
    return 0;
}

int getlines(char lines[], int maxline)
{
    int i, c;

    for (i = 0; i < maxline - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
    {
        lines[i] = c;
    }

    if (c == '\n')
    {
        lines[i] = c;
        ++i;
    }

    lines[i] = '\0';

    return i;
}

期望的输出应该是这样的:-

Hello\n
Hello\n
hi\n
excuseMe\n
excuseMe\n
longLineNotToBePrinted\n
done
done

但出乎意料的是,程序打印的行比MAXLINE 长得多,有时打印的行会省略一些尾随字符。

【问题讨论】:

  • C99 及更高版本需要main() 上的显式返回类型(int)。您不应该使用 30 年前的 C 方言写作。这是当今谨慎对待 K&R 的众多原因之一。
  • 好的先生,我会从下次开始做
  • 找出答案的最佳方法是在调试器中运行您的程序并逐行执行。
  • getlines() 中的代码一次最多可读取 MAXLINE 个字符,但会留下输入中较长的行的剩余部分,以便为下一次输入操作做好准备。如果部分行长于 5(6 或更多),则您的代码会将其写出。如果行尾太短,您的代码不会打印它。
  • 您需要测试 maxline-3 以便仍然可以附加 \n\0。

标签: c getchar


【解决方案1】:

对于初学者来说这个功能

int getlines(char lines[], int maxline)
{
    int i, c;

    for (i = 0; i < maxline - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
    {
        lines[i] = c;
    }

    if (c == '\n')
    {
        lines[i] = c;
        ++i;
    }

    lines[i] = '\0';

    return i;
}

具有未定义的行为,因为它可以将字符 '\0' 存储在具有有效索引范围 [0, maxline). 的数组 lines 之外的位置 maxline

至于您关于输出的问题,如果您输入的文本大于maxline,那么该函数将返回一个不包含换行符'\n' 的字符串。所以下一个字符串会在同一行输出。

【讨论】:

  • 关于:that has the valid range of indices [0, maxline). 由于buffer[ maxline ] 是数组末尾之后的一个,写入buffer[ maxline ] 是数组末尾之后,因此写入存在未定义的行为。 (数组索引为 0...数组 -1 中的元素数)
【解决方案2】:

/* 更新代码。现在它工作正常。 问题出在 main() 函数和函数 getlines() 中。

#include <stdio.h>
#define MAXLINE 10
#define MINLINE 5

int getlines(char lines[], int maxline);

main()
{
    int length;
    char lines[MAXLINE];

    while ((length = getlines(lines, MAXLINE)) > 0)
    {
        if (length > MINLINE)
        {
/* As the input line can be longer than MAXLINE and in that case there will be no '\n' escape sequence to be stored in the lines[MAXLINE] array so we have used the if block to flow the control in such a way that when the input line is  longer than MAXLINE, the output string will be printed manually with a '\n' *newline character. */

            if (length > MAXLINE)
                printf("%s\n", lines);
            else
                printf("%s", lines);
        }
    }
    return 0;
}

int getlines(char lines[], int maxline)
{
    int i, j, c;
    i = 0;

    for (j = 0; (c = getchar()) != EOF && c != '\n'; ++j)
    {

/* In the for loop this time we didn't use the condition 'j < maxline
-1' as getchar() needs to read the whole input line no matter it's length(can be greater than MAXLINE), rather we have used the 'j < maxline -1' condition as a nested if block inside the for loop. While doing this to keep the getchar() function busy reaching the last input character no matter how long the line is we have used two variable i and j to overcome the problem in such a way that i will be used to store characters in the lines[MAXLINE] array, while j will be increased untill it reaches the end of the line. */

        if (j < maxline - 1)
        {
            i = j;
            lines[i] = c;
            ++i;
        }
    }

    if (c == '\n')
    {
        if (j < maxline - 1)
        {
            lines[i] = c;
            ++i;
            ++j;
        }
        else
            ++j;
    }

    lines[i] = '\0';

    return j;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 2019-05-18
    • 1970-01-01
    • 2011-10-28
    • 1970-01-01
    相关资源
    最近更新 更多