Основи
програмування h2>
Національний
технічний університет України h2>
«Київський
політехнічний інститут » h2>
Факультет
інформатики та обчислювальної техніки h2>
Кафедра
обчислювальної техніки h2>
Київ 2000 h2>
Динамічне розподіл
пам'яті. Спискові структури. Технічні характеристики пропонованого модуля
для роботи з односвязним списком. Лістинг модуля Dinamo. Лістинг програми, при написанні якої був використаний
модуль Dinamo. p>
У мові програмування
Паскаль, як і в інших мовах, завжди багато використовуються змінні. У Паскалі
всі змінні, які ми використовуємо в програмі, повинні бути попередньо описані,
тобто, повинен бути зазначений їх тип: ціле число, рядок і т.п. Але часто не
можливо заздалегідь знати, якого типу мінлива нам буде потрібна. Для цих цілей
і служать динамічні змінні, або покажчики. Для їх створення слід перед
ідентифікатором вставити спеціальний символ ^. Перед тим, як в програмі можна
буде використовувати динамічні змінні, слід виділити пам'ять, куди будуть
накопичуватися значення відповідного типу. Тільки після цього покажчик
буде містити дійсну адресу пам'яті. Розміщення динамічних змінних
проводиться в спеціальній області пам'яті Heap.
Динамічні змінні нічим не відрізняються від звичайних змінних. Над ними
можна робити всі дії, що і з звичайними змінними. Для роботи з
динамічним розподілом пам'яті дуже зручно використовувати пов'язані
структури даних, наприклад односвязние списки. p>
Найпростішим прикладом списку
є масив, в якому послідовно розташовані всі його елементи. Але у
такого подання є істотний недолік - потрібно заздалегідь точно
вказати кількість елементів масиву. Тому краще скористатися більш
гнучким механізмом - динамічними змінними. Наочно це виглядає так: p>
Перший елемент
Останній елемент p>
p>
У схемі кожен елемент розбитий на
два логічних поля: Curr - позначає всі змістовні
дані, і Next - покажчик на наступний елемент списку. В останнього
елемента покажчик встановлений в Nil, що використовується
для ініціалізації не розподілених динамічних змінних. Даний список
називається односвязним, оскільки рух від елемента до елемента в ньому
відбувається тільки в одному напрямку. Односвязний список використаний в модулі Dinamo як один з варіантів роботи з динамічними структурами. P>
Як відбувається робота з елементами
односвязного списку, наприклад, вставка нового елемента? Найкраще це можна
проілюструвати наступним малюнком на прикладі односвязного списку з трьох
елементів. p>
p>
p>
Як ми бачимо, перші дією
вказівником нового елемента присвоюється значення покажчика другого елементу (на
останній елемент списку), другий дією розривається зв'язок між другим і
останнім елементом, а замість цього покажчик другого елементу зв'язується з
новим елементом списку. p>
У даній програмі для роботи з
динамічно розподіляє областю використовуються процедури New (Var P
: Pointer) і Dispose (Var P: Pointer). Перша дозволяє створити в Heap-області
нову динамічну змінну, використовуючи при цьому весь вільний кількість
пам'яті, яке потрібно для значення заданого типу даних. Процедура Dispose звільняє динамічну змінну, виділену для Р за
відповідному викликом New. Після виклику Dispose будь-які звернення до значення Р ^ можуть призвести до помилок. Те
Тобто, кожному викликом New повинен відповідати виклик Dispose. p>
У розробці запропонованої
програми і модуля також був використаний процедурний тип даних. Процедурні
типи даних дозволяють інтерпретувати процедури та функції як об'єкти, які
можна використовувати при визначенні змінних і передачі параметрів. У
програмі при виклику такої змінної з відповідними їй параметрами
відбувається виконання призначеної їй процедури або функції. Синтаксис запису
опису процедурного типу відповідає синтаксису звичайного заголовка
процедури або функції. p>
Технічні характеристики
пропонованого модуля для роботи з односвязним списком. p>
У даному модулі реалізовані всі
основні функції, які необхідні для якісної роботи з даними, а
саме: створення, вставка, пошук, видалення або перегляд інформації, що міститься
в односвязном списку. p>
У процедурі, яка дозволяє
створювати нові записи, можливий безпосереднє введення інформації з клавіатури.
Це забезпечує певну мобільність програми. P>
Процедура вставки забезпечує
запис нового, введеної з клавіатури, елемента в те місце списку, яке
користувач вважає за необхідне. p>
Процедура видалення також
забезпечує видалення елемента, попередньо знайденого у списку, в якому б
місці списку він не перебував. p>
Перегляд забезпечує
послідовний, починаючи з першого елементу, перегляд всіх елементів,
що містяться в списку. Управління переглядом здійснюється клавішею
"пробіл". p>
Даний модуль зручний у
використанні, управління окремими процедурами вимагає певної
попередньої типізації. p>
Лістинг
програми b> program b> b> dinamo b> 11; b> p>
uses Crt, Graph; p>
type p>
pitem = ^ adresses; p>
adresses = record p>
inf: string; p>
next: pitem; p>
prev: pitem; p>
end; p>
var p>
tcurr, tfirst, tlast, dont, temp: pitem; p>
r:
char; p>
adre: string; p>
a
: Integer; p>
Procedure Novoe; p>
begin p>
if tfirst = Nil then p>
begin p>
new (tcurr); p>
writeln ( 'Адреса'); p>
readln (adre); p>
tcurr ^. inf: = adre; p>
tcurr ^. next: = nil; p>
tfirst: = tcurr; p>
end p>
else p>
begin p>
writeln ( 'adresses'); p>
readln (adre); p>
new (tcurr ^. next); p>
tcurr: = tcurr ^. next; p>
tcurr ^. inf: = adre; p>
end; p>
tcurr ^. next: = nil; p>
dont: = tcurr; p>
end; p>
Procedure Prosm; p>
begin p>
tcurr: = tfirst; p>
while tcurr <> nil do p>
begin p>
writeln (tcurr ^. inf); p>
repeat p>
r: = readkey; p>
until r in [# 32]; p>
tcurr: = tcurr ^. next; p>
end; p>
tcurr: = dont; p>
repeat p>
until keypressed; p>
end; p>
Procedure Poisk; p>
begin p>
a: = 0; p>
writeln ( 'Chto iskat ?'); p>
readln (adre); p>
tcurr: = tfirst; p>
while tcurr <> nil do p>
begin p>
if
tcurr ^. inf <> adre then p>
tcurr: = tcurr ^. next p>
else p>
begin p>
writeln (tcurr ^. inf); p>
tcurr: = nil; p>
a: = 1; p>
end; p>
end; p>
if a = 0 then p>
begin p>
writeln ( 'Not found'); p>
end; p>
tcurr: = dont; p>
repeat p>
until keypressed; p>
end; p>
Procedure Vstavka; p>
begin p>
a: = 0; p>
writeln ( 'Posle chego vstavka ?'); p>
readln (adre); p>
if adre = '-' then p>
begin p>
new (temp); p>
writeln ( 'Chto ?'); p>
writeln ( 'adresses'); p>
readln (adre); p>
temp ^. inf: = adre; p>
temp ^. next: = tfirst; p>
tfirst: = temp; p>
end p>
else p>
begin p>
tcurr: = tfirst; p>
begin p>
while tcurr <> nil do p>
begin p>
if tcurr ^. inf <> adre then tcurr: = tcurr ^. next p>
else p>
if (tcurr ^. next = nil) and (a = 0) then p>
begin p>
Novoe; p>
a: = 1; p>
tcurr: = nil; p>
end p>
else p>
if (tcurr <> nil) and (a = 0) then p>
begin p>
new (temp); p>
writeln ( 'Chtooo ?'); p>
writeln ( 'adresses'); p>
readln (adre); p>
temp ^. inf: = adre; p>
temp ^. next: = tcurr ^. next; p>
tcurr ^. next: = temp; p>
tcurr: = dont; p>
a: = 1; p>
end; p>
end; p>
end; p>
end; p>
if a = 0 then writeln ( 'Not found'); p>
repeat p>
until keypressed; p>
tcurr: = dont; p>
end; p>
Procedure Deleting; p>
begin p>
writeln ( 'Chto deletet ?'); p>
readln (adre); p>
tcurr: = tfirst; p>
temp: = tfirst; p>
while tcurr <> nil do p>
begin p>
if
tcurr ^. inf <> adre then p>
begin p>
temp: = tcurr; p>
tcurr: = tcurr ^. next; p>
end p>
else p>
begin p>
if tcurr = tfirst then p>
begin p>
tfirst: = temp ^. next; p>
tcurr: = dont; p>
end p>
else p>
if tcurr ^. next = nil then p>
begin p>
temp ^. next: = tcurr ^. next; p>
tcurr: = temp; p>
tcurr ^. next: = nil; p>
dont: = tcurr; p>
end p>
else p>
begin p>
temp ^. next: = tcurr ^. next; p>
tcurr: = temp; p>
end; p>
end; p>
end; p>
tcurr: = dont; p>
writeln ( 'Alles'); p>
repeat p>
until keypressed; p>
end; p>
begin
(programmka) p>
tfirst: = nil; p>
repeat p>
(clrscr;) p>
writeln ( '(С) оздавать, (П) росмотр, (У) даленіе, По (и) ск, (B) ставка'); p>
repeat p>
r: = readkey; p>
until r in [ 'c', 'g', 'b', 'd', 'e', # 27]; p>
case r of p>
'c': Novoe; p>
'g': Prosm; p>
'b': Poisk; p>
'd': Vstavka; p>
'e': Deleting; p>
end; p>
until r = # 27; p>
(dispose (tcurr); p>
dispose (temp );} p>
end. p>
Модуль b>
DINAMO b> p>
unit Dinamo; p>
Interface p>
uses Crt; p>
type p>
pitem = ^ tlist; p>
tlist = record p>
inf: pointer; p>
next: pitem; p>
end; p>
taction = procedure (p: pointer); p>
t_test = function (p: pointer): boolean; p>
Function New_item (p: pointer): pitem; p>
Function Make_item (dont: pitem;
p: pointer): pitem; p>
Procedure Prosm (first: pitem; act: taction); p>
Function Find (first: pitem; test: t_test;
act: taction): pitem; p>
Procedure
Deleting (first: pitem; test: t_test); p>
Function Deleting_f_end (first: pitem;
test: t_test): pitem; p>
Function
Insert_head (first: pitem; p: pointer): pitem; p>
Procedure Insert (first: pitem; test: t_test;
p: pointer); p>
Implementation p>
Function New_item (p: pointer): pitem; p>
var tcurr: pitem; p>
begin p>
new (tcurr); p>
tcurr ^. inf: = p; p>
tcurr ^. next: = nil; p>
end; p>
Function
Make_item (dont: pitem; p: pointer): pitem; p>
var tcurr: pitem; p>
begin p>
new (tcurr ^. next); p>
tcurr: = dont; p>
tcurr: = tcurr ^. next; p>
tcurr ^. inf: = p; p>
tcurr ^. next: = nil; p>
end; p>
Procedure Prosm (first: pitem; act: taction); p>
var tcurr: pitem; p>
begin p>
tcurr: = first; p>
while tcurr <> nil do p>
begin p>
act (tcurr ^. inf); p>
tcurr: = tcurr ^. next; p>
end; p>
end; p>
Function Find (first: pitem; test: t_test;
act: taction): pitem; p>
var tcurr: pitem; p>
begin p>
tcurr: = first; p>
while tcurr <> nil do p>
begin p>
if
test (tcurr ^. inf) = false then p>
tcurr: = tcurr ^. next p>
else p>
begin p>
if test (tcurr ^. inf) = true then p>
begin p>
act (tcurr ^. inf); p>
tcurr: = tcurr ^. next; p>
end; p>
end; p>
end; p>
end; p>
Procedure Deleting (first: pitem;
test: t_test); p>
var tcurr, temp: pitem; p>
begin p>
tcurr: = first; p>
temp: = first; p>
while tcurr <> nil do p>
begin p>
if
test (tcurr ^. inf) = false then p>
begin p>
temp: = tcurr; p>
tcurr: = tcurr ^. next; p>
end p>
else p>
begin p>
if tcurr = first then p>
begin p>
first: = temp ^. next; p>
end p>
else p>
begin p>
temp ^. next: = tcurr ^. next; p>
tcurr: = temp; p>
end; p>
end; p>
end; p>
end; p>
Function Deleting_f_end (first: pitem;
test: t_test): pitem; p>
var tcurr, temp: pitem; p>
begin p>
tcurr: = first; p>
temp: = first; p>
while tcurr <> nil do p>
begin p>
if
test (tcurr ^. inf) = false then p>
begin p>
temp: = tcurr; p>
tcurr: = tcurr ^. next; p>
end p>
else p>
if tcurr ^. next = nil then p>
begin p>
temp ^. next: = tcurr ^. next; p>
tcurr: = temp; p>
tcurr ^. next: = nil; p>
end; p>
end; p>
end; p>
Function
Insert_head (first: pitem; p: pointer): pitem; p>
var tcurr, temp: pitem; p>
begin p>
new (temp); p>
temp ^. inf: = p; p>
temp ^. next: = first; p>
first: = temp; p>
end; p>
Procedure Insert (first: pitem; test: t_test;
p: pointer); p>
var tcurr, temp: pitem; p>
begin p>
if test (tcurr ^. inf) = true then p>
begin p>
new (temp); p>
temp ^. inf: = p; p>
temp ^. next: = tcurr ^. next; p>
tcurr ^. next: = temp; p>
end; p>
end; p>
begin p>
end. p>
Програма,
використовує модуль b> DINAMO b> p>
program DODAVANNYA; p>
uses Dinamo, Crt; p>
type p>
pdata = ^ tdata; p>
tdata = record p>
a: string [20]; p>
end; p>
var p>
r: char; p>
dont, first, ptemp: pitem; p>
b: string [20]; p>
tmp: pdata; p>
Procedure Novoe; far; p>
begin p>
new (tmp); p>
writeln ( 'Vvedite zifru'); p>
read (b); p>
if first = nil then p>
begin p>
with tmp ^ do a: = b; p>
dont: = new_item (tmp); p>
first: = new_item (tmp); p>
end p>
else p>
begin p>
with tmp ^ do a: = b; p>
dont: = make_item (dont, tmp); p>
end; p>
end; p>
Procedure Print (p: pointer); far; p>
begin p>
with pdata (p) ^ do p>
begin p>
writeln (a); p>
writeln ('<>< <> <<><'); p>
end; p>
repeat p>
r: = readkey; p>
until r in [# 32] p>
end; p>
Function test (p: pointer): boolean; far; p>
var t: boolean; p>
begin p>
with pdata (p) ^ do t: = a = b; p>
end; p>
Procedure ToBeFound; far; p>
begin p>
new (tmp); p>
writeln ( 'What must I to find ?'); p>
read (b); p>
Find (first, test, Print); p>
repeat p>
until keypressed; p>
end; p>
Procedure Vstav; far; p>
begin p>
new (tmp); p>
writeln ( 'Posle chego ?'); p>
read (b); p>
if b = 'h' then p>
begin p>
writeln ( 'Chto ?'); p>
readln (b); p>
with tmp ^ do a: = b; p>
first: = Insert_head (first, tmp); p>
end p>
else p>
begin p>
ptemp: = Find (first, test, Print); p>
if ptemp <> nil then p>
begin p>
writeln ( 'Chto ?'); p>
readln (b); p>
with tmp ^ do a: = b; p>
Insert (ptemp, test, tmp); (Type mismatch) p>
end; p>
if ptemp = nil then p>
begin p>
writeln ( 'Chto ?'); p>
readln (b); p>
with tmp ^ do a: = b; p>
dont: = new_item (tmp); p>
end; p>
end; p>
end; p>
begin (programmka) p>
first: = nil; p>
repeat p>
(clrscr;) p>
writeln ( '(С) оздавать, (П) росмотр, (У) даленіе, По (и) ск, (B) ставка'); p>
repeat p>
r: = readkey; p>
until r in [ 'c', 'g', 'b', 'd', 'e', # 27]; p>
case r of p>
'c': Novoe; p>
'g': Prosm (first, Print); p>
'b': ToBeFound; p>
'd': Vstav; p>
( 'e': Delet;) p>
end; p>
until r = # 27; p>
dispose (tmp); p>
end. p>