Главная > Программирование на С++

Распознанный текст, спецсимволы и формулы могут содержать ошибки, поэтому с корректным вариантом рекомендуем ознакомиться на отсканированных изображениях учебника выше

Также, советуем воспользоваться поиском по сайту, мы уверены, что вы сможете найти больше информации по нужной Вам тематике

3.4. Структуры

При разработке программ важным является выбор эффективного способа представления данных. Во многих случаях недостаточно объявить простую переменную или массив, а нужна более гибкая форма представления данных. Таким элементом может быть структура, которая позволяет включать в себя разные типы данных, а также другие структуры. Приведем пример, в котором использование структуры позволяет эффективно представить данные. Таким примером будет инвентарный перечень книг, в котором для каждой книги необходимо указывать ее наименование, автора и год издания. Причем количество книг может быть разным, но будем полгать, что не более 100. Для хранения информации об одной книге целесообразно использовать структуру, которая задается в языке С++ с помощью ключевого слова struct, за которым следует ее имя. Само определение структуры, т.е. то, что она будет содержать, записывается в фигурных скобках {}. В данном случае структура будет иметь следующий вид:

struct book {
char title[100]; //наименование книги
char author[100]; //автор
int year; //год издания
};

Такая конструкция задает своего рода шаблон представления данных, но не сам объект, которым можно было бы оперировать подобно переменной или массиву. Для того чтобы объявить переменную для структуры с именем book используется такая запись:

struct book lib; //объявляется переменная типа book

После объявления переменной lib имеется возможность работать со структурой как с единым объектом данных, который имеет три поля: title, author и year. Обращение к тому или иному полю структуры осуществляется через точку: lib.title, lib.author и lib.year. Таким образом, для записи в структуру информации можно использовать следующий фрагмент программы:

printf(“Введите наименование книги: “);
scanf(“%s”,lib.title);
printf(“Введите автора книги: “);
scanf(“%s”,lib.author);
printf(“Введите год издания книги: “);
scanf(“%d”,&lib.year);

После этого в соответствующие поля будет записана введенная с клавиатуры информация и хранится в единой переменной lib. Однако по условиям задачи необходимо осуществлять запись не по одной, а по 100 книгам. В этом случае целесообразно использовать массив структур типа book, который можно задать следующим образом:

struct book lib[100];

В этом случае программу ввода и хранения информации по книгам можно записать в виде:

Листинг 3.5. Инвентарный перечень книг.

#include
struct book {
char title[100]; //наименование книги
char author[100]; //автор
int year; //год издания
};

int main()
{
int cnt_book = 0, ch;
struct book lib[100];
do
{
printf(“Введите наименование книги: “);
scanf(“%s”,lib[cnt_book].title);
printf(“Введите автора книги: “);
scanf(“%s”,lib[cnt_book].author);
printf(“Введите год издания книги: “);
scanf(“%d”,&lib.year);
printf(“Нажмите q для завершения ввода: ”);
cnt_book++;
}
while(scanf(“%d”,ch) == 1 && cnt_book < 100);
return 0;
}

Данный пример показывает удобство хранения информации по книгам. Тот же алгоритм в общем случае можно реализовать и без структуры, но тогда пришлось бы использовать два двумерных массива символов и один одномерный массив для хранения года издания. Несмотря на то, что формально такая запись была бы корректной с точки зрения языка С++, но менее удобна в обращении.

Структуры можно автоматически инициализировать при их объявлении подобно массивам, используя следующий синтаксис:

struct bool lib = {
“Евгений Онегин”,
“Пушкин А.С.”,
1995
};

При выполнении данного фрагмента программы в переменные структуры title, author и year будет записана соответственно информация: “Евгений Онегин”, “Пушкин А.С.”, 1995. Здесь следует обратить внимание, что последовательность данных при инициализации должна соответствовать последовательности полей в структуре. Это накладывает определенные ограничения, т.к. при инициализации необходимо помнить последовательность полей в структуре. Стандарт C99 допускает более гибкий механизм инициализации полей структуры:

struct book lib = {.year = 1995,
.author = “Пушкин А.С.”,
.title = “Евгений Онегин” };

или

struct book lib = { .year = 1995,
.title = “Евгений Онегин” };

или

struct book lib = {.author = “Пушкин А.С.”,
.title = “Евгений Онегин”,
1995 };

В первом и во втором примерах при инициализации указываются наименования полей через точку. При этом их порядок и число не имеет значения. В третьем примере первые два поля указаны через имена, а последнее инициализируется по порядковому номеру – третьему, который соответствует полю year.

В некоторых случаях имеет смысл создавать структуры, которые содержат в себе другие (вложенные) структуры. Например, при создании простого банка данных о сотрудниках предприятия целесообразно ввести, по крайней мере, две структуры. Одна из них будет содержать информацию о фамилии, имени и отчестве сотрудника, а вторая будет включать в себя первую с добавлением полей о профессии и возрасте:

struct tag_fio {
char last[100];
char first[100];
char otch[100];
};
struct tag_people {
struct tag_fio fio; //вложенная структура
char job[100];
int old;
};

Рассмотрим способ инициализации и доступ к полям структуры people на следующем примере.

Листинг 3.6. Работа с вложенными структурами.

int main()
{
struct people man = {
{“Иванов”, “Иван”, “Иванович”},
“Электрик”,
50 };
printf(“Ф.И.О.:%s %s %sn”,man.fio.last,man.fio.first,
man.fio.otch);
printf(“Профессия : %s n”,man.job);
printf(“Возраст : %dn”,man.old);
return 0;
}

В данном примере показано, что для инициализации структуры внутри другой структуры следует использовать дополнительные фигурные скобки, в которых содержится информация для инициализации полей фамилии, имени и отчества сотрудника. Для того чтобы получить доступ к полям вложенной структуры выполняется сначала обращение к ней по имени man.fio, а затем к ее полям: man.fio.last, man.fio.first и man.fio.otch. Используя данное правило, можно создавать многоуровневые вложения для эффективного хранения и извлечения данных.

Структуры, как и обычные типы данных, можно передавать функции в качестве аргумента. Следующий пример демонстрирует работу функции отображения полей структуры на экран.

Листинг 3.7. Передача структур через аргументы функции.

#include
struct tag_people {
char name[100];
char job[100];
int old;
};
void show_struct(struct tag_people man);
int main()
{
struct tag_people person = {“Иванов”,”Электрик”,30};
show_struct(person);
return 0;
}
void show_struct(struct tag_people man)
{
printf(“Имя: %sn”,man.name);
printf(“Профессия: %sn”,man.job);
printf(“Возраст: %dn”,man.old);
}

В приведенном примере используется функция с именем show_struct, которая имеет тип аргумента struct tag_people и переменную-структуру man. При передаче структуры функции создается ее копия, которая доступная в теле функции show_struct под именем man. Следовательно, любые изменения полей структуры с именем man никак не повлияют на содержание структуры с именем person. Вместе с тем иногда необходимо выполнять изменение полей структуры функции и возвращать измененные данные вызывающей программе. Для этого можно задать функцию, которая будет возвращать структуру, как показано в листинге 3.8.

Листинг 3.8. Функции, принимающие и возвращающие струткуру.

#include
struct tag_people {
char name[100];
char job[100];
int old;
};
void show_struct(struct tag_people man);
struct tag_people get_struct();
int main()
{
struct tag_people person;
person = get_struct();
show_struct(person);
return 0;
}
void show_struct(struct tag_people man)
{
printf(“Имя: %sn”,man.name);
printf(“Профессия: %sn”,man.job);
printf(“Возраст: %dn”,man.old);
}
struct tag_people get_struct()
{
struct tag_people man;
scanf(“%s”,man.name);
scanf(“%s”,man.job);
scanf(“%d”,man.old);
return man;
}

В данном примере используется функция get_struct(), которая инициализирует структуру с именем man, запрашивает у пользователя ввод значений ее полей и возвращает введенную информацию главной программе. В результате выполнения оператора присваивания структуры man структуре person, происходит копирование информации соответствующих полей и автоматическое удаление структуры man.

Функциям в качестве аргумента можно также передавать массивы структур. Для этого используется следующее определение:

void show_struct(struct people mans[], int size);

Здесь size – число элементов массива, которое необходимо для корректного считывания информации массива mans. Следующий пример показывает принцип работы с массивами структур.

Листинг 3.9. Передача массив структур функции.

#include
#define N 2
struct tag_people {
char name[100];
char job[100];
int old;
};
void show_struct(struct people mans[], int size);
int main()
{
struct people persons[N] = {
{ “Иванов”, «Электрик», 35 },
{ “Петров”, «Преподаватель», 50 },
};
show_struct(persons, N);
}
void show_struct(struct people mans[], int size)
{
for(int i = 0;i < size;i++) {
printf(“Имя: %sn”,mans[i].name);
printf(“Профессия: %sn”,mans[i].job);
printf(“Возраст: %dn”,mans[i].old);
}
}

При передаче аргумента persons выполняется копирование информации в массив mans и указывается дополнительный параметр size, для определения числа элементов массива mans. Затем в функции show_struct() реализуется цикл, в котором выполняется отображение информации массива структуры на экран монитора.

Видео по теме

Categories

1
Оглавление
email@scask.ru