Поиск

Полнотекстовый поиск:
Где искать:
везде
только в названии
только в тексте
Выводить:
описание
слова в тексте
только заголовок

Рекомендуем ознакомиться

Информатика, программирование->Конспект
В последнее время все большее распространение приобретают электронные офисы, оборудование и сотрудники которых могут находиться в разных помещениях. Н...полностью>>
Информатика, программирование->Шпаргалка
Объективность информатизации следует из закона “необходимого разнообразия”, сформулированного У. Р. Эшби1. Данный закон имеет фундаментальное значение...полностью>>
Информатика, программирование->Контрольная работа
Использование мультипрограммирования для повышения пропускной способности компьютера главной целью является минимизация простоев всех устройств компью...полностью>>
Информатика, программирование->Лекция
В философском понимании информация есть отражение реального мира, т.е. сведения, которые один реальный объект содержит о другом реальном объекте. Приз...полностью>>

Главная > Лекция >Информатика, программирование

Сохрани ссылку в одной из сетей:

Динамические переменные

Динамической переменной называется переменная, память для которой выделяется во время работы программы. Выделение памяти для динамической переменной осуществляется вызовом процедуры new. У процедуры new один параметр – указатель на переменную того типа, память для которой надо выделить. Например, если р является указателем на тип real, то в результате выполнения процедуры new(p); будет выделена память для переменной типа real (создана переменная типа real), и переменная-указатель р будет содержать адрес памяти, выделенной для этой переменной. У динамической переменной нет имени, поэтому обратиться к ней можно только при помощи указателя.

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

Например, если р – указатель на динамическую переменную, память для которой выделена инструкцией new(p), то инструкция dispose (р) освобождает занимаемую динамической переменной память. Следующая процедура демонстрирует создание, использование и уничтожение динамических переменных.

Листинг 3. Создание, использование и уничтожение динамических переменных

procedure TForm1.Button1Click(Sender: TObject); var

p1,p2,p3: ^Integer; // указатели на переменные типа integer

begin

// создадим динамические переменные типа integer

// (выделим память для динамических переменных)

New(p1);

New(p2);

New(p3);

р1^ := 5;

р2^ := 3;

р3^ := р1^ + р2^;

ShowMessage('Сумма чисел равна ' + IntToStr(р3^));

// уничтожим динамические переменные

// (освободим память, занимаемую динамическими переменными)

Dispose(p1);

Dispose(р2);

Dispose(р3);

end;

В начале работы процедура создает три динамические переменные. Две переменные, на которые указывают p1 и р2, получают значение в результате выполнения инструкции присваивания. Значение третьей переменной вычисляется как сумма первых двух.

Списки

Указатели и динамические переменные позволяют создавать сложные динамические структуры данных, такие как списки и деревья.

Каждый элемент списка (узел) представляет собой запись, состоящую из двух частей. Первая часть - информационная. Вторая часть отвечает за связь со следующим и, возможно, с предыдущим элементом списка. Список, в котором обеспечивается связь только со следующим элементом, называется односвязным. Для того чтобы программа могла использовать список, надо определить тип компонентов списка и переменную-указатель на первый элемент списка. Ниже приведен пример объявления компонента списка студентов:

type

TPStudent = ^TStudent; // указатель на переменную типа TStudent

// описание типа элемента списка

TStudent = record

surname: string[20]; // фамилия

name: string[20]; // имя

group: integer; // номер группы

address: string[60]; // домашний адрес

next: TPStudent; // указатель на следующий элемент списка

end;

var

head: TPStudent; // указатель на первый элемент списка

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

Следующая программа формирует список студентов, добавляя фамилии в начало списка. Данные вводятся в поля редактирования диалогового окна программы и добавляются в список нажатием кнопки Добавить (Button1).

Листинг 4. Добавление элемента в начало динамического списка

unit dlist1_;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Label1: TLabel;

Label2: TLabel;

Label3: TLabel;

Edit1: TEdit; // фамилия

Edit2: TEdit; // имя

Button1: TButton; // кнопка Добавить

Button2: TButton; // кнопка Показать

