Динамический массив структур

Динамический массив структур мы разберем на примере. Нам предстоит решить следующую задачу: пользователь вводит данные о спонсорах какого-то проекта. А именно — фамилию, имя и сумму пожертвования. После каждого ввода данных программа задает вопрос: продолжить ввод или нет. Каждый раз, когда пользователь выбирает «продолжить» — надо выделить участок памяти еще под одну структуру. Таким образом динамический массив структур будет расти, пока пользователь не приостановит ввод. После завершения ввода, вывести таблицу с данными о спонсорах на экран.

#include<iostream>

#include<windows.h>

using namespace std;

 

struct Sponsor

{

char name[32];

char surname[32];

double sum;

};

 

Sponsor* AddStruct(Sponsor* Obj, const int amount);

void setData(Sponsor* Obj, const int amount);

void showData(const Sponsor* Obj, const int amount);

 

int main()

{

setlocale(LC_ALL, "rus");

 

Sponsor* OurSponsors = 0;

int sponsorAmount = 0;

int YesOrNot = 0; //  продолжить или остановить ввод данных

do

{

OurSponsors = AddStruct(OurSponsors, sponsorAmount);

setData(OurSponsors, sponsorAmount);

 

sponsorAmount++;

 

cout << "Продолжить ввод данных (1 - да, 0 - нет): ";

cin >> YesOrNot;

cin.get();

} while (YesOrNot != 0);

 

showData(OurSponsors, sponsorAmount);

 

delete[] OurSponsors;

return 0;

}

 

Sponsor* AddStruct(Sponsor* Obj, const int amount)

{

if (amount == 0)

{

Obj = new Sponsor[amount + 1]; // выделение памяти для первой структуры

}

else

{

Sponsor* tempObj = new Sponsor[amount + 1];

 

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

{

tempObj[i] = Obj[i]; // копируем во временный объект

}

delete [] Obj;

 

Obj = tempObj;

}

return Obj;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void setData(Sponsor* Obj, const int amount)

{

cout << "Фамилия: ";

cin.getline(Obj[amount].surname, 32);

cout << "Имя: ";

cin.getline(Obj[amount].name, 32);

cout << "Сумма пожертвования: ";

cin >> Obj[amount].sum;

cin.get();

cout << endl;

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void showData(const Sponsor* Obj, const int amount)

{

system("cls");

cout << "№  " << "Фамилия\t" << "Имя\t" << "Сумма\t" << endl;

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

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

{

cout << i + 1 << "  " << Obj[i].surname << '\t' << Obj[i].name << '\t' << Obj[i].sum << endl;

}

}

Определение структуры находится в строках 5 — 10. В ней объявлены три элемента namesurnamesum. Ниже объявлены прототипы функций, необходимых для решения задачи. Первая функция Sponsor* AddStruct(Sponsor* Obj, const int amount); будет выделять память для элементов массива структур. Вторая voidsetData(Sponsor* Obj, const int amount); отвечает за ввод данных в структуру. Третья void showData(const Sponsor* Obj, const int amount); — выводит на экран все данные в виде таблицы. Определения этих функций мы рассмотрим ниже.

Чтобы создать динамический массив структур, надо, как и для создания обычного динамического массива, объявить указатель. Только вместо встроенного типа указать дескриптор структуры — строка 20. Этот указатель пока ни на что не указывает. Можно было бы выделить память под массив структур сразу. Например:

Но мы организуем более гибкое выделение памяти под этот динамический массив структур — она будет выделяться по необходимости. Есть один спонсор — выделится память под одну структуру. Есть 3 спонсора — память выделится сначала под одну структуру, потом под вторую и далее под третью. Все будет зависеть от того — решит ли пользователь продолжить ввод.

В строках 21 — 22, объявлены переменные sponsorAmount — счетчик количества спонсоров и YesOrNot — выбор пользователя (продолжить или прервать ввод).

Строки 24 — 34: здесь расположен цикл do while. Он выполняется до тех пор, пока пользователю необходимо вводить данные. В строке 26 вызываем функцию, которая выделяет память под структуру OurSponsors = AddStruct(OurSponsors, sponsorAmount);Опустимся к ее определению в строках 42 — 61. Тут видно, что данная функция будет возвращать указатель на структуру Sponsor. Она принимает два параметра — указатель на структуру и количество структур. Когда она вызывается в первый раз — в нее будет передан объявленный в main указатель OurSponsors и переменная sponsorAmount, которая равна нулю. В функции выполнится блок if — выделится память для одной структуры (строки 44 — 47). Потом функция вернет адрес (указатель) на этот участок памяти и он будет записан в OurSponsors — строка 26.

В строке 27 вызываем функцию, которая позволит внести данные в структуру. Её определение находится в строках 63 — 73. После внесения данных, переменная sponsorAmount увеличивается на единицу. Пользователю предлагаем сделать выбор — продолжить ввод или завершить работу. Если продолжаем — снова вызывается функция AddStruct().

Надо помнить, что указатель OurSponsors уже ссылается на участок памяти с записанными данными. Поэтому не получится просто перевыделить память. Сначала необходимо позаботиться о сохранении данных. Посмотрите на блок elseстроки 48 — 59. В строке 50 создаем временный указатель. Под него выделяем память для amount + 1 структур (т.е. на одну структуру больше, чем приняла функция). Далее копируем данные из принятого объекта. Последний объект массива структур tempObj останется незаполненным. Когда данные скопированы, освобождаем память Obj — строка 57 и записываем в этот указатель новый адрес. Теперь он будет указывать на память, в которой есть сохраненные данные и дополнительный выделенный участок памяти для заполнения новыми данными.

И снова вызывается функция setData(), которая позволит внести данные в новый выделенный участок памяти — в последний элемент массива структур.

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

Результат — ввод данных:

Таблица: