Язык Си - руководство для начинающих - M. УЭИТ
Шрифт:
Интервал:
Закладка:
Резюме: операции над структурами и объединениями
Эта операция используется с именем структуры или объединения для определения элемента этой структуры или объединения. Если name является именем структуры, a member - элементом, определенным структурным шаблоном, то name.member обозначает этот элемент структуры. Операция получения элемента может использоваться таким же образом для объединений.
Примеры
struct {
int code;
float cost;
} item;
item.code = 1265;
Данный оператор присваивает значение элементу code структуры item.
II. ОПЕРАЦИЯ КОСВЕННОГО ПОЛУЧЕНИЯ ЭЛЕМЕНТА: ->
Эта операция используется с указателем на структуру или объединение для определения элемента структуры или объединения. Предположим, что ptrstr является указателем на структуру и что member элемент, определенный структурным шаблоном. Тогда
ptrstr -> member
определяет элемент, на который выполняется ссылка. Операцию косвенного обращения к элементу можно использовать таким же образом и для объединений.
Пример
struct {
int code
float cost;
} item, *ptrst;
ptrst = &item;
ptrst -> code = 3451;
Операторы присваивают значение элементу code структуры item. Следующие три выражения эквивалентны:
ptrst->code item.code (*ptrst).code
ПЕРЕДАЧА ИНФОРМАЦИИ О СТРУКТУРАХ ФУНКЦИЯМ
Вспомним, что аргументы функции передают значения в функцию. Каждое значение является либо числом типа int или float, либо ASCII-кодом или адресом. Структура гораздо сложнее, чем отдельная переменная, поэтому неудивительно, что саму структуру нельзя использовать в качестве аргумента функции. (Это ограничение снято в некоторых новых рeализациях.) Однако есть способы ввести информацию о структуре внутрь функции. Рассмотрим три способа (на самом деле два с вариациями).
Использование элементов структуры
Поскольку элемент структуры является переменной с единственным значением (т.е. типа int или одного из его "родственников" - char, float, double или указатель), он может быть передан как аргумент функции. Простая программа финансовых расчетов на рис. 14.6, которая прибавляет взнос клиента к его счету, иллюстрирует этот способ. Заметим, между прочим, что мы объединили определение шаблона, описание переменной и инициализацию в один оператор.
/* передача элементов структуры как аргументов функции */
struct funds {
char *bank;
float bankfund;
char *save;
float savefund; }
stan = { " Банк синьора Помидора",
1023.43,
" Сбережения и займы Снупи",
4239.87 };
main( )
{
float total, sum( );
extern struct funds stan; /* необязательное описание */
printf("У Стэна всего %.2f долл.n", sum(stan.bankfund,
stan.savefund));
}
/* складывает два числа типа float */
float sum(x, у);
float x, у;
{ return( x + y); }
РИС. 14.6. Программа, передающая функции аргументы, являющиеся элементами структуры.
Результат выполнения этой программы:
У Стэна всего 5263.30 долл.
Вот это да, она работает. Заметим, что функция sum( ) "не знает", или же си безразлично, являются ли элементами структуры фактические аргументы; она только "требует", чтобы они имели тип float.
Конечно, если вы хотите, чтобы программа воздействовала на значение элемента в вызывающей программе, можно передать ей адрес этого элемента:
modify(&stan.bank fund);
и тогда получилась бы функция, которая изменила бы банковский счет в структуре stan.
Второй способ передачи информации о структуре заключается в возможности сообщить суммирующей функции, что она имеет дело со структурой.
Использование адреса структуры
Мы будем решать ту же самую задачу, что и прежде, но при этом использовать адрес структуры в качестве аргумента. Это хорошо, поскольку адрес представляет собой только одно число. Так как функция должна работать со структурой funds, она тоже должна использовать шаблон funds. См. рис. 14.7.
/* передача адреса структуры в функцию */
struct funds {
char *bank;
float bankfund;
char *save;
float savefund;
} stan = {
"Банк синьора Помидора" ,
1023.43,
" Сбережения и займы Снупи" ,
4239.87
};
main( )
{
float total, sum( );
printf(" У Стэна всего %.2f долл.n", sum(&stan) );
}
float sum (money)
struct funds *money;
}
return( money-> bankfund + money-> savefund);
}
PИC. 14.7. Программа, передающая функции адрес структуры. Эта программа тоже выдает
У Стэна всего 5263.30 долл.
Функция sum( ) имеет указатель (money) на структуру fund. Передача адреса &stan в функцию заставляет указатель money ссылаться на структуру stan. Затем используем операцию - > для получения значений элементов stan.bankfund и stan.savefund.
Эта функция также имеет доступ к названиям учреждений, хотя их не использует. Заметим, что мы должны применять операцию & для получения адреса структуры. В отличие от имени массива имя структуры само по себе нe является синонимом своего адреса.
Наш следующий способ применим к массивам структур и является вариантом данного способа.
Использование массива
Предположим, у нас есть массив структур. Имя массива является синонимом его адреса, поэтому его можно передать функции. С другой стороны, функции будет необходим доступ к структурному шаблону. Чтобы показать, как такая программа работает (рис. 14.8), мы расширим нашу программу таким образом, чтобы она обслуживала двух человек, а мы, следовательно, имели бы массив двух структур funds.
/* передача массива структур в функцию */
struct funds {
char *bank;
float bankfund;
char *save;
float savefund; }
jones[2] ={
{ " Банк синьора Помидора" ,
1023.43,
" Сбережения и займы Снупи" ,
4239.87 },
{ " Банк Честного Джека",
976.57,
"Накопления по предварительному плану",
1760.13 } };
main( )
{
float total, sum( );
printf("Джонсы имеют всего %.2f долл.n", sum(jones));
}
float sum(money);
struct funds *money;
{
float total;
int i;
for( i = 0, total = 0; i < 2; i++, money++ )
total += money- > bankfund + money -> savefund;
return(total);
}
РИС. 14. 8. Программа, передающая функции массив структур.
Программа выдает
Джонсы имеют всего 8000.00 долл.
(Что за круглая сумма! Можно подумать, что эти цифры взяты с потолка.) Имя массива jones является указателем на массив. В частности, оно ссылается на первый элемент массива, который является структурой jones[0]. Таким образом, в начале указатель money за дается через
money = &jones[0];
Затем использование операции - > позволяет нам добавить два вклада для первого Джонса. Это действительно очень похоже на последний пример. Далее, цикл for увеличивает указатель money на 1. Теперь он ссылается на следующую структуру, jones[1], и остаток вкладов может быть добавлен к total.
Вот два основных замечания:
1. Имя массива можно использовать для передачи в функцию указателя на первую структуру в массиве.
2. Затем можно использовать арифметическую операцию над указателем, чтобы передвигать его на последующие структуры в массиве. Заметим, что вызов функции