Вход/Регистрация
Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

58 {

59 --p;

60 p[-1] = '\n';

61 }

62 #endif

Строки 54–62 обрабатывают вводимые строки, следующие соглашению Microsoft по завершению строк комбинацией символов возврата каретки и перевода строки (CR-LF), а не просто символом перевода строки (новой строки), который является соглашением Linux/Unix. Обратите внимание, что

#ifdef
исключает этот код на платформе Microsoft, очевидно, библиотека
<stdio.h>
на этих системах автоматически осуществляет это преобразование. Это верно также для других не-Unix систем, поддерживающих стандартный С.

64 backslash = 0;

65 for (p2 = p - 2; p2 >= start; --p2)

66 {

67 if (*p2 != '\\')

68 break;

69 backslash = !backslash;

70 }

71

72 if (!backslash)

73 {

74 p[-1] = '\0';

75 break;

76 }

77

78 /* Это была комбинация обратный слеш/новая строка. Если есть

79 место, прочесть еще одну строку. */

80 if (end - p >= 80)

81 continue;

82

83 /* В конце буфера нужно больше места, поэтому выделить еще.

84 Позаботиться о сохранении текущего смещения в p. */

85 more_buffer:

86 {

87 unsigned long off = p - start;

88 ebuf->size *= 2;

89 start = ebuf->buffer=ebuf->bufstart=(char*)xrealloc(start,

90 ebuf->size);

91 p = start + off;

92 end = start + ebuf->size;

93 *p = '\0';

94 }

95 }

До сих пор мы имели дело с механизмом получения в буфер по крайней мере одной полной строки. Следующий участок обрабатывает случай строки с продолжением. Хотя он должен гарантировать, что конечный символ обратного слеша не является частью нескольких обратных слешей в конце строки. Код проверяет, является ли общее число таких символов четным или нечетным путем простого переключения переменной

backslash
из 0 в 1 и обратно. (Строки 64–70.)

Если число четное, условие '

!backshlash
' (строка 72) будет истинным. В этом случае конечный символ конца строки замещается байтом NUL, и код выходит из цикла.

С другой стороны, если число нечетно, строка содержит четное число пар обратных слешей (представляющих символы \\, как в С), и конечную комбинацию символов обратного слеша и конца строки. [43] В этом случае, если в буфере остались по крайней мере 80 свободных байтов, программа продолжает чтение в цикле следующей строки (строки 78–81). (Использование магического числа 80 не очень здорово; было бы лучше определить и использовать макроподстановку.)

43

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

По достижении строки 83 программе нужно больше места в буфере. Именно здесь вступает в игру динамическое управление памятью. Обратите внимание на комментарий относительно сохранения значения

p
(строки 83-84); мы обсуждали это ранее в терминах повторной инициализации указателей для динамической памяти. Значение end также устанавливается повторно. Строка 89 изменяет размер памяти.

Обратите внимание, что здесь вызывается функция

xrealloc
. Многие программы GNU используют вместо
malloc
и
realloc
функции-оболочки, которые автоматически выводят сообщение об ошибке и завершают программу, когда стандартные процедуры возвращают
NULL
. Такая функция-оболочка может выглядеть таким образом:

extern const char *myname; /* установлено в main */

void *xrealloc(void *ptr, size_t amount) {

 void *p = realloc(ptr, amount);

 if (p == NULL) {

fprintf(stderr, "%s: out of memory!\n", myname);

exit(1);

 }

 return p;

}

Таким образом, если функция

xrealloc
возвращается, она гарантированно возвращает действительный указатель. (Эта стратегия соответствует принципу «проверки каждого вызова на ошибки», избегая в то же время беспорядка в коде, который происходит при таких проверках с непосредственным использованием стандартных процедур.) Вдобавок, это позволяет эффективно использовать конструкцию '
ptr = xrealloc(ptr, new_size)
', против которой мы предостерегали ранее.

Обратите внимание, что не всегда подходит использование такой оболочки. Если вы сами хотите обработать ошибки, не следует использовать оболочку. С другой стороны, если нехватка памяти всегда является фатальной ошибкой, такая оболочка вполне удобна.

97 if (ferror(ebuf->fp))

98 pfatal_with_name(ebuf->floc.filenm);

99

100 /* Если обнаружено несколько строк, возвратить их число.

101 Если не несколько, но _что-то_ нашли, значит, прочитана

  • Читать дальше
  • 1
  • ...
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: