Массив структур. Указатель на структуру

Точно так же, как мы можем создавать массивы любых встроенных типов данных (int, char…), можно создавать массивы структур. Рассмотрим это на примере со структурой WonderfulWoman знакомой нам из первой и второй частей статьи о структурах C++.

Надо внести данные о 7-ми моделях. Данные показать на экран в виде таблицы, чтобы было легче их сравнить. Схематично так:

Чтобы это реализовать — набирайте код:

#include<iostream>

#include<windows.h> // для system("cls");

using namespace std;

 

struct Size

{

int breast;

int waist;  

int hips;  

};

 

struct WonderfulWoman

{

char name[64];

int age;

int height;

int weight;

Size volume;  

bool engKnowledge;

};

 

void showData(const WonderfulWoman Obj[], int amount);

 

int main()

{

setlocale(LC_ALL, "rus");

 

const int amountOfGirl = 7;

WonderfulWoman Woman[amountOfGirl] = {};

 

for (int i = 0; i < amountOfGirl; i++)

{

cout << "Имя: ";

cin.getline(Woman[i].name, 32);

cout << "Возраст: ";

cin >> Woman[i].age;

cout << "Рост: ";

cin >> Woman[i].height;

cout << "Вес: ";

cin >> Woman[i].weight;

cout << "Английский (1 - да, 0 - нет): ";

cin >> Woman[i].engKnowledge;

cout << "Объемы (грудь, талия, бедра): ";

cin >> Woman[i].volume.breast;

cin >> Woman[i].volume.waist;

cin >> Woman[i].volume.hips;

cin.get(); // считывает из потока Enter который пользователь нажимает после ввода возраста

cout << endl;

}

 

showData(Woman, amountOfGirl);

 

return 0;

}

 

void showData(const WonderfulWoman Obj[], int amount)

{

system("cls"); // сработает только для windows

cout << "№\t" << "Имя\t" << "Возраст\t" << "Рост\t" << "Вес\t" << "Объёмы\t\t" << "Английский" << endl;

cout << "==================================================================" << endl;

for (int i = 0; i < amount; i++)

{

cout << i + 1 << '\t' << Obj[i].name << '\t' << Obj[i].age

<< '\t' << Obj[i].height << '\t' << Obj[i].weight << '\t'

<< Obj[i].volume.breast << '/' << Obj[i].volume.waist << '/' << Obj[i].volume.hips

<< '\t' << Obj[i].engKnowledge << endl;

}

}

Массив объектов структуры WonderfulWoman объявлен в строке 29 и в этой же строке все элементы объектов в этом массиве инициализированы нулями. Как видите — кроме того, что вместо встроенного типа мы написали дескриптор структуры, больше ничего нового в этом объявлении для нас нет. Дали имя массиву, указали количество элементов (объектов), инициализировали нулями — всё. Таким образом мы создали массив объектов структуры.

Как обратиться к элементу конкретного объекта структуры?Обычное обращение через точку уже не подойдет:

Конечно, ведь непонятно в какой именно объект из 7 надо внести данные. Так как каждый объект теперь является ячейкой массива структур, чтобы обратиться к его элементам надо сначала указать индекс объекта в квадратных скобках. Только потом точку и имя элемента:

В строках 31- 49 находится цикл for. С его помощью вносятся данные во все объекты массива структур. Обратите внимание на строку 47. Без этого оператора cin.get(); вы столкнетесь с ошибкой, о которой компилятор вам не сообщит. Она заключается в том, что после внесения данных в элемент Woman[i].volume.hips и нажатия Enter, в потоке ввода остаётся символ конца строки. Когда цикл продолжит работу — этот символ автоматически запишется в Woman[i].name следующего объекта и нам сразу будет предложено ввести возраст. То есть имя внести мы не сможем. Чтобы этого избежать, надо считать из потока этот символ с помощью cin.get(); .

Результат — заполняем структуры данными :

После ввода данных всех моделей, экран очистится (за что отвечает system(«cls»);) и мы увидим таблицу:

В этой статье поговорим ещё об указателях на структуры. Если, например, надо написать функцию, в которой будут записываться данные в элементы структуры, то необходимо передать эту структуру по указателю. Иначе изменения не сохранятся. Рассмотрим пример со структурой Size из предыдущего листинга. Надо написать функцию, в которой пользователь вносит данные в элементы структуры.

#include<iostream>

using namespace std;

 

struct Size

{

int breast;

int waist;

int hips;

};

 

void setSizes(Size* Obj);

void showSizes(const Size* Obj);

 

int main()

{

setlocale(LC_ALL, "rus");

 

Size* Volume = new Size;

 

cout << "Введите объемы (грудь, талия, бедра): ";

setSizes(Volume);

showSizes(Volume);

 

Volume->waist = 62;

Volume->hips = 92;

showSizes(Volume);

 

    delete Volume;

 

return 0;

}

 

void setSizes(Size* Obj)

{

cin >> Obj->breast;

cin >> Obj->waist;

cin >> Obj->hips;

cout << endl;

}

 

void showSizes(const Size* Obj)

{

cout << "Объемы = ";

cout << Obj->breast << '/' << Obj->waist << '/' << Obj->hips << endl;

}

Объявляя указатель на структуру, не забывайте о том, что надо выделить память под неё — строка 18. Указатель объявлен. Давайте разберёмся теперь, как обращаться к элементам структуры, через указатель. Допустим надо внести значение в элемент waist. Использовать . — операцию доступа по объекту уже не получится:

Ошибку подсвечивает потому, что указатель должен хранить адрес, а он пытается обратиться к элементу типа int. Попробуем разыменовать указатель на структуру:

Теперь все нормально, но это не совсем удобная запись. В С++ есть специальная операция доступа по указателю (стрелочка — состоит из тире и знака больше) -> . Она как бы показывает, на какой элемент структуры ссылается указатель:

Так что просто запомните — если вы работаете с указателем на структуру, то для доступа к элементам этой структуры надо применять не точку, а стрелку. Перепишите пример, который расположен выше — так будет легче понять и запомнить.

Результат: