Код раздела 1.9 K&R для сохранения самой длинной строки ввода имеет функцию:

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] = c;
    return i;
}

Тем не менее, для лучшей практики я узнал, что функция выполняет только одно действие. Я считаю, что эта функция копирует строку из своего ввода в массив символов s И возвращает длину. Разве это не считается двумя вещами? Прав ли я в своем предположении, что это плохая практика?

Чтобы уточнить, мы действительно используем ввод от функции getLine, но очень неинтуитивно.

main() 
{
    int len;    /*current line length*/
    int max;    /*Current max line 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;
}


/*FUNCTION GETLINE TAKEN OUT */


/*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;

}
1
user275564 24 Окт 2014 в 23:59
2
Даже если вы считаете чтение строки текста и возврат ее длины двумя отдельными вещами, я бы сказал, что разделение ее только ради хорошей практики было бы очень непрактичным.
 – 
j_kubik
25 Окт 2014 в 00:03
Я спрашиваю, считаете ли вы, что функция выполняет две функции, и если да, то нецелесообразно ли иметь хорошую практику в C? Или, возможно, C является исключением из правил?
 – 
user275564
25 Окт 2014 в 00:13
printf печатает строку и возвращает количество записанных ею символов. Пока этот getline уже ведет подсчет длины строки, почему бы не вернуть его в результате? Он даже возвращает 0 для "нет ввода".
 – 
Jongware
25 Окт 2014 в 00:17
Для меня это сбивает с толку делать два дела одновременно. Я бы предпочел создать функцию, которая захватывает ввод и копирует его в массив символов, а другую функцию возвращает его длину. Я просто должен понять, это только я или это действительно лучшая идея.
 – 
user275564
25 Окт 2014 в 00:25
Нет ли пары ошибок в вашем "примере использования"? Зачем тестировать > 80? max никогда не обновляется; конечно, отступ if вводит в заблуждение или ему нужны фигурные скобки?
 – 
Jongware
25 Окт 2014 в 00:34

3 ответа

Лучший ответ

Нет, по двум причинам.

Во-первых, можно утверждать, что цель getline (как следует из названия) - прочитать строку из ввода. Тот факт, что он также возвращает количество прочитанных символов, можно объяснить тем, как работают C-строки, и что в противном случае функция не могла бы использоваться для чтения данных, содержащих нулевые байты.

Во-вторых, функция не содержит дополнительного кода для вычисления длины. Это побочный продукт чтения строки. В противном случае функция имела бы тип void, поэтому на самом деле нет никаких недостатков в возврате длины строки.

Кроме того, рекомендации по кодированию не являются самоцелью, но должны помочь в создании хорошего кода. Я не вижу, как этот код можно улучшить, опустив оператор return и написав отдельную функцию O (n) для получения длины.

2
wonce 25 Окт 2014 в 00:29

Функция getline() не выполняет двух разных действий. Он выполняет две очень тесно связанные вещи, и это определенно неплохая практика, когда он возвращает длину строки.

Не пытайтесь слепо вписывать функции, алгоритмы и другие подобные вещи в схемы. То, что делает getline(), концептуально правильно, поскольку строка является объектом. Она имеет буфер содержимого и длины. Оба «свойства» принадлежат строковому объекту, и на самом деле я считаю плохой практикой разделять их.

Кроме того, было бы излишне сложно (и неэффективно) иметь еще одну функцию, вычисляющую длину строки. В C строки заканчиваются нулем, и поэтому такая функция должна пройти всю строку, чтобы найти ее длину.

(Не говоря уже о том, что такая функция уже есть в стандартной библиотеке C, она называется strlen().)

2
The Paramagnetic Croissant 25 Окт 2014 в 00:29
Спасибо, это то, что мне нужно было знать.
 – 
user275564
25 Окт 2014 в 00:46

Часто для строк и массивов в целом это не исключение, а на самом деле очень полезное поведение. В некотором смысле массивы обладают неявным свойством длины. Иногда это известно во время компиляции, иногда это известно во время выполнения и сохраняется в переменной, а иногда это может быть определено только на основании того, что это массив с завершающим нулем.

В любом случае, поскольку нельзя вернуть массив по значению, возвращение длины массива (которое часто очень удобно знать) является очень полезным свойством функций, которые записывают массив в буфер. Я могу даже утверждать, что это идиоматично в C, когда длина записанного массива не может быть известна вызывающему.

ДОБАВЛЕНИЕ: Вышеупомянутый ответ относится к функциям, которые не выделяют память, а только записывают в предоставленный буфер. Иногда бывает полезно вернуть простую структуру struct { size_t size; valtype* vals; }, если знание размера выделенного массива всегда полезно для вызывающей стороны и вы не хотите позже перебирать массив. Проведя параллели с вашим вопросом, вы поймете, почему в некотором смысле он на самом деле не делает двух вещей; это просто дает вам более полный результат.

1
Luis 25 Окт 2014 в 00:32