Основы программирования в паскале

Автор работы: Пользователь скрыл имя, 16 Сентября 2009 в 13:41, Не определен

Описание работы

Учебник по программированию

Файлы: 16 файлов

Pascal процедуры и функции.doc

— 181.00 Кб (Просмотреть файл, Скачать файл)

Pascal динамические структуры данных.doc

— 147.00 Кб (Скачать файл)

      

       

     После выполнения оператора присваивания

     p2:=p1;

     оба указателя будут содержать адрес  первого участка памяти: 

         

                                   

     Переменные p1^, p2^ являются динамическими, так как  память для них выделяется в процессе выполнения программы с помощью  процедуры New. 

     Динамические  переменные могут  входить в состав выражений, например: 

       p1^:=p1^+8;    Write('p1^=',p1^:3); 

     Пример. В результате выполнения программы: 

     Program DemoPointer;

       var p1,p2,p3:^Integer;

       begin

        p1:=NIL;  p2:=NIL;  p3:=NIL;

        New(p1);  New(p2);  New(p3);

        p1^:=2;  p2^:=4;

        p3^:=p1^+Sqr(p2^);

        writeln('p1^=',p1^:3,'  p2^=',p2^:3,'  p3^=',p3^:3);

        p1:=p2;

        writeln('p1^=',p1^:3,'  p2^=',p2^:3)

       end.

     на  экран дисплея будут выведены результаты:

     p1^=  2  p2^=  4  p3^= 18

     p1^=  4  p2^=  4

     Выделение и освобождение динамической памяти.

     Процедуры и функции в  раздаточном материале см.1 //**//

 

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

     Физически куча располагается в старших  адресах, сразу за программой.

     Указатель на начало кучи храниться в предопределенной переменной HeapOrg, конец - FreePtr, текущую границу незанятой динамической памяти указывает указатель HeapPtr
Для выделения памяти под любую переменную используется процедура New. Единственным параметром является типизированный указатель:
 

(на  доске)

// 

       Var

       I,J: ^Integer;

       R: ^Real;

      Begin

       New(I); {под I выделяется область памяти,}

               {адрес первого  байта этой области  помещается в I}

      End.

// 

       После выполнения этого фрагмента  указатель I приобретёт значение, которое перед этим имел указатель кучи HeapPtr, а HeapPtr увеличится на два (т.к. он типа Integer); New(R) - вызовет смещение указателя на 6 байт.

     После того как указатель приобрёл некоторое  значение, то есть стал указывать на конкретный байт памяти, по этому адресу можно разместить значения соответствующего типа: 
(на доске)

    I^:= 2; 
    R^:= 2*Pi;
     

    Допустима запись: R^:= Sqr (R^) + I^ - 17; 
    Но недопустима запись: R:= Sqr (R^) + I^ - 17; так как указателю R нельзя присвоить значение вещественного выражения. 

     Возврат динамической памяти обратно в кучу осуществляется оператором Dispose
Dispose(R); 
Dispose(I);
- вернут в кучу, ранее забранные 8 байт. 
Dispose(Ptr) не изменяет значения указателя Ptr, а лишь возвращает в кучу память, связанную с этим указателем. Однако повторное применение процедуры к “свободному” указателю приведет к возникновению ошибки времени исполнения.

     Чтобы указать, что указатель  свободен, нужно использовать зарезервированное  слово Nil. 
  К указателям можно применять операции отношения, в том числе и сравнения с Nil:

(на  доске)

//

       Const

       P:^Real = Nil;

       . . . . . . . .

       Begin

       If P = Nil then

        New (P);

       . . . . . . . .

       Dispose(P);

       P:= Nil;

      End.

// 

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

     Многократное  чередование New и Dispose приводит к “ячеистой” структуре кучи. Дело в том, что все операции с кучей выполняется под управлением особой программы, которая ведёт учёт всех свободных фрагментов в куче.

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

     Адрес начала найденного фрагмента возвращается в указателе, а сам фрагмент или  его часть нужной длины, помечаются как занятая часть кучи. 

     Можно освободить целый  фрагмент кучи следующим  образом:

     (на доске)

//

  1. Перед началом выделения динамической памяти значения указателя HeapPtr запоминается в переменной-указателе с помощью процедуры Mark.
  2. Выполнение программы.
  3. Освобождение фрагмента кучи от заполненного адреса до конца динамической памяти с использованием процедуры Release.
  4. Var
  5.   P, P1, P2, P3, P4, P5: ^Integer;
  6. Begin
  7.   New(P1);
  8.   New(P2);
  9.   New(P3);
  10.   New(P4);
  11.   New(P5);
  12.   Mark(P);
  13.   . . . . . . .
  14.   Release (P);
  15. End.

// 

     В этом примере процедурой Mark(P) в указатель P было помещено текущее значение HeapPtr, однако память под переменную не резервировалась. 
  Вызов Release уничтожает список свободных фрагментов в куче, созданных Dispose, поэтому совместное применение этих процедур не рекомендуется. 

       Для работы с нетипизированными  указателями используются также  процедуры GetMem(P, Size) и FreeMem(P, Size) - резервирование и освобождение памяти. 
