Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Листинг 14.8. Программа names1.с
584 Глава 14
Компиляция и запуск программы генерирует следующие результаты:
Введите свое имя.
Васисуалий
Введите свою фамилию.
Лоханкин
Васисуалий Лоханкин, ваше имя и фамилия содержат 18 букв.
Работа программы распределена между тремя функциями, вызываемыми в main(). В каждом случае функции передается адрес структуры person.
Функция getinfo() передает информацию изнутри себя в main(). В частности, она получает имена от пользователя и помещает их в структуру person, применяя для доступа к ней указатель pst. Вспомните, что pst->lname означает член lname структуры, на которую указывает pst. Это делает pst->lname эквивалентом имени массива значений char и, следовательно, подходящим аргументом для функции gets(). Обратите внимание, что хотя функция getinfo() снабжает информацией главную программу, она не использует для этого механизм возврата, поэтому имеет тип void.
Функция makeinfo() выполняет двустороннюю передачу информации. С применением указателя на person она находит имя и фамилию, хранящиеся в этой структуре. Она использует функцию strlen() из библиотеки С для подсчета количества букв в имени и фамилии, а затем применяет адрес структуры person для сохранения полученной суммы. Эта функция также имеет тип void. И, наконец, функция showinfo() использует указатель для доступа к информации, предназначенной для вывода. Поскольку showinfo() не изменяет содержимое массива, указатель объявлен как const.
Структуры и другие формы данных 585
Во всех этих операциях участвовала всего лишь одна переменная типа структуры person, и каждая из функций для доступа к структуре применяла ее адрес. Первая функция передавала информацию изнутри себя вызывающей программе, вторая функция принимала информацию из вызывающей программы внутрь себя, а третья функция делала то и другое.
Теперь посмотрим, каким образом запрограммировать решение той же задачи с использованием структур как аргументов и возвращаемых значений. Во-первых, для передачи самой структуры необходимо применять аргумент person, а не Sperson. Тогда соответствующий формальный аргумент объявляется с типом struct namect, а не указателем на этот тип. Во-вторых, чтобы предоставить main() значения структуры, можно возвратить саму структуру. В листинге 14.9 показана версия программы без указателей.
Листинг 14.9. Программа names2.c
586 Глава 14
Эта версия дает тот же самый результат, что и предыдущая, но работает по-другому. Каждая из трех функций создает собственную копию структуры person, так что в программе задействованы четыре разные структуры, а не только одна.
Для примера рассмотрим функцию makeinfo(). В первой программе ей передавался адрес структуры person, и функция имела дело с действительными значениями person. Во второй версии программы создавалась новая структура по имени info. Значения, хранящиеся в person, копировались в info, и функция работала с копией. Следовательно, подсчитанное количество букв сохранялось в info, но не в person. Тем не менее, это исправляет механизм возврата. Строка в makeinfo()
return info;
объединяется со строкой в main()
person = makeinfo(person);
для копирования значений хранящихся внутри info, в person. Обратите внимание, что функция makeinfo() должна быть объявлена с типом struct namect, т.к. она возвращает структуру.
Структуры или указатели на структуры?
Предположим, что вам необходимо написать функцию, связанную со структурами. Должны ли вы использовать указатели на структуры в качестве аргументов или же типы структур для аргументов и возвращаемых значений? Каждый подход характеризуется сильными и слабыми сторонами.
Метод с применением указателей в аргументах обладает двумя достоинствами: он работает как в старых, так и в новых реализациях С и является быстрым; передается всего лишь один адрес. Недостаток в том, что данные менее защищены. Некоторые операции в вызываемой функции могут непреднамеренно воздействовать на данные в исходной структуре. Однако появившийся в ANSI С спецификатор const решает эту проблему. Например, если в функцию showinfo() из листинга 11.8 поместить код, который изменяет какой-то член структуры, то компилятор обнаружит это и сообщит об ошибке.
Одно из преимуществ передачи структур в качестве аргументов заключается в том, что функция имеет дело с копией исходных данных, что безопаснее, чем работать с исходными данными. Вдобавок стиль программирования становится более ясным.
Структуры и другие формы данных 587
Предположим, что вы определили следующий тип структуры:
struct vector {double х; double у;};
Вы хотите установить вектор ans в сумму векторов а и b. Вы могли бы написать функцию, передающую и возвращающую структуры, которая привела бы к следующему коду:
struct vector ans, a, b;
struct vector sum_vect(struct vector, struct vector);
ans = sum_vect(a,b);
Для инженера эта версия выглядит более естественной, чем версия с указателями, которая могла бы выглядеть так:
struct vector ans, a, b;
void sum_vect(const struct vector *, const struct vector *, struct vector *);
sum_vect(&a, &b, sans);
Кроме того, в версии с указателями пользователь должен помнить, каким аргументом должен быть представлен адрес суммы — первым или последним.
Два основных недостатка передачи структур связаны с тем, что старые реализации С могут не воспринимать такой код, а также с тем, что в этом случае неэкономно расходуется время и память. Особенно расточительно передавать крупные структуры в функцию, которая использует только один или два члена структуры. В этом случае имеет смысл передавать указатель или же требуемые члены как индивидуальные аргументы.
Обычно программисты применяют указатели на структуры в качестве аргументов функции из соображений эффективности, используя const, когда необходимо защитить данные от нежелательных изменений. Передача структур по значению чаще всего делается для структур небольших размеров.
Символьные массивы или указатели на char в структурах
В рассмотренных ранее примерах для хранения строк в структуре применялись символьные массивы. Вероятно, вас интересует, можно ли вместо них использовать указатели на char? Например, в листинге 14.3 имеется следующее объявление:
#define LEN 20
struct names {
char first[LEN]; char last[LEN];
};
Можно ли вместо этого поступить так?
struct pnames { char * first; char * last;
};
Читать дальшеИнтервал:
Закладка: