Лекция_1._Динамические_массивы_Программирование_2семестр (1271737), страница 2
Текст из файла (страница 2)
#include <conio.h>
#include <stdlib.h>
void main()
{ int *a, n, i;// a – указатель на одномерный массив,
//n – число элементов массива, i-счетчик элементов массива.
cout<<"Input the number of elements\n";//приглашение к вводу n
cin>>n; // ввод числа элементов массива n
a=(int*)malloc(n*sizeof(int));
// выше - распределение памяти под динамический массив
cout<<"Input elements\n"; //приглашение к вводу массива
for (i=0;i<n;i=i+1)
cin>>a[i];// в цикле вводится массив
// далее каждый элемент массива заменяется своим квадратом
for (i=0;i<n;i=i+1)
a[i]=a[i]*a[i];
cout<<"Squares of elements:\n";//пояснение выводимых значений
//далее в цикле выводится массив
for (i=0;i<n;i=i+1)
cout<<a[i]<<" ";
cout<<endl;
_getch();//задержка экрана для просмотра результатов
free(a);//освобождение памяти из-под массива
}
Пример 2. Работа с динамической матрицей.
#include <iostream.h>
#include <conio.h>
#include <stdlib.h>
void main()
{ int **a, n,m, i,j;
//a-указатель на массив указателей на строки матрицы
//n-число строк, m-число столбцов;
cout<<"Input n,m\n";//приглашение к вводу n и m
cin>>n>>m;// ввод n и m
a=(int**)malloc(n*sizeof(int*)); //распределение памяти под
// массив указателей на строки матрицы
cout<<"Input matrix\n";//приглашение к вводу матрицы
for (i=0;i<n;i=i+1)//цикл ввода по строкам
{
a[i]=(int*)malloc(m*sizeof(int));// распределение памяти
//под i-ую строку
for (j=0;j<m;j=j+1) // в цикле вводятся элементы i-й строки
cin>>a[i][j];//*(*(a+i)+j)
}//ввод закончен
for (i=0;i<n;i=i+1)//в цикле каждый элемент матрицы удваивается
for (j=0;j<m;j=j+1)
a[i][j]=2*a[i][j];
cout<<"The changed matrix:\n";//пояснение выводимых значений
//далее в цикле выводится матрица и овсобождается память
for (i=0;i<n;i=i+1)
{for(j=0;j<m;j=j+1)
cout<<a[i][j]<<" ";
cout<<endl;
free (a[i]);
}
_getch();
free(a);
}
5. Операции Си++ для распределения и освобождения памяти
Для упрощения работы с динамической памятью в Си++ введены операции выделения (new) и освобождения (delete).
Самый простой способ использования операция new:
указатель=new тип;
Указатель должен быть объявлен с помощью тип*.
Операция new выделяет ячейку памяти заданного типа и и присваивает значение адреса ячейки указателю. После типа в круглых скобках можно указать инициализирующее значение, а в квадратных – количество выделяемых ячеек. В большинстве реализаций языка Си++ одновременно круглые и квадратные скобки не допускаются.
Примеры:
int *ip = new int; /* создание объекта типа int и получение указателя на него */
int ip2 = new int(2); /* то же с установкой начального
значения 2 */
double *dblArray = new double [10]; /* распределение памяти под массив из 10 элементов типа double */
int **matr = new int [m][n]; /* распределение в памяти
целочисленной матрицы из m строк и n столбцов */
Операция delete освобождает память, выделенную с помощью new. Вызов delete осуществляется следующим образом:
delete указатель;
delete [] указатель;//квадратные скобки нужны для массивов
Пример 3. Работа с динамическим одномерным массивом с помощью new и delete.
#include <iostream.h>
#include <conio.h>
void main()
{int *a, n, i;
cout<<"Input the number of elements\n";
cin>>n;
a=new int[n];
//распред-ие памяти под динамич. массив
cout<<"Input elements\n";
for (i=0;i<n;i=i+1)
cin>>a[i];//*(a+i)
for (i=0;i<n;i=i+1)
a[i]=a[i]*a[i];
cout<<"Squares of elements:\n";
for (i=0;i<n;i=i+1)
cout<<a[i]<<" ";
cout<<endl;
_getch();
delete [] (a);
}
Пример 4. Работа с динамической матрицей с помощью new и delete.
#include <iostream.h>
#include <conio.h>
void main()
{ int **a, n,m, i,j;
cout<<"Input n,m\n";
cin>>n>>m;
a=new int*[n];
cout<<"Input matrix\n";
for (i=0;i<n;i=i+1)
{a[i]=new int[m];
for (j=0;j<m;j=j+1)
cin>>a[i][j];//*(*(a+i)+j)
}
for (i=0;i<n;i=i+1)
for (j=0;j<m;j=j+1)
a[i][j]=2*a[i][j];
cout<<"The changed matrix:\n";
for (i=0;i<n;i=i+1)
{ for(j=0;j<m;j=j+1)
cout<<a[i][j]<<" ";
cout<<endl;
delete [] (a[i]);
}
delete [] a;
_getch();
}
6. Параметры функций типа тип**
Одним из основных ограничением использования статических массивов является необходимость объявление размеров массива «по максимуму», с запасом, в том случае если размеры заранее неизвестны (например, задаются вводом). Для матриц, являющих формальными параметрами функций, «по максимуму» должно задаваться число столбцов ‑ см,, например. раздел 2.
Как следует из предыдущего параграфа, положение одномерного массива в памяти определяется указателем на начало массива, то есть значением типа тип*, где тип – это тип элементов массива. Можно объявить формальный параметр, являющийся одномерным массивом, как было показано в разделе 2 (см. прототип функции masout): float a[]; но можно объявить его и с использованием указателя: float* a; в последнем случае фактическим параметром может быть как динамический, так и статический или локальный массив.
Положение матрицы в памяти определяется указателем тип**, где тип – это тип элементов матрицы. Можно тип** использовать для объявления формального параметра, являющегося матрицей, но тогда фактический параметр должен быть обязательно динамическим массивом.
Пример 5. Использование формального параметра типа float** для обработки матриц: вычисление суммы элементов матрицы.
#include <iostream.h>
#include <conio.h>
float sum(float **a, int n, int m);
void main()
{ float **a; int n,m, i,j;
cout<<"Input n,m"<<endl;
cin>>n>>m;
a=new float*[n];
for (i=0;i<n;i++)
{ a[i]=new float[m];
for (j=0;j<m;j++)
cin>>a[i][j];
}
cout<<"sum="<<sum(a,n,m)<<endl;
_getch();
for (i=0;i<n;i++)
delete [] a[i];
delete [] a;
float sum(float **a, int n, int m)
{
float s; int i,j;
s=0;
for (i=0;i<n;i++)
for(j=0;j<m;j++)
s=s+a[i][j];
return (s);
}
Если подпрограммы следует применять для обработки нескольких матриц, то лучше сделать функцию ввода матрицы и в нее включить распределение памяти под динамические матрицы. Тогда указатель на матрицу в динамической памяти является результатом функции ввода и должен возвращаться из функции в вызывающий код, например, через имя функции.
Пример 6. Функция, распределяющая матрицу в динамической памяти и осуществляющая ее ввод:
float** input(int n, int m, char c)
{
int i, j;
float **mat;
cout<<”Input “<<c<<” size of ”<<n<<”*”<<m<<endl;
mat = new float* [n];
for (i = 0; i < n; i++)
{
mat[i] = new float[m];
for (j = 0; j < m; j++)
{
cin >> mat[i][j];
}
cout << endl;
}
return mat;
}
Вызов фунции input будет осуществляться, например, так:
float **A, **B;
A = input(3, 5);
B = input(7, 3);
Кроме того, имеет смысл написать функцию дя освобождения памяти из-под матрицы:
void delMat(float** mat, int n)
{
for (int i = 0; i < n; i++)
{
delete[] mat[i];
}
delete[] mat;
}
1 англ. memory allocation, выделение памяти.
2 Под типом size_t в MS Visual Studio 2008 подразумевается unsigned int.
3 англ. clear allocation, чистое выделение памяти.
4 англ. reallocation, перераспределение памяти.
5 англ. free, освободить
13