P - нетипизированный указатель, Size - размер.

     За  одно обращение к куче процедурой GetMem можно зарезервировать до 65521 байт. Освобождать нужно ровно столько памяти, сколько было зарезервировано, и именно с того адреса, с которого память была зарезервирована, иначе программа не будет работать и завершаться корректно !!!

     (см. раздат материал. 2)

     //Примеры  использования указателей.

 

  Динамическая  память - 200..300 Кбайт. Нужно разместить  массив 100 * 200 типа Extended. Требуется 100 * 200 * 10 = 200000 байт. Пробуем:  

       Var

       i,j: Integer;

       PtrArr: Array[1..100, 1..200] of ^Extended.

      Begin

       . . . . . .

       For i:= 1 to 100 do

        For j:= 1 to 200 do

         New (PtrArr [i,j]);

       . . . . . .

      End.  

      // есть в рм.// Теперь к любому  элементу можно обратиться: PtrArr[i,j]^:=...; Но длина внутреннего представления указателей 4 байта, поэтому потребуется ещё 100*200*4 = 80000 байт, что превышает размер сегмента (65536 байт), доступный для статического размещения данных. 
  Можно было бы работать с адресной арифметикой (арифметикой над указателями), то есть не создавать массив указателей, а вычислять адрес элемента непосредственно перед обращением к нему.

     Однако  в Турбо-Паскале над указателями  не определены никакие операции, кроме  присваивания и отношения.

     Но  задачу решить можно: 
 Seg(x) - возвращает сегментную часть адреса. 
 Ofs(x) - возвращает смещение. 
 x - любая переменная, в том числе и та, на которую указывает указатель. 
  Далее с помощью Ptr(Seg, Ofs: Word): Pointer можно создать значение указателя, совместимое с указателем любого типа.

     Таким образом, сначала с помощью GetMem забираем из кучи несколько фрагментов подходящей длины (не более 65521). Удобно по строкам 200 * 100 = 20000 байт.

     Начало  каждого фрагмента запоминается в массиве PtrStr из 100 указателей. Теперь для доступа к любому элементу строки нужно вычислить смещение этого элемента от начала строки и сформировать указатель.

      

       Var

       i,j: Integer;

       PtrStr: Array [1..100] of Pointer;

       Pr: ^Extended;

      Const

       SizeOfExt = 10;

      Begin

       For i:= 1 to 100 do

        GetMem (PtrStr[i], SizeOfExt*200);

       . . . . . . . . . . . . . . . .

       Pr:= Ptr(Seg(PtrStr[i]^), Ofs(PtrStr[i]^) + (j - 1) * SizeOfExt); {Обращение к элементу матрицы [i,j]}

       End;

     далее работаем с Pr^:=. . . и т.д. 

       Полезно ввести две вспомогательных  функции GetExt и PutExt. Каждая из них будет обращаться к функции вычисления адреса AddrE.  

       Program Demo;

      Const

       SizeOfExt = 10;

       N = 100;

       M = 200;

      Type

       ExtPoint = ^Extended;

      Var

       i,j: Integer;

       PtrStr: Array[1..N] of Pointer;

       S: Extended;

      

       Function AddrE(i,j: Word): ExtPoint;

       Begin

        AddrE:= Ptr(Seg(PtrStr[i]^), Ofs(PtrStr[i]^) + (j - 1) * SizeOfExt);

       End;

      

       Function GetExt(i,j: Integer): Extended;

       Begin

        GetExt:= AddrE(i,j)^;

       End;

      

       Procedure PutExt(i,j: Integer; X: Extended);

       Begin

        AddrE(i,j)^:= X;

       End;

      

      Begin {main}

       Randomize;

       For i:=1 to N do

       Begin

        GetMem (PtrStr[i], M*SizeOfExt);

        For i:= 1 to m do

         PutExt(i, j, Random(255));

       End;

       S:= 0;

       For i:= 1 to N do

        For j:= 1 to M do

         S:= S + GetExt(i,j);

       WriteLn(S/(N*M));

       End.

     / /  

     Мы  предполагали, что каждая строка размещается  в куче с начала границы параграфа  и смещение каждого указателя  PtrStr ровно 0. В действительности при последовательных обращениях к GetMem начало очередного фрагмента следует за концом предыдущего и может не попасть на границу сегмента. В результате при размещении фрагментов максимальной длины (65521 байт) может возникнуть переполнение при вычислении смещения последнего байта.

     1.4 ДИНАМИЧЕСКИЕ СТРУКТУРЫ  ДАННЫХ

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

Pascal и графика.DOC

— 116.50 Кб (Просмотреть файл, Скачать файл)

Program Graph.doc

— 19.00 Кб (Просмотреть файл, Скачать файл)

Unit GraphApp.doc

— 21.50 Кб (Просмотреть файл, Скачать файл)

Unit GraphObj.doc

— 21.50 Кб (Просмотреть файл, Скачать файл)

Краткие основы Паскаля.doc

— 217.00 Кб (Просмотреть файл, Скачать файл)

Общие понятия программирования.doc

— 80.00 Кб (Просмотреть файл, Скачать файл)

Основные принципы ООП.doc

— 151.00 Кб (Просмотреть файл, Скачать файл)

Основы разработки программ.doc

— 148.00 Кб (Просмотреть файл, Скачать файл)

Паскаль на 5-КУ 85 листов.doc

— 651.50 Кб (Скачать файл)

Модуль CRT.doc

— 30.00 Кб (Просмотреть файл, Скачать файл)

Модуль Graph.doc

— 77.50 Кб (Просмотреть файл, Скачать файл)

Структура модуля.doc

— 38.00 Кб (Просмотреть файл, Скачать файл)

Практичесое занятие по работе с модулем граф.doc

— 52.00 Кб (Просмотреть файл, Скачать файл)

Целочисленная арифметика TURBO PASCAL.doc

— 92.00 Кб (Просмотреть файл, Скачать файл)

Информация о работе Основы программирования в паскале