Преподает ли K & R плохую читабельность? - PullRequest
2 голосов
/ 16 октября 2010

Прошло много времени с тех пор, как я посмотрел на C (все еще учусь), и я только вернулся к книге K & R.

Я только что приступил к Упражнению 5-3 (p107).

Напишите версию указателя функции strcat, которую мы показали в главе 2: strcat (s, t) копирует строку t в конец s.

Я придумал этот ...

void strcat(char *s, char *t);

void strcat(char *s, char *t) {

    while (*s++ != '\0');
    s--;
    while (*t != '\0') {
        *s++ = *t++;
    }

    *--t = '\0';

}

int main() {
   char str[] = "Hey, hello";
   char str2[] = " are you?";

   strcat(str, str2);

   printf("%s\n", str);

   return 0;

}

Кажется, это работает.

Что мне интересно, так это то, что книга K & R часто пишет упражнения скак можно меньше строчек - я бы ожидал, если бы они предоставили свой собственный пример кода выше, вы получите такие вещи, как this ...

void strcat(char *s, char *t) {

    while (*s++ != '\0');
    s--;
    while ((*s++ = *t++) != '\0');
    *--t = '\0';

}

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

Является ли книга правильной, пытаясь сделать как можно большегде вы можете, даже если читаемость страдает?

Это просто Путь C ?

Ответы [ 3 ]

13 голосов
/ 16 октября 2010

K & R объясняют важность идиом в книге.Да, краткость кода ценится программистами на Си, но это не намеренно кратко наказывать новичков.После некоторого времени чтения и записи C вы начинаете распознавать шаблоны, поэтому, когда вы видите их в чужом коде, вы знаете, на что вы смотрите.K & R - они объясняют свою философию краткости против ясности и говорят об идиомах.

5 голосов
/ 16 октября 2010

Вы не должны ожидать, что ваша программа будет работать, так как вы вызываете неопределенное поведение .

Вы определяете два буфера определенного размера (str имеет длину 11 байт, str2 длиной 10 байт).Затем, во время strcat, вы пытаетесь записать в str[11], которого не существует.С этого момента нет никаких гарантий относительно выполнения вашей программы.Это может произойти сбой, он может сделать то, что вы ожидали, или он может просто напечатать «42» и заставить вас задуматься, почему.C t имеет тип const char *.

И в-третьих, при повторной реализации функции, также предоставляемой вашей средой, присвойте ей другое имя.В противном случае ваш компилятор может заменить его некоторым встроенным кодом, эквивалентным вызову функции.Например, GCC имеет __builtin_strlen, который иногда заменяет вызовы на strlen.

Фиксированная версия кода выглядит следующим образом:

#include <stdio.h>

/* renamed strcat to str_cat to avoid confusing the compiler */
void str_cat(char *s, const char *t) { /* added the const qualifier to t */

    while (*s++ != '\0');
    s--;
    while (*t != '\0') {
        *s++ = *t++;
    }
    /* removed the needless modification of *t */
    *s = '\0'; /* edit: added this line after the comment from Jonathan Leffler */
}

int main() {
   char str[80] = "Hey, hello"; /* note the large array size here */
   char str2[] = " are you?";

   str_cat(str, str2);
   printf("%s\n", str);

   return 0;

}
0 голосов
/ 17 октября 2010

Другие более удобочитаемые, более эффективные примеры можно найти с помощью Google Codesearch .

Посмотрите на исходный код для Android и BSD, в частности, как на хорошие примеры более современной реализации на C strcat.

Вместо strcat вы должны написать реализацию strlcat и , также можно найти множество примеров этого источника.

...