§16 Структуры

Понятие структуры данных

Структурой данных называется составной тип в котором под одним именем объединены данные различных типов. Структура данных (наряду с классом) представляет собой абстрактный тип данных определяемый разработчиком. Структура может также включать в себя и другие абстрактные типы (например, string). После объявления абстрактного типа можно создавать переменные и массивы, указатели и ссылки, объявлять функции и передавать параметры абстрактного типа, присваивать значения одних переменных значениям других переменных одного и того же абстрактного типа.
Переменные, составляющие структуру, называются её членами (member) или полями. Помимо полей, структуры могут содержать функции-члены, иначе называемые – методами.

Определение структуры

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

struct student {
	double weight;
	double height;
	char stage;
	int age;
	string name;
};

Одновременно с определением структуры могут быть объявлены и переменные этого типа. В этом случае точка с запятой ставится не за фигурной скобкой, а после перечисления идентификаторов абстрактного типа.

struct student {
	double weight;
	double height;
	char stage;
	int age;
	string name;
} Boris, Sveta, Alex, Margo;

Правилом хорошего тона в программировании считается отделение определения структур от объявления переменных этих структур.
Чаще всего структуры определяются вне тела главной функции main(). Делается это для того, чтобы абстрактные типы стали доступными и другим функциям.

Доступ к членам

Операция “точка”

Для того, чтобы получить доступ к членам структуры необходимо использовать операцию “точка” (.)
Синтаксис:
Имя_переменной.Имя_члена

student Masha;
Masha.age = 18;
cout << Masha.age << endl;
Операция "стрелка"

Если получен указатель абстрактного типа, то доступ к элементам можно получить с помощью операции "стрелка" (->)

student Serge;
student *p = new student;
student *t = &Serge;
p -> weight = 65;
t -> height = 160;
cout << p -> weight << endl;
cout << t -> height << endl;

Примечание. Операция p -> atrib означает тоже самое, что и (*p).atrib.

Инициализация переменных абстрактного типа

Инициализировать поля структуры можно с помощью списка инициализации:

student Serge {62, 175, 'A', 16, "Abrosimov S. I."};
student *p = new student {65, 180, 'C', 17, "Lukin A. S."};
cout << Serge.name << endl;
cout << p -> weight << endl;

Если инициализация производилась с пустыми фигурными скобками, то это означает, что все поля будут иметь значения по умолчанию (т. е. нулевые).

Массивы структур

Очень часто структуры используются как элементы массивов. Рассмотрим задачу в которой используется массив структур типа student. В этом примере, в массиве сохраняются учетные записи студентов и определяется их средний рост, вес или возраст (по выбору пользователя).
Программа 16.1.

//============================================================================
// Name        : lesson-16-1.cpp
//============================================================================
#include <iostream>
#include <array>
#include <string>
using namespace std;

struct student {
	double weight;
	double height;
	char stage;
	int age;
	string name;
};

void mean(array<student, 30>&, string&, const int);

int main() {
	array<student, 30> card;
	for (auto &r: card) {
		student per;
		cout << "name => ";   cin >> per.name;
		cout << "stage => ";  cin >> per.stage;
		cout << "age => ";    cin >> per.age;
		cout << "weight => "; cin >> per.weight;
		cout << "height => "; cin >> per.height;
		r = per;
	}
	string str1 = "Cредний возраст";
	string str2 = "Cредний рост";
	string str3 = "Cредний вес";
	cout << "Какие средние параметры вы хотите определить?\n"
            "Введите одну из цифр:\n"
         << "1 - " << str1 << "\n"
         << "2 - " << str2 << "\n"
            "3 - " << str3 << "\n"
            "и нажмите Enter";
    int n; cin >> n;
    switch (n) {
        case 1: mean(card, str1, 1); break;
        case 2: mean(card, str2, 2); break;
        case 3: mean(card, str3, 3); break;
    }
	return 0;
}

void mean(array<student, 30> &aver, string &mstr, const int x) {
    double s = 0;
    if (x == 1) for (auto &r : aver) s += r.age;
    if (x == 2) for (auto &r : aver) s += r.height;
    if (x == 3) for (auto &r : aver) s += r.weight;
    cout << mstr << " - " <<  s / aver.size() << endl;
}

Передача структуры в функцию

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

#include <iostream>
#include <array>
#include <string>
using namespace std;

struct student {
	double weight;
	double height;
	char stage;
	int age;
	string name;
};

void swap_str(student&, student&);

template <typename T>
void swap_mem(T &a, T &b) {
    T temp;
    temp = a;
    a = b;
    b = temp;
}

int main() {
    student pr1 {62, 175, 'A', 16, "Abrosimov S. I."};
   	student pr2 {65, 180, 'C', 17, "Lukin A. S."};
   	cout << pr1.name << endl;
   	cout << pr2.name << endl;
   	swap_str(pr1, pr2);
   	cout << pr1.name << endl;
   	cout << pr2.name << endl;
	return 0;
}

void swap_str(student &prs1, student &prs2) {
    swap_mem(prs1.weight, prs2.weight);
    swap_mem(prs1.height, prs2.height);
    swap_mem(prs1.stage, prs2.stage);
    swap_mem(prs1.age, prs2.age);
    swap_mem(prs1.name, prs2.name);
}

Для того, чтобы возвращать ссылку на структуру необходимо использовать функцию возвращающую ссылку. Такой тип функции мы ещё не рассматривали. В теле такой функции можно производить любые допустимые операции с данными, переданными по ссылке (или иным образом), но возвращать такая функция будет не значение, а ссылку на измененный объект. Как реализовать такую функцию показано в программе 16.3. В этой программе реализована функция для перевода учащегося в старшую группу.
Программа 16.3.

#include <iostream>
#include <array>
#include <string>
using namespace std;

struct student {
	double weight;
	double height;
	char stage;
	int age;
	string name;
};

student &rld_stage(student&);

int main() {
    student person1 {62, 175, 'A', 16, "Abrosimov S. I."};
   	cout << person1.stage << endl;
   	person1 = rld_stage(person1);
   	cout << person1.stage << endl;
	return 0;
}

student &rld_stage(student &old_stg) {
   old_stg.stage = old_stg.stage + 1;
   return old_stg;
}
Новое
  • Структура
  • Абстрактный тип
  • Поле
  • Члены
  • Операция "стрелка"
  • Операция "точка"
Литература
  1. Прата, Стивен. Язык программирования C++. Лекции и упражнения, 6-е изд.: Пер. с англ. — М.: ООО «И.Д. Вильяме», 2012
  2. Липпман Б. Стенли, Жози Лажойе, Барбара Э. Му. Язык программирования С++. Базовый курс. Изд. 5-е. М: ООО "И. Д. Вильямс", 2014
  3. Эллайн А. C++. От ламера до программера. СПб.: Питер, 2015
  4. Джосаттис Н. М. Стандартная библиотека C++: справочное руководство, 2-е изд.-М.: Вильямс, 2014


Print Friendly, PDF & Email

Comments are closed.