Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Билет 14. Тип данных указателей. Принцип работы.
Тип данных - Указатель.
Для работы с динамической памятью в Турбо Паскале используется специальный тип данных - Указатель. Переменная типа Указатель имеет значением адрес оперативной памяти. Адрес приписан каждому байту оперативной памяти (от 0 до max) и состоит из двух частей: сегмента и смещения. Сегмент - непрерывный участок оперативной памяти длиной 64кбайт, начинающийся с физического адреса, кратного 16. Смещение указывает относительный адрес внутри сегмента. Как сегмент, так и смещение являются данными типа word. Таким образом, по своей внутренней структуре указатель состоит из двух слов типа word. С помощью указателя можно размещать в хип-памяти любой тип данных Турбо Паскаля (кроме файла). В случае, когда размещаемый тип данных имеет длину более 1 байта, указатель указывает на начало соответствующей структуры (на первый байт данных).
В Турбо-Паскале имеется два вида указателей: 1)типизированный указатель, указывающий на заданный тип данных; 2)нетипизированный указатель, указывающий лишь на область памяти данных. Типизированный описывается в следующей синтаксической форме: type <имя типа-указателя> = ^ <имя базового типа >; Здесь базовым типом может быть любой тип Турбо Паскаля, а символ ^, помещаемый перед базовым типом, идентифицирует тип-указатель. Например: type pint = ^integer; - тип-указатель на данные типа integer. Синтаксическая форма описания нетипизированного указателя имеет вид: type <имя типа-указателя> =pointer; Для работы с указателями, как и с любыми другими типами данных, объявляются переменные типа-указатель.
Например: var pp:pint; { переменная типа pint (типизированный указатель)} np:pointer; {переменная нетипизированного указателя}
Часто указатели используются для создания рекурсивных структур, характерным примером которых являются списки.
Рекурсивной называется структура, описание которой содержит обращение к самой себе. Такие обращения в Турбо Паскале возможно реализовать только с помощью указателей. Например: type refer = ^ inf; inf = record name,adr,tel:string;next:refer end;
Эта рекурсивная структура описывает линейный список, элементами которого являются записи, содержащие информацию о телефонах (три поля: имя, адрес и номер телефона) и указатель на следующую запись в списке.
. Принципы работы с указателями.
Переменная типа указатель всегда является некоторым адресом оперативной памяти, идентифицирующим размещаемую в хип-памяти структуру данных.
Создание указателя на структуру является особым способом именования этой структуры, отличным от имён, принятых для статических переменных. Необходимо помнить, что обращаясь к указателю, мы обращаемся не непосредственно к структуре данных (не к её значению !), а лишь к адресу начала размещения этой структуры.
В тех случаях, когда необходимо обратиться к значению представленной структуры данных, следует выполнить операцию разыменования, которая в Турбо Паскале имеет специальное обозначение: если p - указатель, то p^ - значение, на которое указывает p.
Для работы с указателями в Турбо Паскале предусмотрен ряд стандартных процедур и функций. Важнейшими из них являются процедуры выделения (резервирования) хип-памяти под структуры, на которые указывают указатели. Выполняет следующая процедура: new(<переменная типизированного указателя>);
При выполнении этой процедуры менеджер выделяет хип-память для размещения структуры, на которую указывает параметр этой процедуры. Значением этого параметра становится адрес, на котором начинается указанная структура. Заметим, что непосредственно после выполнения new значение размещаемой структуры неопределенное - просто под структуру зарезервирована память. Для "наполнения" этой структуры каким-либо значением можно использовать присваивание разыменованному указателю.
Для нетипизированных указателей память выделяется другой процедурой: getmem(<нетипизированный указатель>, < размер памяти >); где: <размер памяти> указывается в байтах. Действие процедуры getmem аналогично процедуре new, различие лишь в том, что размер структуры задаётся явно вторым параметром этой процедуры.
Программа работы с линейным списком - списком телефонов:
program list_tel;{создание списка телефонов}
uses CRT;
type refer=^info; {тип - Указатель на запись}
info= record name,adr,tel:string; next:refer end;
var first,p,pp:refer; {указатели на начало списка и текущие}
s:string;
procedure write_list(start:refer);{вывод всех элементов списка}
begin repeat with start^ do
begin writeln(name); writeln(adr); writeln(tel);
end; start:=start^.next
until start=nil; end{write_list};
BEGIN TextBackground(cyan);TextColor(white);ClrScr;
window(10,5,40,20);TextBackground(green); ClrScr;
new(first);p:=first;pp:=nil;
repeat if pp<>nil then {образование очередного элемента}
begin new(p);pp^.next:=p end;
with p^ do { заполнение элемента списка}
begin write('Ф.И.О.:'); readln(name);
write('Адрес:'); readln(adr); write('Телефон:');readln(tel);
next:=nil end; pp:=p;readln(s) until (s=' ');
writeln('Список телефонов создан'); write_list(first);
writeln('Вывод списка завершен'); END{list_tel}.
В этой программе элементы списка телефонов создаются циклически до тех пор, пока после заполнения полей очередного элемента списка будет введён символ-пробел. Последний элемент списка имеет нулевой указатель на следующий элемент. После создания списка процедура write_list распечатывает содержимое списка. Для возврата освободившегося участка хип-памяти используется процедура dispose (p), где p типизированный указатель, и процедура freemem(p,k), где к размер в байтах освобождаемого участка для нетипизированного указателя p. Процедура mark(ptr) - запоминает в ptr текущее значение указателя HeapPtr. Процедура release(ptr) - освобождение участка хип-памяти от текущего указателя, сохраненного процедурой mark(ptr), до конца хип-памяти. Функции maxavail и memavail - возвращают размер (в байтах) наибольшего непрерывного участка или общего свободного пространства хип-памяти соответственно. Функция addr(x) - возвращает указатель, содержащий адрес аргумента x (имя переменной, процедуры, функции). Эту же функцию выполняет операция @x.
Изменить заданную прямоугольную матрицу так, чтобы
на первом месте стояла строка с максимальной, а на
последнем месте строка с минимальной суммой элементов,
сохранив все элементы исходной матрицы.
program z433_14;
uses Z433_14;
const n=3; m=4;
BEGIN
writeln('Введите матрицу');
for i:=1 to n do
for j:=1 to m do
readln( a[i,j]);
max(a,k);
min(a,b);
zamena(k,a);
for i:=1 to n do
begin
for j:=1 to m do
write(A[i,j]:0:1,' ' );
writeln;
end;
END.
Unit Z433_14;
const n=3; m=4;
type matr=array[1..n,1..m] of real;
var a:matr;b,k,i,j:integer;
Procedure max(var a:matr;var k:integer);
procedure min(var a:matr; var k:integer);
procedure zamena(k:integer;var a:matr);
implementation
Procedure max(var a:matr;var k:integer);
var t,sum:real;
begin
sum:=0; t:=0;
for i:=1 to n do
begin
for j:=1 to m do
sum:=sum+a[i,j];
if sum>t then begin t:=sum;k:=i;end;
sum:=0;
end;
end;
procedure min(var a:matr; var k:integer);
var b,sum:real;
begin
sum:= 0; b:= 0;
for i:= 1 to n do
begin
for j:= 1 to m do sum:=sum+a[i,j];
if sum<b then begin b:=sum; k:=i; end;
sum:=0; end; end;
procedure zamena(k:integer;var a:matr);
var t:real;
begin
for j:=1 to m do begin
t:=a[1,j];
a[1,j]:=a[k,j];
a[k,j]:=t;
end; end; end.