procedure ButtonlClick(Sender: TObject);

procedure Button2Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM)

type

TPStudent=^TStudent; // указатель на тип TStudent

TStudent = record

f_name:string[20]; // фамилия

l_name: string[20]; // имя

next: TPStudent; // следующий элемент списка

end;

var

head: TPStudent; // начало (голова) списка

// добавить элемент в начало списка

procedure TForml.Button1Click(Sender: TObject);

var

curr: TPStudent; // новый элемент списка

begin

new(curr); // выделить память для элемента списка

curr^.f_name := Edit1.Text;

curr^.1_name := Edit2.Text;

// добавление в начало списка

curr^.next := head;

head := curr;

// очистить поля ввода

Edit1.text:=' ';

Edit2.text: = ' ' ;

end;

// вывести список

procedure TForml.Button2Click(Sender: TObject);

var

curr: TPStudent; // текущий элемент списка

n:integer; // длина (кол-во элементов) списка

st:string; // строковое представление списка

begin

n := 0;

st := ' ';

curr := head; // указатель на первый элемент списка

while curr <> NIL do begin

n := n + 1;

st := st + curr^.f_name + ' ' + curr^.1_name + #13;

curr := curr^.next; // указатель на следующий элемент

end;

if n <> 0 then ShowMessage('Список:' + #13 + st)

else ShowMessage('В списке нет элементов.');

end;

end.

Добавление элемента в список выполняет процедура TForm1.Button1Click, которая создает динамическую переменную-запись, присваивает ее полям значения, соответствующие содержимому полей ввода диалогового окна, и корректирует значение указателя head. Вывод списка выполняет процедура TForm1.Button2Click, которая запускается нажатием кнопки Показать. Для доступа к элементам списка используется указатель curr. Сначала он содержит адрес первого элемента списка. После того как первый элемент списка будет обработан, указателю curr присваивается значение поля next той записи, на которую указывает curr. В результате этого переменная curr содержит адрес второго элемента списка. Таким образом, указатель перемещается по списку. Процесс повторяется до тех пор, пока значение поля next текущего элемента списка (элемента, адрес которого содержит переменная curr) не окажется равно NIL.

Упорядоченный список

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

Добавление элемента в список

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

Следующая программа формирует список, упорядоченный по полю Фамилия. Данные вводятся в поля редактирования (Edit1 и Edit2) и нажатием кнопки Добавить (Button1) добавляются в список таким образом, что список всегда упорядочен по полю Фамилия.

Листинг 5. Добавление элементов в упорядоченный список

unit dlist2_;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Label1: TLabel;

Label2: TLabel;

Button1: TButton;

Button2: TButton;

Label3: TLabel;

Edit1: TEdit;

Edit2: TEdit;

procedure ButtonlClick(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure FormActivate(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

($R *.DFM}

type

TPStudent = ^TStudent; //указатель на тип TStudent

TStudent = record

f_name:string[20]; // фамилия

l_name:string[20]; // имя

next: TPStudent; // следующий элемент списка

end;

var

head: TPStudent; // начало (голова) списка

// добавить элемент в список

procedure TForm1.Button1Click(Sender: TObject);

var

node: TPStudent; // новый узел списка

curr: TPStudent; // текущий узел списка

pre: TPStudent; // предыдущий, относительно curr, узел

begin

new(node); // создание нового элемента списка

node^.f_name:=Edit1.Text; // фамилия

node^.l_name:=Edit2.Text; // имя

// добавление узла в список

// сначала найдем в списке подходящее место для узла

curr:=head;

pre:=NIL;

{ Внимание!

Если приведенное ниже условие заменить

на (node. f_name>curr^. f__name) and (curr<>NIL) ,

то при добавлении первого узла возникает ошибка времени

выполнения, т. к. curr = NIL и, следовательно,

переменной curr. ^name нет!

В используемом варианте условия ошибка не возникает, т. к.

сначала проверяется условие (curr <> NIL), значение которого

FALSE, и второе условие в этом случае не проверяется.

}

while (curr<> NIL) and (node.f_name > curr^.f_name) do

begin

// введенное значение больше текущего

pre:= curr;

curr:=curr^.next; // к следующему узлу

end;

if pre = NIL then

begin

// новый узел в начало списка

node^. next: =head;

head:=node;

end

else

begin

// новый узел после pre, перед curr

node^.next:=рre^.next;

рrе^.next:=node;

end;

Edit1.text:=' ';

Edit2.text:=' ';

Edit1.SetFocus;

end;

// отобразить список

procedure TForm1.Button2Click(Sender: TObject);

var

curr: TPStudent; // текущий элемент списка

n:integer; // длина (кол-во элементов) списка

st:string; // строковое представление списка

begin

n:=0;

st: = ' ';

curr:=head;

while curr <> NIL do

begin n:=n+l;

st:=st+curr^.f_name+' '+curr^.l_name+#13;

curr:=curr^.next;

end;

if n <> 0 then ShowMessage('Список: '+#13+st)

else ShowMessage('В списке нет элементов.');

end;

// начало работы программы

procedure TForm1.FormActivate(Sender: TObject);

begin

head:=NIL; // список пустой

end;

end.

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

Вывод списка выполняет процедура TForml.Button2Сlick, которая запускается нажатием кнопки Показать. После запуска программы и ввода нескольких фамилий, например, в такой последовательности: Иванов, Яковлев, Алексеев, петров, список выглядит так, как показано на рис.

Удаление элемента из списка

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

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

var

р: ^integer;

begin

new(p);

{ инструкции программы }

dispose(p);

end

создается динамическая переменная р, а затем она уничтожается. Освободившуюся память смогут использовать другие переменные. Если этого не сделать, то, возможно, из-за недостатка свободной памяти в какой-то момент времени программа не сможет создать очередную динамическую переменную.

Следующая программа позволяет добавлять и удалять узлы упорядоченного списка. Процедуры добавления узла в список и вывода списка, а также объявление типа узла списка ничем не отличаются от соответствующих процедур рассмотренной ранее программы Упорядоченный динамический список 2, поэтому они здесь не приводятся. Удаление узла из списка выполняет процедура TForm1.Button3Click, которая запускается нажатием кнопки Удалить (Buttons). .

Листинг 6. Удаление узла из списка

unit dlist3_;

interface

uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Label1: TLabel;

Label2: TLabel;

Button1: TButton;

Button2: TButton;

Label3: TLabel;

Edit1: TEdit;

Edit2: TEdit;

Button3: TButton;

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure FormActivate(Sender: TObject);

procedure Button3Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;

var

Form1: TForm1;

implementation

{$R *.DFM}

type

TPStudent=^TStudent; //указатель на тип TStudent

TStudent = record

f_name:string[20]; // фамилия

l_name:string[20]; // имя

next: TPStudent; // следующий элемент списка

end;

var

head: TPStudent; // начало (голова) списка

procedure TForm1.Button1Click(Sender: TObject);

var

node: TPStudent; // новый узел списка

curr: TPStudent; // текущий узел списка

pre: TPStudent; // предыдущий, относительно curr, узел

begin

new(node); // создание нового элемента списка

node^.f_name:=Edit1.Text; // фамилия

node^.l_name:=Edit2.Text; // имя

// добавление узла в список

// сначала найдем в списке подходящее место для узла

curr:=head;

pre:=NIL;

{ Внимание!

Если приведенное ниже условие заменить

на (node. f_name>curr^. f__name) and (curr<>NIL) ,

то при добавлении первого узла возникает ошибка времени

выполнения, т. к. curr = NIL и, следовательно,

переменной curr. ^name нет!

В используемом варианте условия ошибка не возникает, т. к.

сначала проверяется условие (curr <> NIL), значение которого

FALSE, и второе условие в этом случае не проверяется.

}

while (curr<> NIL) and (node.f_name > curr^.f_name) do

begin

// введенное значение больше текущего

pre:= curr;

curr:=curr^.next; // к следующему узлу

end;

if pre = NIL then

begin

// новый узел в начало списка

node^. next: =head;

head:=node;

end

else

begin

// новый узел после pre, перед curr

node^.next:=рre^.next;

рrе^.next:=node;

end;

Edit1.text:=' ';

Edit2.text:=' ';

Edit1.SetFocus;

end;

// отобразить список

procedure TForm1.Button2Click(Sender: TObject);

var

curr: TPStudent; // текущий элемент списка

n:integer; // длина (кол-во элементов) списка

st:string; // строковое представление списка

begin

n:=0;

st: = ' ';

curr:=head;

while curr <> NIL do

begin n:=n+l;

st:=st+curr^.f_name+' '+curr^.l_name+#13;

curr:=curr^.next;

end;

if n <> 0 then ShowMessage('Список: '+#13+st)

else ShowMessage('В списке нет элементов.');

end;

procedure TForm1.Button2Click(Sender: TObject);

var

curr: TPStudent; // текущий элемент списка

n:integer; // длина (кол-во элементов) списка

st:string; // строковое представление списка

begin

n:=0;

st: = ' ';

curr:=head;

while curr <> NIL do

begin n:=n+l;

st:=st+curr^.f_name+' '+curr^.l_name+#13;

curr:=curr^.next;

end;

if n <> 0 then ShowMessage('Список: '+#13+st)

else ShowMessage('В списке нет элементов.');

end;

// начало работы программы

procedure TForm1.FormActivate(Sender: TObject);

begin

head:=NIL; // список пустой

end;

procedure TForm1.FormActivate(Sender: TObject);

begin

head:=NIL; // список пустой

end;

login

// щелчок на кнопке Удалить

procedure TForm1.Button3Click(Sender: TObject);

var

curr:TPStudent; // текущий проверяемый узел

pre: TPStudent; // предыдущий узел

found:boolean; // TRUE – узел, который надо удалить, если в списке

begin

if head = NIL then

begin

MessageDlg('Список пустой!',mtError,[mbOk],0);

Exit;

end;

curr:=head; // текущий узел – первый узел

pre:=NIL; // предыдущего узла нет

found:=FALSE;

// найти узел, который надо удалить

while (curr <> NIL) and (not found) do

begin

if (curr^.f_name = Edit1.Text) and (curr^.l_name = Edit2.Text) then

found:=TRUE // нужный узел найден

else // к следующему узлу

begin

pre:=curr;

curr:=curr^.next;

end;

end;

if found then

begin

// нужный узел найден

if MessageDlg('Узел будет удален из списка!', mtWarning,[mbOk,mbCancel],0) <> mrYes

then Exit;

// удаляем узел

if pre = NIL then head:=curr^.next // удаляем первый узел списка

else pre^.next:=curr.next;

Dispose(curr);

MessageDlg('Узел' + #13 + 'Имя:'+Edit1.Text + #13 + 'Фамилия:' + Edit2.Text + #13 +

'удален из списка.', mtInformation,[mbOk],0);

end

else // узла, который надо удалить, в списке нет

MessageDlg('Узел' + #13 + 'Имя:' + Edit1.Text + #13 + 'Фамилия:' + Edit2.Text + #13 +

'в списке не найден.', mtError,[mbOk],0);

Edit1.Text:=' ';

Edit1.Text:=' ';

Edit1.SetFocus;

end;

end.

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

Контрольные вопросы

  1. К какому типу данных относится тип, определяемый программистом?

  2. Запись перечисляемого типа.

  3. Запись интервального типа.

  4. Как записывается запись?

  5. Как объявляется указатель?

  6. Динамическая переменная.

  7. Список.

Резюме

  1. Тип, определенный программистом, может быть отнесен к перечисляемому; интервальному; составному типу данных (записи).

  2. Определить перечисляемый тип – это значит перечислить все значения, которые может принимать переменная, относящаяся к данному типу. В общем виде объявление перечисляемого типа выглядит так: Тип =( Значение1, Значение2, ... Значение i), где: тип – имя перечисляемого типа данных; Значение i – символьная константа, определяющая одно из значений, которое может принимать переменная типа Тип.

  3. Интервальный тип является отрезком или частью другого типа, называемого базовым. В качестве базового обычно используют целый тип данных (integer). При объявлении интервального типа указываются нижняя и верхняя границы интервала, т. е. наименьшее и наибольшее значение, которое может принимать переменная объявляемого типа. В общем виде объявление интервального типа выглядит так: Тип = НижняяГраница..ВерхняяГраница; где: тип – имя объявляемого интервального типа данных; НижняяГраница – наименьшее значение, которое может принимать переменная объявляемого типа; верхняяГраница – наибольшее значение, которое может принимать переменная объявляемого типа.

  4. Запись – это структура данных, состоящая из отдельных именованных компонентов разного типа, называемых полями. Как любой тип, создаваемый программистом, тип "запись" должен быть объявлен в разделе type. В общем виде объявление типа "запись" выглядит так: Имя = record; Поле_1 : Тип_1; Поле_2 : Тип_2; Поле_К : Тип_К; end; где: Имя – имя типа "запись"; record – зарезервированное слово языка Delphi, означающее, что далее следует объявление компонентов (полей) записи; поле_i и тил_i – имя и тип i-го компонента (поля) записи, где i=1, ..., k; end – зарезервированное слово языка Delphi, означающее, что список полей закончен.

  5. Указатель – это переменная, значением которой является адрес другой переменной или структуры данных. Указатель, как и любая другая переменная программы, должен быть объявлен в разделе объявления переменных. В общем виде объявление указателя выглядит следующим образом: Имя: ^ Тип; где: имя – имя переменной-указателя; Тип – тип переменной, на которую указывает переменная-указатель; значок ^ показывает, что объявляемая переменная является указателем.

  6. Динамической переменной называется переменная, память для которой выделяется во время работы программы. Выделение памяти для динамической переменной осуществляется вызовом процедуры new. У процедуры new один параметр – указатель на переменную того типа, память для которой надо выделить. У динамической переменной нет имени, поэтому обратиться к ней можно только при помощи указателя. Процедура, использующая динамические переменные, перед завершением своей работы должна освободить занимаемую этими переменными память или "уничтожить динамические переменные". Для освобождения памяти, занимаемой динамической переменной, используется процедура Dispose, которая имеет один параметр – указатель на динамическую переменную.

  7. Указатели и динамические переменные позволяют создавать сложные динамические структуры данных, такие как списки и деревья. Каждый элемент списка (узел) представляет собой запись, состоящую из двух частей. Первая часть - информационная. Вторая часть отвечает за связь со следующим и с предыдущим элементом списка. Для того чтобы программа могла использовать список, надо определить тип компонентов списка и переменную-указатель на первый элемент списка.

Домашнее задание

Выполнить примеры из лекций.

140




Загрузить файл

Похожие страницы:

  1. Типы данных, определяемые пользователем (агрегативные типы данных)

    Контрольная работа >> Информатика, программирование
    Типы данных, определяемые пользователем (агрегативные типы данных) Язык C позволяет программисту создавать следующие типы данных: переименование типов перечислимый тип структура битовые поля ...
  2. Способы описания различных типов данных в программах на языке Delphi

    Практическая работа >> Информатика, программирование
    ... типов данных Object Pascal поддерживает простые типы данных, определяемые самим программистом. К ним относятся перечислимый и интервальный типы. Данные этих типов ...
  3. Типы данных в языке Паскаль

    Реферат >> Информатика
    ... значений, принадлежащим типу. Предикатной функцией, определяющей принадлежность объекта к данному типу Необходимость использования типов данных Типы данных различаются начиная ...
  4. Информационные данные

    Контрольная работа >> Информатика
    ... ASCII таблицы. Перечислимый тип Перечислимый тип представляет собой упорядоченный тип данных, определяемый программистом, т.е. программист перечисляет все значения ...
  5. Структурные типы данных

    Лекция >> Информатика, программирование
    ... данных, определяемые программистом, описываются в специальном разделе - разделе типов. Раздел типов определен синтаксической диаграммой: Раздел типов Перечисляемый тип данных ...

Хочу больше похожих работ...

Generated in 0.0019500255584717