2013-08-20 2 views
2

Вот что-то похожее на ошибку, но я смущен тем, что мое наблюдение не появляется нигде в Интернете, учитывая возраст и популярность книги. Или, может быть, я просто плохо разбираюсь, или это совсем не ошибка.Ошибка в выпуске K & R второго издания?

Я говорю о программе «распечатать самую длинную строку ввода» из первой главы. Вот код:

#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; 
} 

Теперь, мне кажется, что это должно быть lim-2 в отличие от lim-1 в течение состояния GetLine. В противном случае, когда ввод точно соответствует максимальной длине, то есть 999 символов, за которыми следует '\n', getline будет индексироваться в s[MAXLINE], что выходит за рамки, а также при возникновении копии могут произойти всевозможные ужасные вещи, а from[] не заканчивается a '\0'.

ответ

8

Я думаю, вы где-то смущены. Это условие цикла:

for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i) 

Обеспечивает i никогда больше lim - 2, так что в случае максимальной длиной, i является lim-1 после выхода цикла и нулевой символ хранится в эту последнюю позицию.

+0

Хорошо, спасибо. ОДНАКО, просто для упрощения примеров, установите MAXLINE на 3, а не на 1000. Для ввода aa программа будет печатать как самую длинную строку. – timgeb

+0

Это потому, что обе эти линии имеют одинаковую длину. В тесте есть '>', а не '> =', чтобы перезаписать 'longest'. –

+0

Почему для aa \ n нужно иметь такую ​​же длину, как \ n для MAXLINE == 3? – timgeb

2

В случае 999 символов, отличных от \ n, за которыми следует a \ n, c никогда не равно \ n. Когда цикл for выходит, c равно последнему символу, отличному от новой строки.

Так что c! = '\ N' и не вводит блок, который делает i ++, поэтому я никогда не выхожу за пределы.

+0

Да, я не учитывал оценку короткого замыкания для условия. – timgeb

1

Когда вход имеет длину 999 и сопровождается \n, значение предела 1000 и значение lim -1 будет 999 и испытание на цикл условие i < lim -1 станет ложным, когда i становится 998. Для i < 999, c == \n никогда не будет истинным, и поэтому массив s будет проиндексирован на s[999], а не s[1000]

Смежные вопросы