Почему эта C линия печати программы длиннее, чем MAXLINE? - PullRequest
0 голосов
/ 04 апреля 2020

Программа должна распечатать все входные строки, длина которых превышает 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, а иногда печатает те, которые пропускают некоторые завершающие символы.

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Для начала эта функция

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' в позиции maxline, которая находится вне массива lines, который имеет действительный диапазон индексов [0, maxline).

Что касается вашего вопроса о выводе, то если вы ввели текст, который больше maxline, то функция вернет строку, которая не содержит символ новой строки '\n'. Поэтому следующая строка будет выведена в той же строке.

0 голосов
/ 09 апреля 2020

/ * Обновлен код. Сейчас работает нормально. Проблемы были как в функции 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;
}
...