Теоретические сведения
При определении статического массива: <тип> <имя_массива> [количество_элементов], имя_массива становится указателем на область памяти, выделяемой для размещения элементов массива. Количество элементов должно быть константой. Таким образом, размеры памяти, выделяемой под массив, заданы в определении массива. Но иногда нужно, чтобы размеры памяти были не фиксированными, а выделялись в ходе выполнения программы при решении конкретной задачи.
Формирование массивов с переменными размерами можно организовать с помощью указателей и средств для динамического выделения памяти. Эти средства описаны в файле <alloc.h>. Функции malloc() и calloc() динамически выделяют память в соответствии со значениями их параметров и возвращают адрес начала выделенного участка памяти. Тип возвращаемого значения указателя void *. Его можно преобразовать к указателю любого типа с помощью явного приведения типа. Функция free(void *) освобождает память, выделенную с помощью malloc() или calloc().
int *p;
p=(int *)malloc(size); //Указателю на целое p присваивается адрес начала выделенной области памяти размером size байт.
p=(int *)calloc(n, size); //Указателю на целое p присваивается адрес начала выделенной области памяти размером n*size байт.
free(p); //Освобождает выделенную по адресу p память. Преобразование указателя любого типа к типу void * осуществляется автоматически, так что в качестве фактического параметра можно подставить указатель любого типа без явного приведения типов.
Пример формирования одномерного динамического массива
//lab11_1
#include <stdio.h>
#include <conio.h>
#include <alloc.h>
main()
{ float *p,d;
int i,n;
printf("\n input n:");
scanf("%d",&n);
p=(float *)malloc(n*sizeof(float));
for (i=0;i<n;i++)
{printf("x[%d]=",i);
scanf("%f",&d);
p[i]=d;
}
for (i=0;i<n;i++)
{ if (i%4==0) printf("\n");
printf("\t x[%d]=%6.2f",i,p[i]);
}
free(p);
getch();
}
Доступ к участкам выделенной памяти выполняется с помощью операции индексирования: p[i].
Каждый элемент массива может быть, в свою очередь, массивом. Именно так конструируются динамические многомерные массивы. Рассмотрим алгоритм создания и обработки двумерного массива.
1 Определяем указатель на массив указателей, задающий адреса начала строк матрицы: тип **uk.
2 Вводим размеры матрицы n,m.
3 Создаём динамический массив указателей на указатели начала строк: uk=(тип **)malloc(n*sizeof(тип *));
4 В цикле выделяем память под n массивов – строк по m элементов в каждом: for (i=0;i<n;i++) uk[i]=(тип *)malloc(m*sizeof(тип));
5 Обработка массива (работа с индексированными элементами uk[i][j]).
6 В цикле освобождаем память, занятую под n массивов – строк: for (i=0;i<n;i++) free(uk[i]);
7 Освобождаем память, занятую под массив указателей: free(uk).
Пример обработки двумерного динамического массива
Составить программу, создающую динамическую матрицу размером n*n, заполнить матрицу случайными числами. Вычислить сумму каждой строки и поместить суммы строк в одномерный динамический массив.
//lab11_2
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <alloc.h>
void main()
{ int n,j,i;
float ** matr; float * mass; // Объявляем matr - указатель на массив указателей //mass – указатель на одномерный массив
clrscr();
printf("Введите размер квадратной матрицы n: "); scanf("%d",&n);
mass=(float *)malloc(n*sizeof(float)); // Выделяем память под массив mass
if (mass==NULL)
{ puts("не создан динамический массив!");
return;}
matr=(float **)malloc(sizeof(float *)*n); // Выделяем память под массив указателей
if (matr==NULL)
{ puts("не создан динамический массив!");
return;}
randomize();
for (i=0;i<n;i++)
{ matr[i]=(float *)malloc(sizeof(float)*n); // Выделяем память под i-ю строку
if (matr[i]==NULL)
{ puts("не создан динамический массив!");
return;}
for (j=0;j<n;j++) matr[i][j]=random(100);
}
for (i=0;i<n;i++)
{ mass[i]=0;
for (j=0;j<n;j++)
mass[i]+=matr[i][j];
}
for (i=0;i<n;i++)
{ for (j=0;j<n;j++)
printf("\t%6.2f",matr[i][j]);
printf("\n");
}
for (i=0;i<n;i++)
printf("\n сумма %d строки %8.2f",i,mass[i]);
for (i=0;i<n;i++)
free(matr[i]); //Освобождаем память i – й строки
free(matr); // Освобождаем память массива указателей
free(mass); // Освобождаем память массива сумм
getch();
}
Выполнение работы
1 Проанализировать приведенные программы.
2 Создать двумерный динамический массив и выполнить задание по своему варианту.
Варианты заданий
1 Даны матрица A размером m*n и вектор В размером m. Записать на главную диагональ элементы вектора, а в вектор - элементы главной диагонали.
2 Выбрать максимальный элемент матрицы С (размер m*n), элементы четных строк разделить на максимальный элемент, а к элементам нечетных прибавить максимальный элемент.
3 Найти минимальный элемент матрицы С (размер m*n), и поменять его местами с первым элементом.
4 Дана матрица Е размером m*n. Вычислить суммы элементов каждого столбца. Определить наибольшее значение этих сумм и номер соответствующего столбца.
5 В матрице К размером m*n найти в каждом столбце произведение отрицательных элементов и количество нулевых элементов в матрице.
6 Даны две матрицы А и В одинаковой размерности m*n. Получить матрицу
C = max (a i j, b i j), и матрицу D = min (a i j, b i j).
7 Дана матрица Р размером m*n. Найти сумму минимальных элементов каждого столбца матрицы.
8 Даны матрицы: А размером m*k и В размером k*n.Получить матрицуС=A*В.
9 Дана матрица К размером m*n. Вычислить сумму минимальных элементов каждого столбца.
10 Дана матрица С размером m*n. Упорядочить эту матрицу по возрастанию элементов в каждом столбце.
11 Дан одномерный массив A из m элементов. Вводится число k (k<m). Получить из А матрицу, по k элементов в строке. Недостающие элементы заменить 0.
12 В матрице Т размером m*k переставить элементы в строках так, чтобы по диагонали они были упорядочены по возрастанию.
5 Контрольные вопросы
1 Отличия динамического массива от статического.
2 Как создать одномерный динамический массив?
3 Как создать динамическую матрицу?
4 Как освобождается память, занятая под динамические структуры?
ЛАБОРАТОРНАЯ РАБОТА №4
Интерфейсы программных продуктов