ТЕМА 5. Указатели и их использование при работе с динамическими массивами

Организация динамического распределния памяти осуществляется в свободной от загруженных программ области оперативной памяти, называемой кучей (heap). Для этого используются процедуры New, Dispose или GetMem, FreeMem.

Процедура

Организация динамического распределния памяти осуществляется в свободной от загруженных программ области оперативной памяти, называемой кучей (heap). Для этого используются процедуры New, Dispose или GetMem, FreeMem.

Процедура

       New(var P: Pointer);

выделяет участок памяти, размер которого определяется типом указателя P. Указателю P присваивается адрес первого байта этого участка. После того как необходимость работы с этой переменной отпала, данный участок памяти освобождается с помощью процедуры

Dispose(var P: Pointer);

После освобождения адрес в указателе P остается, однако доступ к ячейке с этим адресом запрещен.

Например:

Var  a, b : PInt; 

begin

               New(a);

                       b:=a;

                       a^:=9;

                       b^:=5

                       Write(a);  // Распечатается 58

               …

Dispose(b);

Здесь выделена память под переменную типа integer. Указать b стал указывать на ту же область памяти, что и указатель a . В выделенную область сначала занесено значение, равное 9, затем туда же значение равное 5. Для освобождения памяти можно использовать как Dispose(b) так и Dispose(a).

Процедура GetMem используется при работе как с типизированными, так и с нетипизированными указателями, поэтому задается не только имя указателя, но и объем необходимой памяти в байтах:

       GetMem(P:pointer;size:Word);

Процедура

       FreeMem(P:pointer;size:Word);

освобождает область памяти, связанную с указателем Р, и имеющую размер, равный size.

Для определения размера, который требуется выделить под переменную обычно пользуются функцией sizeof(<имя типа>).

5.2. Организация динамических массивов

Обычно динамическое выделение и освобождение памяти используется при работе с большими массивами данных.

В случае, когда максимальные размеры массива заранее известны, динамическое распределение памяти может быть организовано следующим образом:

               type        Tmas = array[1..1000, 1..2000] of byte;

                       Pmas = ^Tmas

               var        B : Pmas                 // Указатель на динамический массив

       begin

               New(B);                 .. Выделение памяти

                       <работа с массивом>

               Dispose(B);  // Освобождение памяти

При такой организации память выделяется нерационально и заведомо с избытком, при этом всегда нужно помнить об ограничении на индексы.

С помощью процедур Getmem и Freemem можно создавать массивы с изменяемым размером – динамические массивы. Для этого определим тип указателя на массив с небольшим размером, а затем выделим памяти столько, сколько необходимо:

type

       Tmas=array[1..1] of extended;

       Pmas=^Tmas;  // Указатель на массив

  Var a : Pmas;

  mt, n : word;

begin

       mt:=sizeof(extended); // Определение количества байт,

  // которое занимает указанный тип данных

  GetMem(a,mt*n);  // Выделение памяти под n чисел

                <работа с массивом размерности n>

  FreeMem(a, mt*n);  // Освобождение памяти

При работе с такой программой необходимо отключать проверку выхода индекса за пределы массива и внимательно следить за тем, чтобы индекс не вышел за пределы выделенной памяти.

Организация двумерного динамического массива реализуется следующим образом:

       Type

TMas = array[1..1] of integer;

  PMas = ^TMas;

TMas2 = array[1..1] of  PMas;

                PMas2 = ^TMas2;

  Var

               a : PMas2;

N,M,i,j : integer;

  begin

  GetMem(a,4*M);

  for i:=1 to M do GetMem(a[i],N*sizeof(integer));

  // Работа с массивом а[i,j], 1≤i≤M, 1≤j≤N

  for i:=1 to M do FreeMem(a[i],N*sizeof(integer));

  FreeMem(a,4*M);

5.3. Компонент TBitBtn

Компонент TBitBtn расположен на странице Additonal палитры компонентов и представляет собой разновидность стандартной кнопки TButton. Его отличительная особенность – наличие растрового изображения на поверхности кнопки, которое определяется свойством Clyph. Кроме того, имеется свойство Kind, которое задает одну из 11 стандартных разновидностей кнопок. Кнопка bkClose закрывает главное окно и завершает работу программы.

5.4. Пример написания программы

Задание: Дан массив, состоящий из семи цифр. Упорядочить элементы массива по возрастанию. Панель диалога приведена на рис. 5.1.

Рис. 5.1.

Текст программы приведен на Листинге 5.1.

Листинг 5.1.

unit Unit5;

interface

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, StdCtrls, Buttons, Grids;

type

  TForm1 = class(TForm)

  StringGrid1: TStringGrid;

  StringGrid2: TStringGrid;

  Label1: TLabel;

  Label2: TLabel;

  BitBtn1: TBitBtn;

  BitBtn2: TBitBtn;

  procedure FormCreate(Sender: TObject);

  procedure BitBtn1Click(Sender: TObject);

  private

  { Private declarations }

  public

  { Public declarations }

  end;

const N=7;

Type

       TMas = array[1..1] of integer;

  PMas = ^TMas;

var

  Form1: TForm1;

         a : PMas;

          i,j,t  :  integer;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);

begin

Randomize;

  for i:=1 to N do

  StringGrid1.Cells[i-1,0]:=IntToStr(Random(100));

end;

procedure TForm1.BitBtn1Click(Sender: TObject);

begin

GetMem(a,N*sizeof(integer));

  for i:=1 to N do

  a[i]:=StrToInt(StringGrid1.Cells[i-1,0]);

  for i:=1 to N-1 do

  for j:=i+1 to N do

  if a[i]>a[j] then begin

  t:=a[i];

  a[i]:=a[j];

  a[j]:=t;

  end;

  for i:=1 to N do

  StringGrid2.Cells[i-1,0]:=IntToStr(a[i]);

  FreeMem(a,N*sizeof(integer));

end;

end.

5.4. Выполнение индивидуальные задания

а). Выполните задачу из п. 4.6 используя двумерный динамический массив.

б). По указанию преподавателя выберите вариант задачи. Нарисуйте схему алгоритма. Выделение памяти под массив организовать динамически. Организуйте ввод данных из StringGrid1. Вывод организовать, в зависимости от варианта, в StringGrid2, или в Edit1.

1. Дан массив, состоящий из символов. Расположить его элементы в обратном порядке.

2. Дан массив, состоящий из символов. Преобразовать его по следующему правилу: сначала должны находиться цифры, а затем все остальные символы, сохраняя при этом взаимное расположение символов в каждой из этих двух групп.

3. Дан массив, состоящий из символов. Вывести на экран цифру, наиболее часто встречающуюся в этом массиве.

4. Дан массив, состоящий из символов. Определить количество различных элементов массива (т.е. повторяющиеся элементы считать один раз).

5. Дан массив, состоящий из символов. Элементы массива циклически сдвинуть на k позиций влево.

6. Дан массив, состоящий из символов. Элементы массива циклически сдвинуть на n позиций вправо.

7. Дан массив, состоящий из символов. Преобразовать массив по следующему правилу: все отрицательные элементы массива перенести в начало, а все остальные – в конец, сохраняя исходное взаимное расположение, как среди отрицательных, так и среди остальных элементов.

8. Элементы каждого из массивов X и Y упорядочены по возрастанию Объединить элементы этих двух массивов в один массив Z так, чтобы они снова оказались упоряченными по возрастанию.

9. Дан массив, состоящий из символов. Определить, симметричен ли он, т.е. читается ли он одинаково слева направо и справа налево.

10. Дано два массива. Найти наименьшее среди тех элементов первого массива, которые не входят во второй массив.

11. Определить количество инверсий в этом массиве X (т.е. таких пар элементов, в которых большее число находится слева от меньшего: xi>xj при i<j).

12. Дан массив из строчных латинских букв. Вывести на экран в алфавитном порядке все буквы, которые входят в этот текст по одному разу.

13. Дан массив, состоящий из символов. Удалить из него повторные вхождения каждого символа.

14. Дан массив, состоящий из цифр. Удалить из него все четные числа.

15. Дан массив, состоящий из цифр. Удалить из него все отрицательные числа.

Вы здесь: