Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Далее в программе идут следующие строки:
while (getchar() != ‘\n')
continue; /* очистить входную строку */
Как уже говорилось в предшествующих главах, этот код компенсирует игнорирование функцией scanf() пробелов и символов новой строки. Когда вы отвечаете на запрос цены книги, вы набираете что-нибудь такое:
12.50[enter]
576 глава 14
Эго приводит к передаче следующей последовательности символов:
12.50\n
Функция scanf() получает символы 1,2, ., 5 и 0, но оставляет символ \n в ожидании, что им займется следующий оператор чтения. Если бы код очистки входной строки отсутствовал, то следующий оператор чтения, s_gets (library [count] . title, MAXTITL), прочитал бы оставленный символ новой строки и посчитал бы, что введена пустая строка, а это является сигналом к прекращению ввода. Вставленный нами код читает символы до тех пор, пока не обнаружит символ новой строки и затем избавится от него. Он ничего не делает с этими символами, а лишь удаляет их из входной очереди. Это позволяет функции s_gets() корректно начать чтение следующих входных данных.
Теперь возвратимся к исследованию структур.
Вложенные структуры
Иногда удобно, чтобы одна структура содержала другую структуру, которая называется вложенной. Например, Шейла Пироски создает структуру с информацией о своих друзьях. Одним из членов структуры является, естественно, имя друга. Однако имя само может быть представлено с помощью структуры, с отдельными записями для имени и фамилии. В листинге 14.3 показан сжатый пример работы Шейлы.
Листинг 14.3. Программа friend.с
Структуры и другие формы данных 577
Ниже представлен вывод, полученный из этой программы:
Дорогой Билли,
Благодарю вас за чудесно проведенный вечер, Билли.
Вы однозначно продемонстрировали, что персональный тренер
являет собою особый тип мужчины. Мы обязательно должны встретиться
за восхитительным ужином с запеченными омарами и весело провести время.
До скорой встречи,
Шейла
Во-первых, обратите внимание на то, каким образом вложенная структура устанавливается в объявлении структуры. Она просто объявляется, как если бы это была переменная типа int:
struct names handle;
Такое объявление говорит о том, что handle является переменной типа struct names. Разумеется, файл должен также включать объявление структуры names.
Во-вторых, посмотрите, как получать доступ к члену вложенной структуры; нужно всего лишь два раза воспользоваться операцией точки:
printf("Дорогой %s!\n\n", fellow.handle.hrst);
Если рассматривать эту конструкцию слева направо, она интерпретируется следующим образом:
(fellow.handle).hrst
То есть необходимо найти структуру fellow, затем член handle структуры fellow и, наконец, член first структуры типа names.
Указатели на структуры
Любители указателей будут рады узнать о возможности иметь указатели на структуры. Существуют, по меньшей мере, четыре причины, обусловливающие необходимость в указателях на структуры. Во-первых, точно так же, как манипулировать указателями на массивы проще, чем самими массивами (скажем, в задаче сортировки), с указателями на структуры часто работать легче, чем с самими структурами. Во-вторых, в некоторых старых реализациях структура не может быть передана как аргумент функции, но указатель на структуру — может. В-третьих, несмотря на то, что структуру можно передавать в качестве аргумента, передача указателя зачастую эффективнее.
578 глава 14
И, в-четвертых, многие замысловатые представления данных применяют структуры, содержащие указатели на другие структуры.
Следующий краткий пример (листинг 14.4) демонстрирует определение указателя на структуру и его использование для доступа к членам структуры.
Листинг 14.4. Программа friends.с
Запуск программы дает следующий вывод:
адрес #1: 0x7fff5fbff820 #2: 0x7fff5fbff874 указатель #1: 0x7fff5fbff820 #2: 0x7fff5fbff874 him->income равно $68112.00: (*him).income равно $68112.00 him->favfood равно рыбным фрикасе: him->handle.last равно Стюарт
Мы сначала посмотрим, каким образом создается указатель на структуру guy, а затем объясним, как описать отдельные члены структур с применением этого указателя.
Структуры и другие формы данных 579
Объявление и инициализация указателя на структуру
Объявить указатель на структуру очень просто:
struct guy * him;
Первым идет ключевое слово struct, затем дескриптор структуры guy, звездочка (*) и, наконец, имя указателя. Это тот же самый синтаксис, который используется для объявления других указателей, как было показано ранее.
Объявление не приводит к созданию новой структуры, но указатель him теперь может ссылаться на любую существующую структуру типа guy. Например, если barney — структура типа guy, то можно написать следующий оператор:
him = &barney;
В отличие от массивов, имя структуры не является ее адресом — вы должны применять операцию &.
В нашем примере fellow — массив структур, т.е. fellow [0] представляет собой структуру, поэтому код инициализирует him, делая его указывающим на f el low [0]:
him = &fellow[0];
Первые две строки вывода показывают, что присваивание прошло успешно. Сравнивая эти две строки, мы видим, что him указывает на fellow [0], a him + 1 — на fellow [1]. Обратите внимание, что добавление 1 к him приводит к добавлению значения 84 к адресу. В шестнадцатеричной форме записи 874 - 820 = 54 (шестнадцатеричное) = 84 (десятичное), т.к. каждая структура guy занимает 84 байта памяти: иод names, first отводится 20 байтов, под names, last — 20 байтов, под favfood — 20 байтов, под job — 20 байтов и под income — 4 байта (размер типа float в нашей системе). Кстати, в некоторых системах размер структуры может быть больше суммы размеров ее частей. Причина в том, что требования к выравниванию данных системы могут вызвать появление зазоров. Например, возможно, что система должна размещать каждый член структуры по четному адресу либо по адресу, кратному 4. Такие структуры могут содержать в себе неиспользуемые “бреши”.
Доступ к членам по указателю
Указатель him указывает на структуру fellow [0]. А как с помощью him получить значение члена fellow [0] ? В третьей строке вывода демонстрируются два метода.
Первый и наиболее распространенный метод предусматривает применение новой операции ->. Знак этой операции образован из дефиса (-) и символа “больше” (>). Мы имеем следующие зависимости:
him->income равно barney.income, если him == &barney
him->income равно fellow[0].income, если him == &fellow[0]
Другими словами, указатель на структуру, за которым следует операция ->, работает таким же образом, как имя структуры с последующей операцией точки (.). (Вы не можете использовать просто him. income, потому что him не является именем структуры.)
Читать дальшеИнтервал:
Закладка: