Выбрать главу

Вот и все! Скромная, но тем не менее полезная версия grep в 130 строк кода.

12.9. Рекомендуемая литература

1. Programming Pearls, 2nd edition, by Jon Louis Bentley Addison-Wesley, Reading, Massachusetts, USA, 2000. ISBN- 0-201-65788-0. См. также веб-сайт этой книги.[131]

Проектирование программы с операторами проверки является одной из главных тем в этой книге.

2. Building Secure Software How to Avoid Security Problems the Right Way, by John Viega and Gary McGraw Addison-Wesley, Reading, Massachusetts, USA, 2001. ISBN: 0-201-72152-X.

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

3. The Art of Computer Programming. Volume 2. Seminumerical Algorithms, 3rd edition, by Donald E. Knuth Addison-Wesley, Reading, Massachusetts, USA, 1998. ISBN- 0-201-89684-2.[132] См также веб-сайт этой книги.[133]

Это классическое справочное руководство по генерации случайных чисел.

4. Random Number Generation and Monte Carlo Methods, 2nd edition, by James E. Gentle Springer-Verlag, Berlin, Germany. 2003. ISBN: 0-387-00178-6.

Данная книга широко освещает методы генерации и тестирования псевдослучайных чисел. Хотя для неё также требуется математическая и статистическая подготовка, уровень не такой высокий, как в книге Кнута. (Благодарим Nelson H.F. Beebe за указание этой ссылки.)

5. sed & awk, 2nd edition, by Dale Dougherty and Arnold Robbins. O'Reilly and Associates, Sebastopol, California, USA, 1997. ISBN: 1-56592-225-5.

Эта книга осторожно вводит в регулярные выражения и обработку текста, начиная с grep и продвигаясь к более мощным инструментам sed и awk.

6. Mastering Regular Expressions, 2nd edition, by Jeffrey E.F. Friedl. O'Reilly and Associates, Sebastopol, California, USA, 2002.[134] ISBN: 0-59600-289-0.

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

7. Руководство для GNU grep также объясняет регулярные выражения. На системе GNU/Linux для просмотра локальной копии вы можете использовать 'info grep'. Или использовать браузер для прочтения онлайн-документации проекта GNU для grep.[135]

12.10. Резюме

• Операторы проверки предоставляют способ сделать утверждения о предполагаемом состоянии программы. Они являются полезным инструментом для проектирования и отладки и обычно должны оставаться в коде изделия. Однако, будьте внимательны, чтобы не перепутать операторы проверки с проверками возможных ошибок времени исполнения.

• Функции memXXX() являются аналогичными более известным функциям strXXX(). Самой большой их ценностью является то. что они могут работать с двоичными данными; нулевые байты не отличаются от других байтов. Больше известна memcpy() против memmove(), обрабатывающей перекрывающиеся копии.

• Временные файлы полезны во многих приложениях. Функции API tmpfile() и mkstemp() являются предпочтительными способами создания временных файлов, в то же время позволяя избежать состояния гонки и связанных с ней проблем безопасности. Многие программы для указания местоположения своих временных файлов используют переменную окружения TMPDIR, а если она не определена, приемлемое значение по умолчанию (обычно /tmp). Это хорошее соглашение, которое следует принять на вооружение в своих программах.

• Функция abort() посылает вызывающему процессу сигнал SIGABRT. Результатом является завершение процесса и создание дампа ядра, предположительно для отладки.

• setjmp() и longjmp() обеспечивают нелокальный переход. Это мощная возможность, которая должна использоваться с осторожностью. sigsetjmp() и siglongjmp() сохраняют и восстанавливают маску сигналов процесса, когда программа осуществляет нелокальный переход. Проблемы с нелокальными переходами иногда перевешивают их преимущества, соответственно используйте эти процедуры лишь когда нет лучшего способа структурировать ваше приложение.

• Случайные числа полезны для множества приложений. Большинство программ используют псевдослучайные числа — последовательности номеров, которые кажутся случайными, но которые могут быть воспроизведены с помощью одного и того же начального значения. rand() и srand() являются первоначальными функциями API, стандартизованными языком С. На многих системах rand() использует низкокачественный алгоритм, random() и srandom() используют лучший алгоритм, включены в стандарт POSIX и являются предпочтительными по сравнению с rand() и srand(). Используйте специальные файлы /dev/random и /dev/urandom, если (а) они доступны и (б) если вам нужны случайные числа высокого качества.

• Три функции API предоставляют все более мощные возможности для развертывания метасимволов (подстановки символов).

  • fnmatch() является простейшей, возвращающей true/false, если данная строка соответствует или не соответствует шаблону символов подстановки оболочки.

  • glob() просматривает файловую систему, возвращая список путей, которые соответствуют данному шаблону. Когда требуются стандартные возможности glob(), следует использовать эту функцию. Хотя GLIBC версия glob() имеет некоторые расширения, переносимые программы, которым нужны дополнительные возможности, должны вместо этого использовать wordexp(). (Программы, которые будут работать лишь на системах GNU/Linux, не должны стесняться использовать полную мощь GLIBC glob().)

  • wordexp() не только делает то, что делает glob(), но также выполняет полное развертывание слов в стиле оболочки, включая развертывание тильды, развертывание переменных оболочки и подстановку команд.

• Функции regcomp() и regexec() обеспечивают доступ к базовым и расширенным регулярным выражениям POSIX. Используя одну из этих функций, можно заставить свою программу вести себя идентично со стандартными утилитами, значительно упрощая использование программы пользователями, знакомыми с GNU/Linux и Unix.

Упражнения

1. Используйте read() и memcmp() для написания простой версии программы cmp, которая сравнивает два файла. Вашей версии не нужно поддерживать какие-нибудь опции.

2. Используйте макрос <stdio.h> getc() и прямое сравнение каждого прочитанного символа для написания другой версии cmp, которая сравнивает два файла. Сравните производительность этой версии с производительностью написанной в предыдущем упражнении.

3. (Средней трудности) Рассмотрите функции <stdio.h> fgets() и GLIBC getline(). Полезна ли memcpy() для их реализации? Набросайте с ее использованием возможную реализацию fgets().

4. (Трудное) Найдите исходный код GLIBC версии memcmp(). Он должен быть на одном из CD-ROM с исходным кодом в вашем дистрибутиве GNU/Linux, или же вы можете найти его в сети. Исследуйте код и объясните его.

вернуться

131

http://www.cs.bell-labs.com/cm/cs/pearls/Примеч. автора.

вернуться

132

Русский перевод: Дональд E. Кнут. Искусство программирования. Том 2. Получисленные алгоритмы (3-е издание). Москва - Санкт-Петербург - Киев. Вильямс. 2000 — Примеч. науч. ред.

вернуться

133

http://www-cs-faculty.stanford.edu/~knuth/taocp.htmlПримеч. автора.

вернуться

134

Русский перевод — Дж. Фридл. Регулярные выражения (2-е издание). C.-Петербург, Питер, 2003 — Прим. науч. ред.

вернуться

135

http://www.gnu.org/software/grep/doc/grep.htmlПримеч. автора.