Почему мы используем дополнительное выражение? - PullRequest
1 голос
/ 16 сентября 2008

Вот пример из «Языка программирования C» Кернигана и Ричи:

int getline(char s[], int lim)
{
   int c, i = 0;

   while (--lim > 0; && (c=getchar()) !=EOF && c !='\n')
   {
      s[i++] = c;
   }

   if (c =='\n') 
   {
      s[i++] = c;
   }

   s[i] = '\0';

   return i;
}

Почему мы должны проверять, если c != '\n', несмотря на то, что мы используем s[i++] = c после этого?

Ответы [ 8 ]

3 голосов
/ 16 сентября 2008

Функции читают символы из стандартного ввода до тех пор, пока не будут найдены символы EOF или символы новой строки.

Вторая проверка гарантирует, что единственный символ новой строки будет помещен в массив char. EOF не должен встречаться в правильной c-строке. Кроме того, если символ не является новой строкой, это означает, что мы могли бы заполнить нашу c-строку, и в этом случае мы не должны помещать в нее больше символов.

Обратите внимание, мы все еще добавляем '\ 0'. Мы позаботились о том, чтобы в нашей c-строке оставалось место для еще одного символа, поскольку мы используем декремент до исправления, который оценивается перед сравнением.

1 голос
/ 17 сентября 2008

В коде есть ошибка.

Если размер s равен N байтам, а пользователь вводит новую строку в качестве (N-1) -го символа, N-й символ становится символом '\ n' и (N + 1) -ым символом (который выделено) станет '\ 0'.

1 голос
/ 16 сентября 2008

Сравнение заключается в том, что readline завершается, когда встречается символ новой строки ('\ n'). На той итерации, где она выполняется, она завершается без добавления новой строки в строку, поэтому оператор после этого гарантирует, что строка всегда завершается новой строкой, даже если выполнено одно из других условий завершения.

0 голосов
/ 16 сентября 2008

Не отвечаю на ваш вопрос, но все равно напишу несколько комментариев:

Я не помню все правила K & R, но функция, которую вы перечислили, потерпит неудачу, если lim равен единице. Тогда вы не будете запускать цикл, который оставляет c незапущенным, но вы все равно будете использовать переменную в проверке if (c == '\ n').

Кроме того, while (--lm> 0; ...) не проходит через компилятор. Удалить ';' и это делает.

0 голосов
/ 16 сентября 2008

Я не уверен, понимаю ли я вопрос. c !='\n' используется для прекращения чтения строки, когда происходит конец строки (перевод строки). В противном случае мы всегда будем читать его до предела, даже если он заканчивается раньше. Первый s[i++] = c; в цикле while не появляется, если достигнут перевод строки. Вот почему после этого есть специальный тест, а другой s[i++] = c; на случай, если это был перевод строки, который нарушил цикл.

0 голосов
/ 16 сентября 2008
int getline(char s[], int lim)
{
   int c, i;
   i=0;
   /* While staying withing limit and there is a char in stdin and it's not new line sign */
   while (--lim > 0; && (c=getchar()) !=EOF && c !='\n')
   /* Store char at the current position in array, advance current pos by one */
      s[i++] = c;
   /* If While loop stopped on new-line, store it in array, advance current pos by one */
   if (c =='\n') 
      s[i++] = c;
   /* finally terminate string with \0 */
   s[i] = '\0';
   return i;
}
0 голосов
/ 16 сентября 2008

Это гарантирует, что вы остановитесь в конце строки, даже если это не конец ввода. Затем, если есть новая строка, \ n добавляется в конец строки, и я увеличиваю ее еще раз, чтобы избежать перезаписи \ 0.

0 голосов
/ 16 сентября 2008

Вы делаете это только для выхода из цикла while на новой строке. В противном случае вам придется проверить это в то время как тело и использовать перерыв.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...