Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Рис. 11.4. Функция puts() и нулевой символ
Заголовочный файл string.h содержит прототипы для семейства строковых функций С, поэтому он и был включен в данном примере.
На заметку!
В некоторых системах, существовавших до выхода стандарта ANSI, вместо string.h используется заголовочный файл strings.h, а в ряде систем такой заголовочный файл вообще отсутствует.
Функция strcat()
Функция strcat() (от string concatenation — конкатенация строк) в качестве аргументов принимает две строки. Копия второй строки присоединяется в конец первой строки, и такая объединенная версия становится новой первой строкой. Вторая строка не изменяется. Функция strcat() имеет тип char * (т.е. указатель на char). Она возвращает значение своего первого аргумента — адрес первого символа строки, в конец которой была добавлена вторая строка.
В листинге 11.18 демонстрируются возможности функции strcat(). В коде также применяется функция s_gets(), которая была определена в листинге 11.10; вспомните, что s_gets() использует fgets() для чтения строки, а затем удаляет из нее символ новой строки, если он присутствует.
Символьные строки и строковые функции 447
Получаем следующие выходные данные:
Какой у вас любимый цветок?
Анемон
Анемон пахнет как старые валенки, пахнет как старые валенки.
Программа завершена.
В выводе видно, что строка flower изменилась, а строка addon — нет.
функция strncat()
Функция strcat() не проверяет, умещается ли вторая строка в первый массив. Если вы не выделите достаточного пространства для первого массива, то столкнетесь с проблемой переполнения соседних ячеек памяти избыточными символами.
448 глава 11
Конечно, можно заранее проверить длину с помощью strlen(), как показано в листинге 11.15. Обратите внимание, что эта функция добавляет 1 к общей длине, резервируя место для нулевого символа. В качестве альтернативы можно воспользоваться функцией strncat(), которая принимает второй аргумент, указывающий максимальное количество добавляемых символов. Например, вызов strncat (bugs, addon, 13) добавляет содержимое строки addon к bugs, останавливаясь после прохода 13 дополнительных символов или при обнаружении нулевого символа, в зависимости от того, что случится раньше. Следовательно, учитывая нулевой символ (который добавляется в любом случае), массив bugs должен иметь размер, достаточный для хранения исходной строки (без нулевого символа), максимум 13 дополнительных символов и завершающего нулевого символа. В листинге 11.19 эта информация применяется для вычисления значения переменной available, которая служит максимальным разрешенным количеством дополнительных символов.
Листинг 11.19. Программа joinchk.c
Символьные строки и строковые функции 449
Вот результаты выполнения этой учебной программы:
Какой у вас любимый цветок?
Роза
Роза пахнет как старые валенки.
Какое у вас любимое насекомое?
Комар
Комар пахнет
Вы уже могли заметить, что функция strcat(), как и gets(), может приводить к переполнению буфера. Почему же тогда в стандарте С11 не отказались от strcat(), а лишь предложили функцию strncat() ? Одной из причин может быть то, что функция gets() подвергает программу опасности со стороны тех, кто ее использует, в то время как strcat() подвергает программу опасности вследствие невнимательности программиста. Будущее поведение того или иного пользователя предвидеть невозможно, но можно контролировать то, что происходит внутри программы. Философия доверия программисту, принятая в С, возлагает на вас ответственность за определение ситуаций, в которых функция strcat() может применяться безопасным образом.
ФУНКЦИЯ strcmp()
Предположим, что требуется сравнить введенный кем-то ответ со строкой, хранящейся в памяти, как показано в листинге 11.20.
Листинг 11.20. Программа nogo.с
450 глава 11
Как бы симпатично не выглядела эта программа, работает она некорректно. В действительности ANSWER и try являются указателями, так что сравнение try != ANSWER не проверяет, совпадают ли две строки. Вместо этого оно проверяет, имеют ли указанные две строки один и тот же адрес. Поскольку ANSWER и try хранятся в разных ячейках памяти, их адреса никогда не будут совпадать, и пользователь каждый раз получает сообщение о том, что введенный им ответ неправилен. Такие программы часто сбивают пользователей с толку.
Нам необходима функция, которая сравнивает содержимое строк, а не их адреса. Можно было бы создать такую функцию самостоятельно, но функция подобного рода уже имеется — strcmp() (от string comparison — сравнение строк). Эта функция делает для строк то же, что операции отношений делают для чисел. В частности, она возвращает 0, если оба строковых аргумента одинаковы, и ненулевое значение в противном случае. В листинге 11.21 приведена переделанная программа.
Листинг 11.21. Программа compare.с
Символьные строки и строковые функции 451
На заметку!
Поскольку любое ненулевое значение трактуется как истинное, опытные программисты на С
наверняка сократят этот оператор while до while (strcmp (try, ANSWER)).
Одно из примечательных свойств функции strcmp() заключается в том, что она сравнивает строки, а не массивы. Хотя массив try занимает 40 ячеек памяти, а строка "Грант" — только шесть (одна ячейка отводится под нулевой символ), при сравнении просматривается только часть массива try до первого встреченного нулевого символа. Следовательно, strcmp() может использоваться для сравнения строк, хранящихся в массивах разных размеров.
А что, если пользователь введет в качестве ответа "ГРАНТ", "грант" или "Улисс С. Грант"? Программа сообщит о том, что ответ неправильный. Чтобы сделать программу более дружественной, необходимо предусмотреть все возможные правильные ответы. Для этого есть несколько приемов. Например, с помощью директивы #define можно определить ответ как "ГРАНТ" и написать функцию, которая преобразует все введенные буквы в прописные. Это устраняет проблему употребления прописных букв, но по-прежнему остаются другие формы ответа, о которых следует позаботиться, а также учесть тот факт, что жена Гранта, Джулия, также похоронена в той же могиле. Мы оставляем эти задачи в качестве упражнений для самостоятельной проработки.
Возвращаемое значение функции strcmp()
Читать дальшеИнтервал:
Закладка: