Как здесь работает функция getline()?

Я не понимаю, как здесь работает функция getline. Почему символ новой строки был исключен из цикла for и почему он проверяет наличие символа новой строки в отдельном блоке?

#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */

int getline(char line[], int maxline);
void copy(char to[], char from[]);

/* print the longest input line */
main()
{
    int len; /* current line length */
    int max; /* maximum length seen so far */
    char line[MAXLINE]; /* current input line */
    char longest[MAXLINE]; /* longest line saved here */
    max = 0;
    while ((len = getline(line, MAXLINE)) > 0)
        if (len > max) {
            max = len;
            copy(longest, line);
        }
    if (max > 0) /* there was a line */
        printf("%s", longest);
    return 0;
}


/* getline: read a line into s, return length */
int getline(char s[],int lim)
{
    int c, i;
    for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
        s[i] = c;
    if (c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}


/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
    int i;
    i = 0;
    while ((to[i] = from[i]) != '\0')
        ++i;
}

person chanzerre    schedule 16.08.2013    source источник


Ответы (4)


getline прочитает одну строку из stdin. Поскольку строки разделены символами новой строки ('\n' символов), getline будет читаться до новой строки включительно. Для getline не имеет смысла читать дальше новой строки, потому что тогда будет читаться более одной строки.

Есть три случая, которые могут привести к остановке цикла for.

1) был обнаружен \'n'.
Если это произойдет, новая строка будет добавлена ​​в конец текущей строки перед добавлением завершающего нуля. Для этого и нужен if (c == '\n').

2) EOF читается или 3) считывается максимальное количество символов, которые нужно прочитать.
Если происходит одно из этих событий , добавление новой строки в конец строки пропускается и добавляется только завершающий нуль.

Завершающий нуль (символ '\0') — это то, как C указывает конец строки.

person Ryan Haining    schedule 16.08.2013
comment
понял. это было довольно просто, я полагаю. - person chanzerre; 17.08.2013

Причина, по которой они исключают \n из цикла, а затем проверяют наличие \n, заключается в том, что значение c все еще выделяется (все еще находится в области видимости) после завершения цикла for. одна из причин, по которой это кажется немного сложным, заключается в том, что они решили исключить скобки. Поскольку функция состоит в том, чтобы получить следующую строку, строка «заканчивается», когда вы получаете символ новой строки «\n». Чтобы написать это так, чтобы это было немного более читабельно, это выглядело бы так:

int getline(char s[],int lim)
{
    int c,
    int i;
    for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i) {
        s[i] = c;
    }
    if (c == '\n') {
        s[i] = c;
        ++i;
    }
    s[i] = '\0';
    return i;
}
person rahul0705    schedule 16.08.2013

Есть три важных случая, которые следует учитывать при чтении до конца строки. Те, кто:

  1. Мы достигли максимально допустимого количества байтов в нашем буфере.
  2. Мы достигли EOF и, следовательно, больше нечего читать.
  3. Мы достигли конца строки и должны прекратить чтение дальше.

В цикле for следующее:

  • i < ( lim - 1 ) проверяет случай 1.
  • ( c = getchar() ) != EOF проверяет случай 2 (уродливый).
  • c != '\n' проверяет случай 3.

... причина, по которой он должен замыкаться при чтении новой строки, заключается в том, что это является целью функции. Он также считывает символ новой строки и включает его в строку. Последний шаг:

s[ i ] = '\0';

... гарантирует, что это строка с NULL завершением (соглашение в C). Затем он возвращает количество прочитанных байтов (что не редкость).

person Jacob Pollack    schedule 16.08.2013

Ну я тоже придумал этот вопрос. Вот возможный ответ на ваш вопрос.

1)Самое первое заблуждение в этом вопросе - это сам getline. В частности, в этом коде getline является определяемой пользователем функцией. Некоторые компиляторы могут выдать ошибку. Поэтому попробуйте другое имя для этой функции (может быть, getl или что-то, что вы найдете подходящим для себя)

2) Во-вторых, main() действует как посредник для принятия входной строки. Он проверяет, больше ли длина входной строки (вычисленной функцией getline() ) нуля и макс.

3) Функция копирования копирует значение самой длинной строки в самом длинном массиве символов.

Во время печати код говорит: printf("%s",longest); Теперь возникает вопрос. Почему бы не использовать цикл for для печати строки. Что ж, это тоже правильно, но потребует больше шагов и итераций, что неэффективно.

Это то, что я придумал.

person Satyendra Yadav    schedule 24.12.2016