
- •5 Какими характеристиками определяются дискретные системы идентификации?
- •1.1.2 2. Основные этапы математического моделирования
- •Запуск пакета MatLab?
- •10.Рабочая среда MatLab 6.Х содержит следующие элементы:
- •11. Назначение программы matlab.
- •15.Назовите два способа запуска пакета Simulink ?
- •13.Возможности моделирования, предоставляемые пакетом прикладных программ Control System Toolbox (сst) и matlab Simulink.
- •14.Основные этапы работы с программой.
- •16.Назовите основные разделы Simulink?
- •Методы определения амплитудно-частотных характеристик
- •Экспериментальный:
- •Аналитический:
- •40. Что такое «запасы устойчивости по фазе и по амплитуде»?
- •41. Какие различные формы имеет функция plot?
- •42. Какая функция позволяет выводить множество графиков в одном окне?
- •2.Содержание к разделу «Численные методы»
- •1.Общие понятия. Численные методы и математические модели га.
- •2.Постановка задачи. Решение уравнений с одной переменной.
- •3.Решение уравнений с одной переменной методом хорд.
- •4.Решение уравнений с одной переменной методом касательных (Ньютона).
- •5.Решение уравнений с одной переменной методом половинного деления.
- •1. Анализ существующих методов решения задачи
- •21.Постановка задачи численного интегрирования
- •22.Квадратурные формулы Ньютона-Котеса.
- •23. Численное интегрирование. Приближенное вычисление с помощью формул трапеций.
- •24. Численное интегрирование. Приближенное вычисление с помощью формул Симпсона. Формула Симпсона
- •25. Особенности задач численного дифференцирования. Формулы численного дифференцирования
- •28. Численные методы решения обыкновенных дифференциальных уравнений. Модификации метода Эйлера. Неявный метод Эйлера
- •29. Численные методы решения обыкновенных дифференциальных уравнений. Метод Эйлера – Коши. Метод Эйлера-Коши
- •30. Численные методы решения обыкновенных дифференциальных уравнений. Неявный метод Эйлера – Коши
- •31.Численные методы решения обыкновенных дифференциальных уравнений. Первый улучшенный метод Эйлера.
- •32.Численные методы решения обыкновенных дифференциальных уравнений. Метод Рунге-Кутты.
- •33.Численные методы решения обыкновенных дифференциальных уравнений. Метод Рунге-Кутты третьего порядка точности
- •34.Численные методы решения обыкновенных дифференциальных уравнений. Метод Рунге-Кутты четвертого порядка точности
- •35.Методы обработки и анализа экспериментальных данных. Сущность метода наименьших квадратов.
- •36.Метод наименьших квадратов. Виды приближающих функций. Метод наименьших квадратов
- •5 Билет
- •6 Билет
- •7 Билет
- •Понятие рекурсии.
- •Передача параметров
- •Локальные и глобальные переменные.
- •10.Строковые данные. Обработка символьных данных
- •11.Строковые данные. Программирование задач обработки символьных данных
- •12.Особенности программирования задач, включающих действия со структурами данных. Записи. Записи с вариантами. Оператор присоединения With.
- •Запись с вариантами.
- •13.Особенности программирования задач, включающих действия со структурами данных. Множества. Операции над множествами. Использование множеств при создании экспертных систем.
- •Операции над множествами Бинарные операции
- •Унарные операции
- •1. Объявление указателей
- •2. Выделение и освобождение динамической памяти
- •18. Структурное программирование
1. Объявление указателей
Как правило, в Турбо-Паскале указатель связывается с некоторым типом данных (типизированныеуказатели).
Type PerPnt = ^PerRec;{указатель на переменную типа PerRec} PerRec = Record Name: String; Job: String; Next: PerPnt; End; Var P1: ^Integer; P2: ^Real;
Внимание! При объявлении типа PerPnt мы сослались на PerRec, который ещё не был объявлен, это связано с тем, что существует исключение из правил для указателей, которые содержат ссылку на ещё неописанный тип данных. Это исключение сделано не случайно, так как динамическая память позволяет использовать организацию данных в виде списков (каждый элемент имеет в своём составе ссылку на соседний элемент - обратите внимание на поле Next).
В Турбо-Паскале можно объявлять указатель и не связывать его с конкретным типом данных: Var PP: Pointer;
Указатели такого рода называют нетипизированными. В них удобно размещать данные, структура которых меняется по ходу работы.
В Турбо-Паскале можно передавать значения только между указателями, связанными с одним и тем же типом данных. Var P1,P2: ^Integer; P3: ^Real; PP:Pointer; Begin P1:= P2; {- верно} P1:= P3; {- неверно}
но можно сделать так: PP:= P3; P1:= PP; так как ограничение не распространяются на нетипизированные указатели. Но подобные операции часто путают программиста и чреваты смысловыми ошибками.
2. Выделение и освобождение динамической памяти
Вся динамическая память – пространство ячеек, называемое кучей. Физически куча располагается в старших адресах, сразу за программой. Указатель на начало кучи храниться в предопределенной переменной 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.
Var P, P1, P2, P3, P4, P5: ^Integer; Begin New(P1); New(P2); New(P3); New(P4); New(P5); Mark(P); . . . . . . . . Release (P); End.
В этом примере процедурой Mark(P) в указатель P было помещено текущее значение HeapPtr, однако память под переменную не резервировалась.
Вызов Release уничтожает список свободных фрагментов в куче, созданных Dispose, поэтому совместное применение этих процедур не рекомендуется.
Для работы с нетипизированными указателями используются также процедуры GetMem(P, Size) иFreeMem(P, Size) - резервирование и освобождение памяти. P - нетипизированный указатель, Size - размер.
За одно обращение к куче процедурой GetMem можно зарезервировать до 65521 байт. Освобождать нужно ровно столько памяти, сколько было зарезервировано, и именно с того адреса, с которого память была зарезервирована, иначе программа не будет работать и завершаться корректно!!!
Использование нетипизированных указателей даёт широкие возможности неявного преобразования типов: Var i,j: ^Integer; r: ^Real; Begin New (i); { I:= HeapOrg; HeapPtr:= HeapOrg+2 } j:= i; { J:= HeapOrg } j^:=2; Dispose (i); { HeapPtr:= HeapOrg } New (r); { R:= HeapOrg; HeapPtr:= HeapOrg+6 } r^:= Pi; WriteLn (j^); End. {Будет выведено: "8578"} {здесь преобразование не имеет никакого смысла}
Примеры использования указателей. Динамическая память - 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 - любая переменная, в том числе и та, на которую указывает указатель.