- •Лабораторна робота № 6
- •6. 1. Короткі теоретичні відомості Особливості застосування покажчиків
- •Зв'язок покажчиків з масивами
- •Декларація багатовимірного масиву :
- •Покажчики на покажчики
- •Динамічне розміщення даних
- •6. 2.2. Приклад створення консольного застосування
- •6.3. Індивідуальні завдання
- •6.4. Індивідуальні завдання
Динамічне розміщення даних
Для створення масивів зі змінною розмірністю використовується динамічне розміщення даних, що декларуються покажчиками.
Для роботи з динамічною пам'яттю використовуються стандартні функції бібліотеки alloc.h:
void *malloc(size) і void *calloc(n, size) - виділяють блок пам'яті розміром size і n(size байт відповідно; повертають покажчик на виділену область, при помилці - значення NULL;
void free(bf); - звільняє раніше виділену пам'ять з адресою bf.
Іншим, прийнятнішим підходом до динамічного розподілу пам'яті є використання операцій мови З++ new і delete.
Операція new повертає адресу ОП, відведеною під динамічно розміщений об'єкт, при помилці - NULL, а операція delete звільняє пам'ять.
Мінімальний набір дій, необхідних для динамічного розміщення одновимірного масиву дійсних чисел розміром n :
double *а;
. . .
а = new double[n]; // Захоплення пам'яті для n елементів
. . .
delete []а; // Звільнення пам'яті
Мінімальний набір дій, необхідних для динамічного розміщення двомірного масиву дійсних чисел розміром n(m :
int i, n, m; // n, m - розміри масиву
double **a;
a = new double *[n]; // Захоплення пам'яті під покажчики
for(i=0; i<n; i++) a[i] = new double [m]; // і під елементи
. . .
for(i=0; i<n; i++) delete []a[i]; // Звільнення пам'яті
delete []a;
Для сучасних компіляторів (версій старше «6») для звільнення пам'яті досить записати тільки delete []a;
6.2. Приклад виконання завдання
Розрахувати значення вектору _, де А - квадратна матриця розміром N(N, а Y і B - одновимірні масиви розміром N. Елементи вектору Y визначаються по формулі _.
6. 2.1. Приклад створення віконного застосування
Значення N вводити з Edit, А і B - з компонент StringGrid. Результат вивести в компоненту StringGrid.
Панель діалогу і результати виконання програми приведена на мал. 6.1.
Мал. 6.1
Налаштування компонент StringGrid
Для компоненти StringGrid1 значення ColCount і RowCount встановите рівними, наприклад, 3 - три стовпці і три рядки, а FixedCols і FixedRows - 1.
Оскільки компоненти StringGrid2 і StringGrid3 мають тільки один стовпець, то у них ColCount = 1, RowCount = 3, а FixedCols = 0 і FixedRows = 1.
У властивості Options рядок goEditing для компонент StringGrid1 і StringGrid2 встановите в положення true.
Для зміни розміру n використовується функція-обробник EditChange, отримана подвійним клацанням по компоненті Edit.
Текст програми може мати наступний вигляд:
. . .
//---------------------- Глобальні змінні -------------------
int n = 3;
double **a, *b; // Декларації покажчиків
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
Edit1 ->Text=IntToStr(n);
StringGrid1 ->ColCount = n+1; StringGrid1 ->RowCount = n+1;
StringGrid2 ->RowCount = n+1; StringGrid3 ->RowCount = n+1;
// Введення в лівий верхній елемент таблиці назви масивів
StringGrid1 ->Cells[0][0] = "Матриця A";
StringGrid2 ->Cells[0][0] = "Масив B";
StringGrid3 ->Cells[0][0] = "Масив Y";
for(int i=1; i<=n;i++){
StringGrid1 ->Cells[0][i]="i="+IntToStr(i);
StringGrid1 ->Cells[i][0]="j="+IntToStr(i);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Edit1Change(TObject *Sender)
{
int i;
n=StrToInt(Edit1 ->Text);
StringGrid1 ->ColCount = n+1; StringGrid1 ->RowCount = n+1;
StringGrid2 ->RowCount = n+1; StringGrid3 ->RowCount = n+1;
for(i=1; i<=n;i++){
StringGrid1 ->Cells[0][i]="i="+IntToStr(i);
StringGrid1 ->Cells[i][0]="j="+IntToStr(i);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
double s;
int i, j;
a = new double*[n]; // Захоплення пам'яті під покажчики
for(i=0; i<n;i++) a[i] = new double[n]; // Захоплення пам'яті під елементи
b = new double[n];
// Заповнення масивів А і В елементами з таблиць StringGrid1 і StringGrid2
for(i=0; i<n;i++){
for(j=0; j<n;j++) a[i][j]=StrToFloat(StringGrid1 ->Cells[j+1][i+1]);
b[i]=StrToFloat(StringGrid2 ->Cells[0][i+1]);
}
// Множення рядка матриці А на вектор В і виведення результату s в StringGrid3
for(i=0; i<n;i++){
for(s=0, j=0; j<n;j++) s += a[i][j]*b[j];
StringGrid3 ->Cells[0][i+1] = FloatToStrF(s, ffFixed, 8,2);
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
delete []a;
delete []b;
ShowMessage("Пам'ять звільнена"!);
Close();
}