Linux программирование в примерах
Регулярные выражения являются важной частью Unix. Чтобы научиться заменять, вырезать и распределять текст с использованием регулярных выражений, мы рекомендуем эту книгу
7. Руководство для GNU
также объясняет регулярные выражения. На системе GNU/Linux для просмотра локальной копии вы можете использовать 'grep'. Или использовать браузер для прочтения онлайн-документации проекта GNU дляinfo grep. [135]grep12.10. Резюме
• Операторы проверки предоставляют способ сделать утверждения о предполагаемом состоянии программы. Они являются полезным инструментом для проектирования и отладки и обычно должны оставаться в коде изделия. Однако, будьте внимательны, чтобы не перепутать операторы проверки с проверками возможных ошибок времени исполнения.
• Функции
являются аналогичными более известным функциямmem<i>XXX</i>(). Самой большой их ценностью является то. что они могут работать с двоичными данными; нулевые байты не отличаются от других байтов. Больше известнаstr<i>XXX</i>()противmemcpy(), обрабатывающей перекрывающиеся копии.memmove()• Временные файлы полезны во многих приложениях. Функции API
иtmpfile()являются предпочтительными способами создания временных файлов, в то же время позволяя избежать состояния гонки и связанных с ней проблем безопасности. Многие программы для указания местоположения своих временных файлов используют переменную окруженияmkstemp(), а если она не определена, приемлемое значение по умолчанию (обычноTMPDIR). Это хорошее соглашение, которое следует принять на вооружение в своих программах./tmp• Функция
посылает вызывающему процессу сигналabort(). Результатом является завершение процесса и создание дампа ядра, предположительно для отладки.SIGABRT•
иsetjmp()обеспечивают нелокальный переход. Это мощная возможность, которая должна использоваться с осторожностью.longjmp()иsigsetjmp()сохраняют и восстанавливают маску сигналов процесса, когда программа осуществляет нелокальный переход. Проблемы с нелокальными переходами иногда перевешивают их преимущества, соответственно используйте эти процедуры лишь когда нет лучшего способа структурировать ваше приложение.siglongjmp()• Случайные числа полезны для множества приложений. Большинство программ используют псевдослучайные числа — последовательности номеров, которые кажутся случайными, но которые могут быть воспроизведены с помощью одного и того же начального значения.
иrand()являются первоначальными функциями API, стандартизованными языком С. На многих системахsrand()использует низкокачественный алгоритм,rand()иrandom()используют лучший алгоритм, включены в стандарт POSIX и являются предпочтительными по сравнению сsrandom()иrand(). Используйте специальные файлыsrand()и/dev/random, если (а) они доступны и (б) если вам нужны случайные числа высокого качества./dev/urandom• Три функции API предоставляют все более мощные возможности для развертывания метасимволов (подстановки символов).
•
является простейшей, возвращающей true/false, если данная строка соответствует или не соответствует шаблону символов подстановки оболочки.fnmatch()•
просматривает файловую систему, возвращая список путей, которые соответствуют данному шаблону. Когда требуются стандартные возможностиglob(), следует использовать эту функцию. Хотя GLIBC версияglob()имеет некоторые расширения, переносимые программы, которым нужны дополнительные возможности, должны вместо этого использоватьglob(). (Программы, которые будут работать лишь на системах GNU/Linux, не должны стесняться использовать полную мощь GLIBCwordexp().)glob()•
не только делает то, что делаетwordexp(), но также выполняет полное развертывание слов в стиле оболочки, включая развертывание тильды, развертывание переменных оболочки и подстановку команд.glob()• Функции
иregcomp()обеспечивают доступ к базовым и расширенным регулярным выражениям POSIX. Используя одну из этих функций, можно заставить свою программу вести себя идентично со стандартными утилитами, значительно упрощая использование программы пользователями, знакомыми с GNU/Linux и Unix.regexec()Упражнения
1. Используйте
иread()для написания простой версии программыmemcmp(), которая сравнивает два файла. Вашей версии не нужно поддерживать какие-нибудь опции.cmp2. Используйте макрос
и прямое сравнение каждого прочитанного символа для написания другой версии<stdio.h> getc(), которая сравнивает два файла. Сравните производительность этой версии с производительностью написанной в предыдущем упражнении.cmp3. (Средней трудности) Рассмотрите функции
и GLIBC<stdio.h> fgets(). Полезна лиgetline()для их реализации? Набросайте с ее использованием возможную реализациюmemcpy().fgets()4. (Трудное) Найдите исходный код GLIBC версии
. Он должен быть на одном из CD-ROM с исходным кодом в вашем дистрибутиве GNU/Linux, или же вы можете найти его в сети. Исследуйте код и объясните его.memcmp()5. Проверьте свою память. Как
организует удаление файла, когда закрыт указатель файла?tmpfile()6. Используя
иmkstemp(), а также другие необходимые функции или системные вызовы, напишите свою версиюfdopen(). Протестируйте ее тоже.tmpfile()7. Опишите преимущества и недостатки использования
для имени файла, созданногоunlink(), непосредственно после возвращенияmkstemp().mkstemp()8. Напишите свою версию
, используяmkstemp()иmktemp(). Как вы можете обеспечить те же гарантии уникальности, которые обеспечиваетopen()?mkstemp()