Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатика
ИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханика
ОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторика
СоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансы
ХимияЧерчениеЭкологияЭкономикаЭлектроника

Приклади програм

Читайте также:
  1. D. Программы использования
  2. I «Волевые* метапрограммы_________________________ 161
  3. I. РАБОЧАЯ ПРОГРАММА
  4. I. РАБОЧАЯ ПРОГРАММА ДИСЦИПЛИНЫ
  5. I. Система прерываний программ в ПК
  6. II. Модульное структурирование содержания образовательной программы
  7. II. Требования к структуре образовательной программы дошкольного образования и ее объему

Теоретичні основи

У мові C для виділення динамічної пам’яті та її вивільнення вико­ристовуються функції calloc(), malloc(), realloc() і free(), заголовки (прототипи) яких описані в заголовковому файлі alloc.h:

void *calloc(unsigned n, unsigned m) – повертає вказівник на початок ділянки динамічної пам’яті для розміщення n елементів по m байт кожен або NULL при невдалому виділенні;

void *malloc(unsigned s) – повертає вказівник на блок динамічної пам’яті довжиною s байт або NULL;

void *realloc(void *bl, unsigned ns) – змінює розмір виділеної динамічної пам’яті з адресою початку bl до розміру ns байт або NULL. Якщо bl == NULL, то функція працює як malloc();

void free(void *bl) – звільнює раніше виділений блок динамічної пам’яті з адресою першого байта bl.

Треба пам’ятати, що функції динамічного розподілу пам’яті мають тип void *. Це обумовлює необхідність приведення типу при зв’язуванні виділе­ної пам’яті з конкретним вказівником:

#include<alloc.h>
//...
char *pchar;
long *plong;
int n = 10;
// Виділення 256 байт під символьний масив
pchar = (char *)malloc(256);
// Виділення пам’яті під масив з n елементів
// типу long
plong = (long *)calloc(n, sizeof(long));
//...
free(pchar); // Вивільнення пам’яті, що
// зв’язана з вказівником pchar
free(plong); // Вивільнення пам’яті, що
// зв’язана з вказівником plong

На відміну від імені масиву звичайний вказівник може змінювати своє значення. Однак у цьому випадку можна загубити можливість пра­вильного вивільнення пам’яті. Справа в тому, що після розподілу пам’яті вказівник зв’язується з першим байтом виділеної ділянки пам’яті. Якщо ж вказівник змінює своє значення, то вивільнення пам’яті з початку виділе­ної ділянки стає неможливим. Тому завжди необхідно зберігати адресу початку виділеної ділянки пам’яті.

Важливим моментом є необхідність перевірки правильності виділення пам’яті. Для цього необхідна перевірка значення вказівника після розподілення пам’яті. Наприклад,

if (pchar!= NULL)...

або

if (pchar)...

У мові C++ існує операція

new ім’я_типу

або

new ім’я_типу ініціалізатор

яка дозволяє виділити ділянку динамічної пам’яті, розмір якої відповідає типу даних, що визначається іменем типу. Ініціалізатор задається виразом у круглих дужках. Якщо пам’ять не може бути виділена, то операція new повертає значення NULL.

Вивільнення пам’яті в мові C++ здійснюється операцією

delete вказівник;

Якщо вивільнюється пам’ять, що виділялася під масив, то операція delete має такий формат:

delete [] вказівник;

У програмі може бути визначений як звичайний вказівник, так і вказівник на масив.

Наприклад,

long *plong; // Вказівник на тип long
long (*plarray)[3][2]; // Вказівник на масив 3х2

Ці вказівники можуть бути зв’язані як з об’єктами статичної пам’яті, так і з об’єктами динамічної пам’яті.

Приклади програм

Приклад 1. Дано натуральне число n і послідовність дійсних чисел , , …, . Вивести члени послідовності в порядку, зворотному по­рядку введення.

Розв’язок.

#include <iostream>
#include <conio.h>

using namespace std;
int main()
{
int n;
double *PtD; // Вказівник на double для створення масиву
cout << "n = ";
cin >> n;
// Відведення пам'яті під n елементів типу double:
PtD = new double[n];
// Те ж засобами мови C:
// PtD = (double *)calloc(n, sizeof(double));
for (int i = 0; i < n; i++) // Цикл уведення масиву
cin >> PtD[i];
for (int i = n - 1; i >= 0; i--) // Цикл виведення масиву
cout << PtD[i] << '\t';
delete [] PtD; // Видалення масиву з пам'яті: free(PtD);
cout << "\nPress any key";
_getch();
return 0;
}

Приклад 2. Дано двовимірний масив дійсних чисел з фіксованою кількістю рядків і стовпців. Розмістити його в динамічній пам’яті і вивести на екран за стовп­цями у вигляді екранних рядків.

 

Розв’язок.

#include <iostream>
#include <conio.h>
using namespace std;
int main(void)
{
float (*pfarr)[3][4]; // Вказівник на масив
// Відведення пам'яті під масив
pfarr = (float(*)[3][4])malloc(sizeof(float[3][4]));
// Аналог:
// pfarr = new float [1][3][4];
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4; j++)
cin >> (*pfarr)[i][j]; // Робота з елементами
// динамічного масиву
// Аналог:
// cin >> pfarr[0][i][j];
for (int j = 0; j < 4; j++)
{
for (int i = 0; i < 3; i++)
cout << (*pfarr)[i][j]; << '\t'; // Робота з
// елементами динамічного масиву
// Аналог:
// cout << pfarr[0][i][j] << '\t';
}
// Видалення масиву з пам'яті
free(pfarr); // Можна: delete [] pfarr;
cout << "\nPress any key";
_getch();
return 0;
}

Приклад 3. Дано натуральне число n і симетрична матриця A розміру n´n з дійсними елементами, що визначена елементами нижнього трикутника під головною діагоналлю і на ній. Отримати матрицю A 2 розміру n´n. Переконатися, що ця матриця теж є симетричною.

Розв’язок.

#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
int n;
// Вказівники на double ** для створення масиву
double **A, **A_2;
cout << "n = ";
cin >> n;
// Відведення пам'яті під n елементів типу double *
A = new double *[n];
// Цикл створення і введення "масиву" з рядками
for (int i = 0; i < n; i++) // різної довжини
{ // Створення рядків з довжинами від 1 до n елементів
A[i] = new double[i];
for (int j = 0; j <= i; j++) // Уведення елементів
cin >> A[i][j]; // рядка "масиву" A
}
A_2 = new double *[n];
for (int i = 0; i < n; i++)
{
A_2[i] = new double[n];
for (int j = 0; j < n; j++)
{
A_2[i][j] = 0;
for (int k = 0; k < n; k++)
{ // Нижче - елементи i-го рядка
double Aik, Akj; // та j-го стовпця
if (k <= i) // Під діагоналлю і на ній
Aik = A[i][k];
else // Над діагоналлю
Aik = A[k][i];
if (k <= j) // Під діагоналлю і на ній
Akj = A[j][k];
else // Над діагоналлю
Akj = A[k][j];
A_2[i][j] += Aik * Akj;
}
}
}
for (int i = 0; i < n; i++) // Цикл виведення
{ // результуючої матриці
for (int j = 0; j < n; j++)
cout << A_2[i][j] << '\t';
cout << endl;
}
for (int i = 0; i < n; i++)
{
delete [] A[i]; // Видалення рядка "масиву" A
delete [] A_2[i]; // Видалення рядка "масиву" A_2
}
delete [] A; // Видалення масиву вказівників
delete [] A_2; // Видалення масиву вказівників
cout << "\nPress any key";
_getch();
return 0;
}

Приклад 4. Дано натуральне число і масив з n дійсних чисел. Отри­мати новий масив з додатних елементів вихідного масиву, записа­ни­х у зворотному порядку відносно початкового. Визначити функцію фор­му­вання вказаного масиву.

Розв’язок.

#include <iostream>
#include <conio.h>
using namespace std;

double * NewPositiveArray(double ** NewArr, int * NewCount,
double * OldArr, int OldCount);

int main()
{
int n, m;
double *A; // Вказівник для створення масиву A
cout << "n = ";
cin >> n;
// Відведення пам'яті під n елементів типу double
A = new double[n];
for (int i = 0; i < n; i++) // Цикл уведення масиву
cin >> A[i];
double *B = NULL; // Вказівник для створення масиву B
B = NewPositiveArray(&B, &m, A, n);
delete [] A; // Видалення масиву A
if (B!= NULL) // Якщо в масиві A є додатні елементи
for (int i = 0; i < m; i++) // Цикл виведення масиву B
cout << B[i] << '\t';
else
cout << "There are no positive numbers\n";
delete [] B; // Видалення масиву B
cout << "\nPress any key";
_getch();
return 0;
}

double * NewPositiveArray(double **NewArr, int *NewCount,
double * OldArr, int OldCount)
{
double *Pt;
*NewCount = 0; // Вважаємо, що додатні елементи відсутні
// Шукаємо перший від кінця масиву OldArr додатний елемент
for (Pt = OldArr + OldCount - 1;
Pt >= OldArr && * Pt <= 0; Pt--);
// Якщо в масиві OldArr відсутні додатні елементи, то Pt
// посилатиметься на елемент перед масивом OldArr; інакше
// Pt посилатиметься на останній додатний елемент в OldArr
if (Pt < OldArr) // Якщо додатні елементи відсутні,
return *NewArr = NULL; // то *NewArr отримує значення
// NULL, яке повертає функція в точку її виклику
// Нижче підраховуємо
for (double *Pt1 = Pt; Pt1 >= OldArr; Pt1--) // кількість
if (*Pt1 > 0) // додатних елементів, тобто
(*NewCount)++; // розмір нового масиву
*NewArr = new double[*NewCount]; //Створюємо новий масив
// Оскільки Pt посилається на останній додатний елемент,
for (int i = 0; i < *NewCount; Pt--) // йдемо від нього до
if (*Pt > 0) // початку масиву OldArr і переписуємо
(*NewArr)[i++] = *Pt; // додатні значення в *NewArr
return *NewArr; //Повертаємо адресу першого елемента
}


Дата добавления: 2015-12-08; просмотров: 43 | Нарушение авторских прав



mybiblioteka.su - 2015-2024 год. (0.009 сек.)