В этом примере определен так называемый анонимный тип. У этого типа нет тега. Поэтому на него нельзя ссылаться в другом программном коде. Польза от этого кода в определенных здесь двух переменных employee и worker.
Пример 4. Определение типа, переменной и указателя на структуру.
#define MLEN 81 struct person_salary
{
char fio[MLEN]; double salary;
};
//…
struct person_salary employee; struct person_salary* p = &employee;
Здесь дополнительно объявлен и инициализирован указатель на структуру типа struct_salary.
Для обращения к отдельным полям структуры в языке Си служат два оператора:
∙.
∙->
Оператор . используется в том случае, когда известна переменная, имеющая тип структуры. Оператор -> при работе со структурой через указатель. Оба оператора относится к категории бинарных операторов. Эти операторы имеют следующий формат:
∙<α1> . <β>.
∙<α2> -> <β>.
Здесь α1 – переменная, имеющая тип структуры, α2 – указатель, установленный на объект типа структуры, а β - поле структуры.
Важно отметить, что результат вычисления рассматриваемых выражений имеет все свойства своего правого операнда. К ним относятся значение и тип результата. Рассмотрим следующий пример. Пусть имеется следующий
программный код.
#define MLEN 81 struct person_salary
{
char fio[MLEN]; double salary;
};
//…
struct person_salary employee; struct person_salary* p = &employee;
Тогда можно написать следующий программный код, содержащий
обращения к полям объекта employee. strcpy(employee.fio, “Petrov Ivan Ivanovich”);
puts(p->fio); p->salary = 10000;
121
printf(“%10.3f\n”, employee.salary);
Структура может быть инициализирована во время своего определения.
Ограничимся примером.
#define MLEN 81 struct person_salary
{
char fio[MLEN]; double salary;
};
int main(void)
{
struct person_salary new_person = {
“Ivanov I.I”, 25000
};
// …
}
Со структурой как со структурной переменной можно выполнять следующие операции:
∙присваивание,
∙передавать в функцию по значению,
∙передавать в функцию с использованием указателя,
∙ структуру можно использовать как значение, возвращаемое функцией.
Остальные операции со структурами выполняются по компонентно. Пример 1. Присваивание структур.
Постановка задачи. Имеются две структуры person1 и person2. Требуется скопировать поля структуры person1 в структуру person2.
Решение
#define MLEN 81 struct person_salary
{
char fio[MLEN]; double salary;
};
int main(void)
{
struct person_salary person1 = {
“Ivanov I.I”, 25000
};
122
struct person_salary person2 = {
“Petrov P.P”, 17000
};
person2 = peson1; // …
}
После выполнения этого фрагмента программного кода все поля структуры person1 оказались скопированными в структуру person2.
Пример 2. Возврат функцией значения типа структуры.
Постановка задачи. Заданы значения полей. Требуется сформировать структуру (построить структурную переменную) структуру.
Решение
#define MLEN 81 struct person_salary
{
char fio[MLEN]; double salary;
};
// Прототип функции, которая формирует структуру
struct person_salary form_struct(const char* fio, double salary);
int main(void)
{
struct person_salary = form_struct(“Petrov P.P.”, 20000); //…
}
struct person_salary form_struct(const char* fio, double salary)
{
struct person_salary temp; strcpy(temp.fio, fio); temp.salary = salary; return temp;
}
Пример 3. Использование указателей для передачи структур в качестве аргументов функций.
Постановка задачи. Выполнить обмен значений двух структур.
Решение
#define MLEN 81 struct person_salary
{
char fio[MLEN]; double salary;
123
};
void swap_struct(struct person_salary* p1, struct person_salary* p2);
int main(void)
{
struct person_salary person1, person2; //…
swap_struct(&person1, &person2); //…
}
void swap_struct(struct person_salary* p1, struct person_salary* p2)
{
struct person_salary temp = |
*p1; |
|
*p1 |
= |
*p2; |
*p2 |
= |
temp; |
}
Массивы структур широко используются на практике.
При определении массива структур используются обычные правила определения массивов:
<α> <β>[<γ>]; Здесь α – имя типа элементов, β - имя массива, γ – размер массива.
Приведем пример.
#define MLEN 81 #define MSIZE 20 struct person_salary
{
char fio[MLEN]; double salary;
};
struct person_salary ar[MSIZE];
// …
}
Здесь объявлен массив структур. В массиве можно хранить до 20 структур, имеющих тип struct person_salary.
124
При обращении к полям элемента структур могут возникнуть синтаксические сложности. Для их преодоления следует учитывать, что вначале надо получить доступ к элементу массива. Для этого необходимо использовать оператор []. Затем, используя оператор “.”, получить доступ к полю структуры. Дальнейшие действия зависят от типа поля.
Пример.
Пусть имеется массив, объявленный следующим образом.
#define MLEN 81 #define MSIZE 20 struct person_salary
{
char |
fio[MLEN]; |
|
double |
salary; |
|
}; |
|
|
struct person_salary arк[MSIZE]; |
||
Рассмотрим выражения, приведенные в таблице, приведенной ниже. |
||
Выражение |
|
Пояснение |
arr[0].salary |
|
Обращение к полю salary 1-ой |
|
|
структуры в массиве arr |
arr[1].fio |
|
Обращение к полю fio 2-ой |
|
|
структуры в массиве arr |
arr[1].fio[2] |
|
Обращение к 3-му символу поля fio |
|
|
2-ой структуры в массиве arr |
Язык Си не определяет операции ввода – вывода. Такие операции выполняются с помощью библиотечных функций. Библиотечные функции, предназначенные для этих целей можно разделить на две категории:
∙потоковые функции,
∙низкоуровневые функции.
Потоковые функции нашли более широкое применение на практике по сравнению с низкоуровневыми. Этому способствовало то обстоятельство, что потоковые функции были включены в стандартную библиотеку языка Си. Применение таких функций не ухудшают переносимость программы.
Низкоуровневые библиотечные функции учитывают особенности той среды, в которой будет выполняться программа. Это позволяет повысить их эффективность по сравнению с потоковыми функциями. Недостаток – ухудшению переносимости программы. Ограничимся рассмотрением потоковых функций.
125