Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Нулевой указатель, или null, имеет значение, которое не соответствует какому-то допустимому адресу данных. Он часто используется в функциях, в противном случае возвращающих допустимые адреса, для указания на некоторую специальную ситуацию, такую как обнаружение признака конца файла или невозможность выполнения действия ожидаемым образом.
Итак, нулевой символ имеет целочисленный тип, а нулевой указатель — тип указателя. Иногда путаница возникает из-за того, что числовым представлением их обоих может оказаться значение 0. Но концептуально — это различные типы 0. Кроме того, нулевой символ, будучи символом, занимает один байт, тогда как нулевой указатель, как адрес, обычно занимает четыре байта.
Функция gets_s()
Необязательная функция gets_s() в С11, подобно fgets(), применяет аргумент для ограничения количества читаемых символов. С учетом определений из листин- та 11.9 следующий код будет считывать строку ввода в массив words, обеспечивая появление символа новой строки в числе первых 9 символов ввода:
gets_s(words, STLEN);
Ниже описаны три основных отличия этой функции от fgets().
• Функция gets s() просто выполняет чтение из стандартного ввода, поэтому она не нуждается в третьем аргументе.
• Если функция gets s() считывает символ новой строки, то отбрасывает его, а не сохраняет.
Символьные строки и строковые функции 437
• Если gets_s() прочитает максимальное количество символов, и среди них символ новой строки отсутствует, она предпринимает несколько действий. Функция устанавливает первый символ целевого массива в нулевой символ. Затем она читает и отбрасывает последующие введенные данные, пока не встретится символ новой строки или признак конца файла. Наконец, функция возвращает нулевой указатель. Она вызывает зависящую от реализации функцию “обработчика” (или же выбранную вами функцию), которая может привести к выходу из программы или прекращению ее работы.
Второе отличие означает, что до тех пор, пока строка ввода не слишком длинная, функция gets_s() ведет себя подобно gets(), благодаря чему gets() проще заменить функцией gets s(), чем fgets(). Третье отличие означает необходимость в обучении применению этой функции.
Давайте сравним приемлемость функций gets(), fgets() и gets_s(). Если строка ввода умещается в целевую область памяти, то все три функции работают успешно. Но функция fgets() включает в строку символ новой строки, поэтому может возникнуть необходимость в коде для его замены нулевым символом.
А что происходит, если длина строки ввода превышает заданный размер? Тогда использование функции gets() будет небезопасным — могут быть повреждены данные и нарушена безопасность. Функция gets_s() безопасна, но если вы не хотите, чтобы программа прекратила работу или выполнила выход каким-нибудь способом, придется подумать над тем, как написать и зарегистрировать специальные “обработчики”. Кроме того, если все же удается сохранить программу в работоспособном состоянии, функция gets_s() отбросит остальную часть строки ввода независимо от вашего желания. В случае, когда строка не умещается в заданную область памяти, с функцией fgets() иметь дело проще, чем с двумя другими функциями, и она предоставляет больше возможных вариантов. Если нужно, чтобы программа обработала остальную часть строки ввода, это можно сделать, как показано в листинге 11.8. Если же требуется, чтобы программа обработала остальную часть строки ввода, это также возможно, как видно в листинге 11.9.
Таким образом, когда ввод не соответствует ожиданиям, функция gets s() является менее удобной и гибкой по сравнению с fgets(). Вероятно, это одна из причин, по которой функция gets s() представляет собой лишь необязательное расширение библиотеки С. И с учетом необязательности gets_s() обычно лучшим выбором будет функция fgets().
Функция s _ gets ()
В листинге 11.9 представлен один из способов применения функции fgets(): чтение всей строки и замена символа новой строки нулевым символом либо чтение части строки, умещающейся в заданную область памяти, и отбрасывание остальных символов — т.е. своего рода разновидность функции gets s(), но без дополнительных препятствий. Ни одна из стандартных функций не удовлетворяет этому описанию, но мы можем создать такую функцию самостоятельно. Она пригодится в будущих примерах. В листинге 11.10 демонстрируется один из подходов.
Листинг 11.10. Функция s_gets()
438 глава 11
В то время как функция fgets() возвращает NULL, указывая на конец файла или ошибку чтения, функция s_gets() пропускает обработку остальных данных. В противном случае она имитирует работу программы из листинга 11.9, заменяя в строке символ новой строки нулевым символом, если названный символ присутствует, и отбрасывая остальную часть строки в противоположной ситуации. Затем она возвращает то же самое значение, что и fgets(). Мы будем использовать эту функцию в последующих примерах.
Возможно, вас интересует, в чем смысл отбрасывания остальной части слишком длинной строки. Проблема в том, что если остальную часть строки оставить, она становится входными данными для следующего оператора чтения. Это может, например, вызвать аварийное завершение программы, если следующий оператор чтения ожидает значение типа double. Отбрасывание остальной части строки поддерживает операторы чтения в состоянии синхронизации с вводом с клавиатуры.
Наша функция s_gets() не идеальна. Наиболее серьезный ее недостаток в том, что она молча отбрасывает лишние входных данных, не ставя об этом в известность ни программу, ни пользователя, и тем самым лишая его других возможностей, таких как повторение ввода или нахождение большего объема памяти. Еще один недостаток — отсутствие мер на случай неправильного применения вроде передачи размера, равного 1 или меньше. Тем не менее, эта функция вполне может служить заменой функции gets() в наших примерах.
Функция scanf()
Давайте снова возвратимся к функции scanf(). Ранее для чтения строки мы использовали функцию scanf() с форматом %s. Основное отличие между функциями scanf() и fgets() связано с тем, как они определяют момент достижения конца строки: функция scanf() больше ориентирована на “получение слова”, а не на “получение строки”. Функция gets(), как вы уже видели, принимает все символы вплоть до первого символа новой строки, как это делает fgets(), если строка является достаточно короткой.
Функция scanf() располагает двумя возможностями для прекращения ввода. При любом варианте строка начинается с первого встреченного непробелыюго символа. Если задан формат %s, строка продолжается до следующего (не включая его) пробель ного символа (символа пробела, табуляции или новой строки). Если указана ширина поля, как в %10s, функция scanf() читает до получения 10 символов или до появления первого пробельного символа, в зависимости от того, что произойдет раньше (рис. 11.3).
Читать дальшеИнтервал:
Закладка: