Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
вопросы 1-30(кроме1,2,16,19,27,28).doc
Скачиваний:
2
Добавлен:
14.04.2019
Размер:
316.93 Кб
Скачать

1

Графом будем называть несколько точек (вершин), некоторые пары которых соединены отрезками (рёбрами). Граф связный, если от каждой вершины можно дойти до любой другой по этим отрезкам. Циклом назовём какой-то путь по рёбрам графа, начинающегося и заканчивающегося в одной и той же вершине. И ещё граф называется взвешенным, если каждому ребру соответствует какое-то число (вес). Не может быть двух рёбер, соединяющих одни и те же вершины.

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

3

Введение файлового типа в язык ПАСКАЛЬ вызвано необходимостью

обеспечить возможность работы с периферийными (внешними) устройствами

ЭВМ, предназначенными для ввода, вывода и хранения данных.

Файловый тип данных или файл определяет упорядоченную совокупность

произвольного числа однотипных компонент.

Общее свойство массива, множества и записи заключается в том, что

количество их компонент определено на этапе написания программы, тог-

да как количество компонент файла в тексте программы не определяется

и может быть произвольным.

Понятие файла достаточно широко. Это может быть обычный файл на

диске, коммуникационный порт ЭВМ, устройство печати, клавиатура или

другие устройства.

При работе с файлами выполняются операции ввода - вывода. Операция

ввода означает перепись данных с внешнего устройства (из входного

файла) в основную память ЭВМ, операция вывода - это пересылка данных

из основной памяти на внешнее устройство (в выходной файл).

Файлы на внешних устройствах часто называют физическими файлами.

Их имена определяются операционной системой. В программах на языке

Паскаль имена файлов задаются с помощью строк. Например, имя файла на

диске может иметь вид:

'A:LAB1.DAT'

'c:\ABC150\pr.pas'

'lab3.pas'.

К О М П О Н Е Н Т Н Ы Е Ф А Й Л Ы

Компонентный или типизированный файл - это файл с объявленным ти-

пом его компонент. Компонентные файлы состоят из машинных представле-

ний значений переменных, они хранят данные в том же виде, что и па-

мять ЭВМ.

Описание величин файлового типа имеет вид:

type M= File Of T;

где М - имя файлового типа, Т - тип компоненты. Например:

type

FIO= String[20];

SPISOK=File of FIO;

var

STUD, PREP: SPISOK;

Здесь STUD, PREP - имена файлов, компонентами которых являются

строки.

Описание файлов можно задавать в разделе описания переменных:

var

fsimv: File of Char;

fr: File of Real;

Компонентами файла могут быть все скалярные типы, а из структури-

рованных - массивы, множества, записи. Практически во всех конкретных

реализациях языка ПАСКАЛЬ конструкция "файл файлов" недопустима.

Все операции над компонентными файлами производятся с помощью

стандартных процедур:

Reset, Rewrite, Read, Write, Close.

Для ввода - вывода используются процедуры:

Read(f,X);

Write(f,X);

где f - имя логического файла, Х - либо переменная, либо массив,

либо строка, либо множество, либо запись с таким же описанием, какое

имеет компонента файла.

Выполнение процедуры Read(f,X) состоит в чтении с внешнего уст-

ройства одной компоненты файла и запись ее в X. Повторное применение

процедуры Read(f,X) обеспечит чтение следующей компоненты файла и за-

пись ее в X.

Выполнение процедуры Write(f,X) состоит в записи X на внешнее уст-

ройство как одной компоненты. Повторное применение этой процедуры

обеспечит запись X как следующей компоненты файла.

Для работы с компонентными файлами введена расширенная форма опе-

раторов ввода и вывода:

Read(f,X1,X2,...XK)

Write(f,X1,X2,...XK)

Здесь f - компонентный файл, а переменные Х1, Х2,...ХК должны

иметь тот-же тип, что и объявленный тип компонент файла f.

Б Е С Т И П О В Ы Е Ф А Й Л Ы

Бестиповые файлы позволяют записывать на диск произвольные участки

пвмяти ЭВМ и считывать их с диска в память. Операции обмена с бести-

повыми файлами осуществляется с помощью процедур BlokRead и

BlockWrite. Кроме того, вводится расширенная форма процедур Reset и

Rewrite. В остальном принципы работы остаются такими же, как и с ком-

понентными файлами.

Перед использованием логический файл

var f: File;

должен быть связан с физическим с помощью процедуры Assign. Далее

файл должен быть открыт для чтения или для записи процедурой Reset

или Rewrite, а после окончания работы закрыт процедурой Close.

При открытии файла длина буфера устанавливается по умолчанию в 128

байт. TURBO PASCAL позволяет изменить размер буфера ввода - вывода,

для чего следует открывать файл расширенной записью процедур

Reset(var f: File; BufSize: Word )

или

Rewrite(var f: File; BufSize: Word )

Параметр BufSize задает число байтов, считываемых из файла или за-

писываемых в него за одно обращение. Минимальное значение BufSize - 1

байт, максимальное - 64 К байт.

Чтение данных из бестипового файла осуществляется процедурой

BlockRead( var f: File; var X; Count: Word; var QuantBlock: Word );

Эта процедура осуществляет за одно обращение чтение в переменную X

количества блоков, заданное параметром Count, при этом длина блока

равна длине буфера. Значение Count не может быть меньше 1. За одно

обращение нельзя прочесть больше, чем 64 К байтов.

Необязательный параметр QuantBlock возвращает число блоков (буфе-

ров), прочитанных текущей операцией BlockRead. В случае успешного за-

вершения операции чтения QuantBlock = Count, в случае аварийной ситу-

ации параметр QuantBlock будет содержать число удачно прочитанных

блоков. Отсюда следует, что с помощью параметра QuantBlock можно

контролировать правильность выполнения операции чтения.

Запись данных в бестиповой файл выполняется процедурой

BlockWrite( var f: File; var X; Count: Word; var QuantBlock: Word );

которая осуществляет за одно обращение запись из переменной X коли-

чества блоков, заданное параметром Count, при этом длина блока равна

длине буфера.

Необязательный параметр QuantBlock возвращает число блоков (буфе-

ров), записанных успешно текущей операцией BlockWrite.

4

Бинарное (двоичное) дерево (binary tree) - это упорядоченное дерево, каждая вершина которого имеет не более двух поддеревьев, причем для каждого узла выполняется правило: в левом поддереве содержатся только ключи, имеющие значения, меньшие, чем значение данного узла, а в правом поддереве содержатся только ключи, имеющие значения, большие, чем значение данного узла.

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

Узел дерева, не имеющий потомков, называется листом.

Схематичное изображение бинарного дерева:

Бинарное дерево может представлять собой пустое множество.

Бинарное дерево может выродиться в список:

Построение бинарного дерева

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

template<class T>

struct TNode {

T value;

TNode *pleft, *pright;

//constructor

TNode() {

pleft = pright = 0;

}

};

Здесь поля pleft и pright - это указатели на потомков данного узла, а поле value предназначено для хранения информации.

Теперь мы можем написать рекурсивную функцию, которая будет вызываться при создании дерева:

template<class T>

void makeTree(TNode<T>** pp, T x) {

if(!(*pp)) {

TNode<T>* p = new TNode<T>();

p->value = x;

*pp = p;

}

else {

if((*pp)->value > x)

makeTree(&((*pp)->pleft), x);

else

makeTree(&((*pp)->pright), x);

}

}

Эта функция добавляет элемент x к дереву, учитывая величину x. При этом создается новый узел дерева.

Обход дерева

Функция, выполняющая обход дерева, позволяет перебрать все элементы, содержащиеся в дереве.

В приведенной ниже реализации функция обхода дерева будет просто выводить на экран значение поля value каждого узла дерева (включая его корень):

template<class T>

void walkTree(TNode<T>* p) {

if(p) {

walkTree(p->pleft);

cout << p->value << ' ';

walkTree(p->pright);

}

}

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

Например, нерекурсивная функция для обхода дерева может выглядеть так:

template<class T>

void walkNotRec(TNode<T>* tree) {

if (tree) {

TNode<T> temp;

TNode<T>* ptemp = &temp;

TNode<T>* p = ptemp, *c = tree, *w;

while (c != ptemp) {

cout << c->value;

w = c->pleft;

c->pleft = c->pright;

if(c == p)

c->pright = 0;

else

c->pright = p;

p = c;

if (w) c = w;

}

}

}

Применение

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

5

Оператор ввода

Readln (x1[,x2,x3,...]) - сначала идет имя процедуры Readln, затем имена переменных, которым будут присвоены значения. Их может быть несколько либо одно. Но необходимо помнить, что Readln после ввода каждой переменной требует переход на новую строку, иначе часть введенной строки отбрасывается.

Замечание: иногда Readln используют для организации ожидания до нажатия клавиши Enter. Это требуется, когда перед завершением программы необходимо просмотреть результаты ее работы. Наверх

Оператор вывода

Writeln (['Текст пояснения ',]x1[,x2,x3,...]) - сначала идет имя процедуры Writeln, затем текст, имена переменных, арифметические выражения. Их может быть несколько либо одно имя.

Но необходимо помнить, что Writeln переводит курсор на новую строку в отличии от Write.

Арифметические выражения вычисляются, а затем выводятся.

При выводе вещественных чисел необходимо форматирование, иначе они будут представлены в форме с плавающей запятой.

Writeln(real2:5:2); Здесь переменная real2 выводится на экран ограниченная по ширине в 5 символов, а также с 2 знаками после запятой.

№6

Типы параметров подпрограмм

Параметры-значения

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

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

Параметры-константы

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

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

Параметры-переменные

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

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

Нетипизированные параметры

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

В процедуре или функции у нетипизированного параметра-переменной тип отсутствует, т. е. он несовместим с переменными всех типов, пока ему не будет присвоен определенный тип с помощью присваивания типа переменной.

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

Процедурные переменные

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

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

7

Двумерный массив - это одномерный массив, элементами которого являются одномерные массивы. Другими словами, это набор однотипных данных, имеющий общее имя, доступ к элементам которого осуществляется по двум индексам. Наглядно двумерный массив удобно представлять в виде таблицы, в которой n строк и m столбцов, а под ячейкой таблицы, стоящей в i-й строке и j-м столбце понимают некоторый элемент массива a[i][j].

Действительно, если разобраться с тем, что такое a[i] при фиксированном значении i, то увидим, что это одномерный массив, состоящий из m элементов, к которым можно обращаться по индексу: a[i][1], a[i][2], ... , a[i][m]. Схематически это вся i-я строка строка таблицы. Аналогично, если мы рассмотрим одномерный массив строк, то сможем заметить, что это так же двумерный массив, где каждый отдельный элемент - это символ типа char, а a[i] - это одномерный массив, представляющий отдельную строку исходного одномерного массива строк. Исходя из идеи определения думерного массива можно определить рекурентное понятие многомерного массива:

n-мерный массив - это одномерный массив, элементами которого являются (n-1)-мерные массивы.

Несложно догадаться, что 3-мерный массив визуально можно представить в виде куба с ячейками (похоже на кубик Рубика), где каждый элемент имеет вид a[i][j][k]. А вот с большими размерностями возникают сложности с визуальным представлением, но математическая модель ясна.

По-другому двумерный массив также называют матрицей, а в том случае, когда n=m (число строк равно числу столбцов) матрицу называют квадратной. В матрицах можно хранить любые табличные данные: содержание игрового поля (шашки, шахматы, Lines и т.д.), лабиринты, таблицу смежности графа, коэффициенты системы линейных уравнений и т.д. Матрицы часто используют для решения олимпиадных и математических задач.

В задачах табличные данные часто определяются во входном файле следующим образом: сначала в первой строке указываются значения n и m через пробел, а далее идут n строк по m элементов в каждой, также друг от друга отделенные пробелом и входной файл может иметь, например, следующее содержание, понятно отражающее содержимое матрицы при обычном просмотре:

3 5

7 8 2 3 1

5 3 2 6 3

9 3 5 2 0

В приведенном примере определена матрица, состоящая из трех строк и пяти столбцов. Рассмотрим пример чтения этих данных в матрицу и вывода матрицы в файл. Для этого удобно использовать двойной цикл, где внешний цикл по i будет пробегать по всем строкам, а внутренний цикл по j будет для текущей строки i перебирать все ее элементы. Алгоритмическая реализация этого процесса может выглядеть следующим образом:

int a[1..100][1..100];

//Чтение данных двумерного массива из файла

read(n,m);

for i=1..n{

for j=1..m{

read(a[i][j]);

}

}

//Вывод матрицы в файл

for i=1..n{

for j=1..m{

write(a[i][j], ' ');

}

writeln; //новая строка

}

8

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

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

Динамическая структура данных характеризуется тем что:

она не имеет имени;

ей выделяется память в процессе выполнения программы;

количество элементов структуры может не фиксироваться;

размерность структуры может меняться в процессе выполнения программы;

в процессе выполнения программы может меняться характер взаимосвязи между элементами структуры.

Каждой динамической структуре данных сопоставляется статическая переменная типа указатель (ее значение – адрес этого объекта), посредством которой осуществляется доступ к динамической структуре.

Сами динамические величины не требуют описания в программе, поскольку во время компиляции память под них не выделяется. Во время компиляции память выделяется только под статические величины. Указатели – это статические величины, поэтому они требуют описания.

Необходимость в динамических структурах данных обычно возникает в следующих случаях.

Используются переменные, имеющие довольно большой размер (например, массивы большой размерности), необходимые в одних частях программы и совершенно не нужные в других.

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

Когда размер данных, обрабатываемых в программе, превышает объем сегмента данных.

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

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

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

размер структуры ограничивается только доступным объемом машинной памяти;

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

большая гибкость структуры.

Вместе с тем, связное представление не лишено и недостатков, основными из которых являются следующие:

на поля, содержащие указатели для связывания элементов друг с другом, расходуется дополнительная память;

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

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

Порядок работы с динамическими структурами данных следующий:

создать (отвести место в динамической памяти);

работать при помощи указателя;

удалить (освободить занятое структурой место).

Классификация динамических структур данных

Во многих задачах требуется использовать данные, у которых конфигурация, размеры и состав могут меняться в процессе выполнения программы. Для их представления используют динамические информационные структуры. К таким структурам относят:

однонаправленные (односвязные) списки;

двунаправленные (двусвязные) списки;

циклические списки;

стек;

дек;

очередь;

бинарные деревья.

Они отличаются способом связи отдельных элементов и/или допустимыми операциями. Динамическая структура может занимать несмежные участки оперативной памяти.

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

9

Записи

В программах часто возникает необходимость логического объединения данных. Например, база данных предприятия содержит для каждого сотрудника его фамилию, дату рождения, должность, оклад и так далее. Однотипные данные организуются в массивы, а для объединения разнотипных данных предназначен тип "запись". Он вводится с помощью ключевого слова record. Элементы записи называются полями:

type имя_типа = record

описание 1-го поля записи;

описание 2-го поля записи;

...

описание n-го поля записи;

end;

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

type goods = record

name : string[20];

price : real;

number: integer;

end;

Переменные типа "запись" описываются обычным образом. Можно задавать описание типа при описании переменной, создавать массивы из записей, записи из массивов:

var g1, g2 : goods;

stock : array [1 .. 100] of goods;

student : record

name : string [30];

group : byte;

marks : array [1 .. 4] of byte;

end;

Можно присваивать одну запись другой, если они одного типа, например:

g1 := g2;

g2 := stock[3];

Все остальные действия выполняются с отдельными полями записи. Есть два способа доступа к полю записи: либо с помощью конструкции имя_записи.имя_поля, либо с использованием оператора присоединения with, например:

g1.price := 200;

with g1 do begin

price := 200; number := 10

end;

Пример 1

Сведения о товарах на складе хранятся в текстовом файле. Для каждого товара отводится одна строка, в первых 20 позициях которой записано наименование товара, а затем через произвольное количество пробелов его цена и количество единиц. Программа по запросу выдает сведения о товаре или сообщение о том, что товар не найден.

program store;

const Max_n = 100;

type

str20 = string [20];

goods = record

name : str20;

price : real;

number : integer;

end;

var stock : array[1 .. Max_n] of goods;

i, j, len : integer;

name : str20;

found : boolean;

f : text;

begin

assign(f, 'stock.txt'); reset(f);

i := 1;

while not Eof(f) do begin

with stock[i] do readln(f, name, price, number);

inc(i);

if i > Max_n then begin {1}

writeln('Переполнение массива'); exit end;

end;

while true do begin {2}

writeln('Введите наименование'); Readln(name);

len := length(name);

if len = 0 then break; {3}

for j := len + 1 to 20 do name := name + ' '; {4}

found := false;

for j := 1 to i - 1 do begin {5}

if name <> stock[j].name then continue;

with stock[j] do writeln (name:22, price:7:2, number:5);

found := true;

break;

end;

if not found then writeln ('Товар не найден'); {6}

end;

end.

Инициализация записей выполняется в разделе констант, при этом для каждого поля задается его имя, после которого через двоеточие указывается значение:

const g : goods = ( name: 'boots';

price: 200; number: 10 );

Множества

Множественный тип данных в языке Паскаль соответствует математическому представлению о множествах: это ограниченная совокупность различных элементов. Множество создается на основе элементов базового типа, он может быть перечисляемым, интервальным или byte. В множестве не может быть более 256 элементов.

Множество описывается с помощью служебных слов set of:

type имя_типа = set of базовый_тип;

Примеры:

type Caps = set of 'A' .. 'Z';

Colors = set of (RED, GREEN, BLUE);

Numbers = set of byte;

Принадлежность переменных к множественному типу может быть определена прямо в разделе описания переменных, например:

var oct : set of 0 .. 7;

Константы множественного типа записываются в виде заключенной в квадратные скобки последовательности элементов или интервалов базового типа, разделенных запятыми, например:

['A', 'D'] [1, 3, 6] [2, 3, 10 .. 13].

Константа вида [ ] означает пустое подмножество.

Тип "множество" задает набор всех возможных подмножеств его элементов, включая пустое. Если базовый тип, на котором строится множество, имеет k элементов, то число подмножеств, входящих в это множество, равно 2k.

Переменная множественного типа содержит одно конкретное подмножество значений множества. Пусть имеется переменная b интервального типа:

var b : 1 .. 3;

Эта переменная может принимать три различных значения: 1, 2 или 3. Переменная m множественного типа

var m : set of 1 .. 3;

может принимать восемь различных значений:

[ ] [1] [2] [3] [1, 2] [1, 3] [2, 3] [1, 2, 3]

Порядок перечисления элементов базового типа в константах безразличен.

Операции над множествами

Величины множественного типа не могут быть элементами списка ввода-вывода. Допустимые операции над множествами перечислены в таблице: Знак Название Математическая запись Результат

:= присваивание

+ объединение È множество

* пересечение Ç множество

- дополнение \ множество

= тождественность = логический

<> нетождественность ¹ логический

<= содержится в Í логический

>= содержит Ê логический

in принадлежность логический

Пример 2

Рассмотрим примеры применения операций. Пусть задано множество, основанное на значениях прописных латинских букв:

type Caps = set of 'A' .. 'Z';

var a, b, c : Caps;

begin

a := ['A', 'U' .. 'Z'];

b := [ 'M' .. 'Z'];

c := a; { присваивание }

c := a + b; { объединение, результат ['A', 'M' .. 'Z'] }

c := a * b; { пересечение, результат ['U' .. 'Z'] }

c := b - a; { вычитание, результат ['M' .. 'T'] }

c := a - b; { вычитание, результат ['A'] }

if a = b then writeln ('тождественны'); { не выполнится }

if a <> b then writeln ('не тождественны'); { выполнится }

if c <= a then writeln ('c содержится в а'); { выполнится }

if 'N' in b then writeln ('в b есть N'); { выполнится }

end.

10

http://citforum.ru/programming/bp70_ug/bp70ug_08.shtml

(по ссылке все подробней)

Указатель - это ссылка на данные или код вашей программы. Он

представляет адрес в памяти элемента, на который указывает. Ис-

пользование указателей позволяет писать большие и более гибкие

программы и особенно полезно, когда вы начинаете писать объект-

но-ориентированные программы.

Для чего используются указатели?

Рано или поздно каждый программист, работающий на Паскале,

попадает в ситуацию, требующую использования указателей. Указате-

ли требуется применять в следующих случаях:

* Если ваша программа работает с большими объемами данных

(общий объем которых превышает 64К).

* Если ваша программа во время компиляция использует данные

неизвестного размера.

* Если программа использует временные буферы данных.

* Если ваша программа работает с несколькими типами данных.

* Если ваша программа использует связанные списки данных или

объектов.

Как использовать указатели?

Теперь вы получили достаточно хорошее представление о том, в

каких ситуациях вы можете использовать указатели, и можно расс-

мотреть их фактическое применение. В данном разделе охватываются

следующие темы:

* Распределение динамических переменных.

* Освобождение выделенной для динамических переменных памя-

ти.

* Распределение и освобождение выделенных объемов памяти.

* Проверка доступного в динамически распределяемой области

пространства.

Borland Pascal предусматривает две пары процедур для выде-

ления и освобождения памяти, распределяемой для динамических пе-

ременных. Чаще всего используются процедуры New и Dispose, кото-

рые отвечают большинству потребностей. Процедуры GetMem и FreeMem

выполняют те же функции, но на более низком уровне.

11

11. Рекурсия - это такой способ организации обработки данных, при котором программа вызывает сама себя непосредственно, либо с помощью других программ.

В программировании рекурсия — вызов функции (процедуры) из неё же самой, непосредственно (простая рекурсия) или через другие функции (сложная рекурсия), например, функция A вызывает функцию B, а функция B — функцию A. Количество вложенных вызовов функции или процедуры называется глубиной рекурсии.

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

Общая схема рекурсивного цикла:

 

Procedure Рекурсивный_Цикл (…);

begin

if < условие цикла > then

begin

< тело рекурсивного цикла; >

Рекурсивный_Цикл (…);

end;

end;

 

Итерация - способ организации обработки данных, при котором определенные действия повторяются многократно, не приводя при этом к рекурсивным вызовам программ.

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

В основе итеративного вычислительного процесса лежит итеративный цикл While, Repeat-Until, For. Наиболее общим является цикл While:

While < условие цикла > do < тело цикла >;

 

Существует два важных положения, известных в математике и в программировании, определяющих соотношение между итерацией и рекурсией:

- Любой итеративный цикл может быть заменен рекурсией.

- Рекурсия не всегда может быть заменена итерацией.

№12

инейной называется программа, все операторы которой выполняются последовательно, в том порядке, в котором они записаны. Это самый простой вид программ.

Переменные

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

Для каждой переменной задается ее имя и тип, например

var number : integer;

x, y : real;

option : char;

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

Тип переменных выбирается исходя из диапазона и требуемой точности представления данных.

При объявлении можно присвоить переменной некоторое начальное значение, то есть инициализировать ее. Под инициализацией понимается задание значения, выполняемое до начала работы программы. Инициализированные переменные описываются после ключевого слова const:

const

number : integer = 100;

x : real = 0.02;

option : char = 'ю';

По умолчанию все переменные, описанные в главной программе, обнуляются.

Выражения

Выражение - это правило вычисления значения. В выражении участвуют операнды, объединенные знаками операций. Операндами выражения могут быть константы, переменные и вызовы функций. Операции выполняются в определенном порядке в соответствии с приоритетами, как и в математике. Для изменения порядка выполнения операций используются круглые скобки, уровень их вложенности практически не ограничен.

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

Ниже приведены операции Паскаля, упорядоченные по убыванию приоритетов.

Унарная операция not, унарный минус -, взятие адреса @.

Операции типа умножения: * / div mod and shl shr.

Операции типа сложения: + - or xor.

Операции отношения: = <> < > <= >= in.

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

Примеры выражений:

t + sin(x)/2 * x - результат имеет вещественный тип

a <= b + 2 - результат имеет логический тип

(x > 0) and (y < 0) - результат имеет логический тип

Структура программы

Программа на Паскале состоит из необязательного заголовка, разделов описаний и раздела операторов:

program имя; { заголовок }

разделы описаний

begin

раздел операторов

end. (* программа заканчивается точкой *)

Программа может содержать комментарии, заключенные в фигурные скобки { } или в скобки вида (* *).

В разделе операторов записываются исполняемые операторы программы. Ключевые слова begin и end не являются операторами, а служат для их объединения в так называемый составной оператор, или блок. Блок может записываться в любом месте программы, где допустим обычный оператор.

Разделы описаний бывают нескольких видов: описание модулей, констант, типов, переменных, меток, процедур и функций.

Модуль - это подключаемая к программе библиотека ресурсов (подпрограмм, констант и т.п.).

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

uses crt, graph, my_module;

Возможности стандартных модулей мы рассмотрим в разделе "Стандартные модули Паскаля", а создание собственных - описано в разделе "Модули".

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

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

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

const weight : real = 61.5;

n = 10;

Раздел описания меток начинается с ключевого слова label, зa которым через запятую следует перечисление всех меток, встречающихся в программе. Метка - это либо имя, либо положительное число, не превышающее 9999. Метка ставится перед любым исполняемым оператором и отделяется от него двоеточием. Пример описания меток:

label 1, 2, error;

Метки служат для организации перехода на конкретный оператор с помощью оператора безусловного переходаgoto.

Оператор присваивания

Присваивание - это занесение значения в память. В общем виде оператор присваивания записывается так:

переменная := выражение

Здесь символами := обозначена операция присваивания. Внутри знака операции пробелы не допускаются.

Механизм выполнения оператора присваивания такой: вычисляется выражение и его результат заносится в память по адресу, который определяется именем переменной, находящейся слева от знака операции.

Пример 1

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

a := b + c / 2;

b := a;

a := b;

x := 1;

x := x + 0.5;

Обратите внимание: b := a и a := b - это совершенно разные действия!

Правая и левая части оператора присваивания должны быть совместимы по присваиванию. Например, выражение целого типа можно присвоить вещественной переменной.

13

Массивы - это совокупности однотипных элементов. Характеризуются они следующим:

каждый компонент массива может быть явно обозначен и к нему имеется прямой доступ;

число компонент массива определяется при его описании и в дальнейшем не меняется.

Для обозначения компонент массива используется имя переменной-массива и так называемые индексы, которые обычно указывают желаемый элемент. Тип индекса может быть только порядковым (кроме longint). Чаще всего используется интервальный тип (диапазон).

Описание типа массива задается следующим образом:

type

имя типа = array[ список индексов ] of тип

Здесь имя типа - правильный идентификатор; список индексов - список одного или нескольких индексных типов, разделенных запятыми; тип - любой тип данных.

Вводить и выводить массивы можно только поэлементно.

Пример 1. Ввод и вывод одномерного массива.

const

n = 5;

type

mas = array[1..n] of integer;

var

a: mas;

i: byte;

begin

writeln('введите элементы массива');

for i:=1 to n do readln(a[i]);

writeln('вывод элементов массива:');

for i:=1 to n do write(a[i]:5);

end.

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

var a,b,c: array[1..10] of integer;

Если массивы a и b описаны как:

var

a = array[1..5] of integer;

b = array[1..5] of integer;

то переменные a и b считаются разных типов. Для обеспечения совместимости применяйте описание переменных через предварительное описание типа.

Если типы массивов идентичны, то в программе один массив может быть присвоен другому. В этом случае значения всех переменных одного массива будет присвоены соответствующим элементам второго массива.

Вместе с тем, над массивами не определены операции отношения. Сравнивать два массива можно только поэлементно.

Так как тип, идущий за ключевым словом of в описании массива, - любой тип Турбо Паскаль, то он может быть и другим массивом. Например:

type

mas = array[1..5] of array[1..10] of integer;

Такую запись можно заменить более компактной:

type

mas = array[1..5, 1..10] of integer;

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

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

for i:=1 to m do

for j:=1 to n do a[i,j]:=random(10);

Для "красивого" вывода матрицы на экран используйте такой цикл:

for i:=1 to m do begin

for j:=1 to n do write(a[i,j]:5);

writeln;

end;

14

. В таблице приведены основные математические операции Турбо Паскаль.

Символ операции

Название операции

Пример

*

умножение

2*3 (результат: 6)

/

деление

30/2 (результат: 1.5E+01)

+

сложение

2+3 (результат: 5)

-

вычитание

5-3 (результат: 2)

div

целочисленное деление

5 div 2 (результат: 2)

mod

остаток от деления

5 mod 2 (результат: 1)

15

Метод ветвей и границ (англ. branch and bound) — общий алгоритмический метод для нахождения оптимальных решений различных задач оптимизации, особенно дискретной икомбинаторной оптимизации. По существу, метод является вариацией полного перебора с отсевом подмножеств допустимых решений, заведомо не содержащих оптимальных решений.

Метод ветвей и границ был впервые предложен в 1960 году Ленд и Дойг[1] для решения задач целочисленного программирования.

Общая идея метода может быть описана на примере поиска минимума и максимума функции f(x) на множестве допустимых значений x. Функция f и x могут быть произвольной природы. Для метода ветвей и границ необходимы две процедуры: ветвление и нахождение оценок (границ).

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

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

В основе метода ветвей и границ лежит следующая идея (для задачи минимизации): если нижняя граница для подобласти A дерева поиска больше, чем верхняя граница какой-либо ранее просмотренной подобласти B, то A может быть исключена из дальнейшего рассмотрения (правило отсева). Обычно, минимальную из полученных верхних оценок записывают в глобальную переменную m; любой узел дерева поиска, нижняя граница которого больше значения m, может быть исключен из дальнейшего рассмотрения.

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

17

Сортировка массива методом пузырька - медленная, но если скорость не главное, можно применить и его.

Алгоритм очень прост - если два соседних элемента расположены не по порядку,

то меняем их местами. Так повторяем до тех пор, пока в очередном проходе не сделаем ни одного обмена,

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

(Arr - массив для сортировки с начальным индексом 0, n - размерность массива)

procedure SortPuz (var Arr : array of Integer; n : Integer);

var

i : Integer;

Temp : Integer;

Flag : Boolean;

begin

repeat

Flag := False;

for i := 0 to n - 1 do

if Arr [i] > Arr [i + 1] then begin

Temp := Arr [i];

Arr [i] := Arr [i + 1];

Arr [i + 1] := Temp;

Flag := True;

end;

until Flag = False;

end;

Сортировка методом нахождения минимального элемента

Ещё один вариант сортировки, более быстрый, чем метод пузырька.

Заключается он в следующем: при каждом просмотре массива находим

минимальный элемент и меняем местами его с первым на первом проходе,

со вторым - на втором и т.д. Не забудьте только, что первый элемент массива должен иметь индекс 0.

procedure SortMin (var Arr : array of Integer; n : Integer);

var

i, j : Integer;

Min, Pos, Temp : Integer;

begin

for i := 0 to n - 1 do begin

Min := Arr [i];

Pos := i;

for j := i + 1 to n do

if Arr [j] < Min then begin

Min := Arr [j];

Pos := j;

end;

Temp := Arr [i];

Arr [i] := Arr [Pos];

Arr [Pos] := Temp;

end;

end;

Сортировка массива вставками

Более быстрый и оптимальный метод сортировки - сортировка вставками.

Суть её в том, что на n-ном шаге мы имеем упорядоченную часть массива из n элементов,

и следующий элемент встаёт на подходящее ему место.

Имейте в виду - первый индекс массива - 0.

procedure SortInsert (var Arr : array of Integer; n : Integer);

var

i, j, Temp : Integer;

begin

for i := 1 to n do begin

Temp := Arr [i];

j := i - 1;

while Temp < Arr [j] do begin

Arr [j + 1] := Arr [j];

Dec (j);

if j < 0 then

Break;

end;

Arr [j + 1] := Temp;

end;

end;

Поиск перебором

Чтобы найти какие-то данные в неупорядоченном массиве,

применяется алгоритм простого перебора элементов.

Следующая функция возвращает индекс заданного элемента массива.

Её аргументы: массив с первым индексом 0, количество элементов

в массиве и искомое число. Если число не найдено, возвращается -1.

function SearchPer (Arr : array of Integer; n, v : Integer) : Integer;

var

i : Integer;

begin

Result := -1;

for i := 1 to n do

if Arr [i] = v then begin

Result := i;

Exit;

end;

end;

Бинарный поиск

При поиске в упорядоченном массиве можно применить гораздо

более быстрый метод поиска - бинарный.

Суть его в следующем: В начале переменная Up указывает на самый

маленький элемент массива (Up := 0), Down - на самый большой

(Down := n, где n - верхний индекс массива), а Mid - на средний.

Дальше, если искомое число равно Mid, то задача решена; если число меньше Mid,

то нужный нам элемент лежит ниже среднего, и за новое значение Up принимается Mid + 1;

и если нужное нам число меньше среднего элемента, значит, оно расположено

выше среднего элемента, и Down := Mid - 1. Затем следует новая итерация цикла,

и так повторяется до тех пор, пока не найдётся нужное число, или Up не станет больше Doun.

function SearchBin (Arr : array of Integer; v, n : Integer) : Integer;

var

Up, Down, Mid : Integer;

Found : Boolean;

begin

Up := 0; Down := n;

Found := False; Result := -1;

repeat

Mid := Trunc ((Down - Up) / 2) + Up;

if Arr [Mid] = v then

Found := True

else

if v < Arr [Mid] then

Down := Mid - 1

else

Up := Mid + 1;

until (Up > Down) or Found;

if Found then

Result := Mid;

end;

18

Модели объектов и процессов (графические, вербальные, табличные, математические и др.).

Все модели можно разбить на два больших класса: модели предметные (материальные) и модели информационные. Предметные модели воспроизводят геометрические, физические и другие свойства объектов в материальной форме (глобус, анатомические муляжи, модели кристаллических решеток, макеты зданий и сооружений и др.).

Типы информационных моделей

Информационные модели представляют объекты и процессы в образной или знаковой форме. Образные модели (рисунки, фотографии и др.) представляют собой зрительные образы объектов, зафиксированные на каком-либо носителе информации (бумаге, фото- и кинопленке и др.). Широко используются образные информационные модели в образовании (учебные плакаты по различным предметам) и науках, где требуется классификация объектов по их внешним признакам (в ботанике, биологии, палеонтологии и др.).

Знаковые информационные модели строятся с использованием различных языков (знаковых систем). Знаковая информационная модель может быть представлена в форме текста (например, программы на языке программирования), формулы (например, второго закона Ньютона F=ma), таблицы (например, периодической таблицы элементов Д. И. Менделеева) и так далее.

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

Табличные информационные модели

Одним из наиболее часто используемых типов информационных моделей является прямоугольная таблица, которая состоит из столбцов и строк. Такой тип моделей применяется для описания ряда объектов, обладающих одинаковыми наборами свойств. С помощью таблиц могут быть построены как статические, так и динамические информационные модели в различных предметных областях. Широко известно табличное представление математических функций, статистических данных, расписаний поездов и самолетов, уроков и так далее.

Представление объектов и их свойств в форме таблицы часто используется в научных исследованиях. Так, на развитие химии и физики решающее влияние оказало создание Д. И. Менделеевым в конце XIX века периодической системы элементов, которая представляет собой табличную информационную модель. В этой модели химические элементы располагаются в ячейках таблицы по возрастанию атомных весов, а в столбцах — по количеству валентных электронов, причем по положению в таблице можно определить некоторые физические и химические свойства элементов.

Табличные информационные модели проще всего строить и исследовать на компьютере с помощью электронных таблиц и систем управления базами данных. Визуализируем полученную табличную модель путем построения диаграммы в электронных таблицах.

Иерархические и сетевые модели

Множество окружающих нас объектов обладает одинаковыми свойствами, которые отличают их от других групп объектов. Группа объектов, обладающих одинаковыми общими свойствами, называется классом объектов. Внутри класса объектов могут быть выделены подклассы, объекты которых обладают какими-то особыми свойствами. В свою очередь подклассы могут делится на более мелкие группы и т.д.

В процессе классификации объектов часто строят информационные модели, которые имеют иерархическую структуру.

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

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

Сетевые информационные модели применяются для отражения систем со сложной структурой, в которых связи между элементами имеют произвольный характер.

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

Классификация моделей по временному фактору

Статическая модель — это как бы одномоментный срез информации по объекту. Например, обследование учащихся в стоматологической поликлинике дает картину состояния их ротовой полости на данный момент времени: число молочных и постоянных зубов, пломб, дефектов и т.п.

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

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

Информационные модели отражают различные типы систем объектов, в которых реализуются различные структуры взаимодействия и взаимосвязи между элементами системы. Для отражения систем с различными структурами используются различные типы информационных моделей: табличные, иерархические и сетевые.

Знаковые и вербальные информационные модели

К информационным моделям можно отнести вербальные (от лат. «verbalize» — устный) модели, полученные в результате раздумий, умозаключений. Они могут так и остаться мысленными или быть выражены словесно. Примером такой модели может стать наше поведение при переходе улицы. Человек анализирует ситуацию на дороге (что показывает светофор, как далеко находятся машины, с какой скоростью они движутся и т. п.) и вырабатывает свою модель поведения. Если ситуация смоделирована правильно, то переход будет безопасным, если нет, то может произойти авария. К таким моделям можно отнести и идею, возникшую у изобретателя, и музыкальную тему, промелькнувшую в голове композитора, и рифму, прозвучавшую пока еще в сознании поэта.

Вербальная модель – информационная модель в мысленной или разговорной форме.

Знаковая модель – информационная модель, выраженная специальными знаками, т. е. средствами любого формального языка.

Знаковые модели окружают нас повсюду. Это рисунки, тексты, графики и схемы... Вербальные и знаковые модели, как правило, взаимосвязаны. Мысленный образ, родившийся в мозгу человека, может быть облечен в знаковую форму. И наоборот, знаковая модель помогает сформировать в сознании верный мысленный образ.

Согласно легенде, яблоко, упавшее на голову Ньютону, вызвало в его сознании мысль о земном притяжении. И только впоследствии эта мысль оформилась в закон, т. е. обрела знаковую форму.

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

20

Модуль в программировании представляет собой функционально законченный фрагмент программы, оформленный в виде отдельного файла с исходным кодом или поименованной непрерывной его части (например, Active Oberon), предназначенный для использования в других программах. Модули позволяют разбивать сложные задачи на более мелкие в соответствии с принципом модульности. Обычно проектируются таким образом, чтобы предоставлять программистам удобную для многократного использования функциональность (интерфейс) в виде набора функций, классов, констант. Модули могут объединяться в пакеты и, далее, в библиотеки.

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

Модули

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

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

Все ресурсы модуля делятся на две группы: внешние – предназначенные для использования другими программными единицами, и внутренние – рабочие ресурсы данного модуля.

Структура модуля выглядит следующим образом:

Unit <имя модуля>

Interface

<интерфейсная секция>

[Begin

<секция инициализации>]

End.

Имя модуля должно совпадать с именем файла, в котором он содержится. Результат компиляции модуля помещается в файл с тем же именем и расширением .tpu.

Примечание. Среда языка Borland Pascal предусматривает три режима компиляции программы, использующей модули:

  • Compile – компилируется только основная программа, все модули должны быть предварительно откомпилированы в файлы <имя модуля> .tpu и размещены либо в текущем каталоге, либо в одном из каталогов, указанных как источники файлов .tpu в настройках среды;

  • Make – модули, для которых не обнаружены файлы .tpu, компилируются из соответствующих файлов .pas, которые должны находиться в текущем каталоге или в каталогах, указанных в настройках среды в качестве источников исходных файлов модулей;

  • Build – все ранее откомпилированные модули .tpu игнорируются и все модули компилируются из своих исходных файлов заново.

В процессе отладки модулей целесообразно использовать режим Build, а при отладке программы – режим Compile

Интерфейсная секция содержит объявление ресурсов (в том числе заголовки подпрограмм), к которым возможны обращения извне.

Секция реализации содержит описание подпрограмм, объявленных в интерфейсной секции, и описание внутренних ресурсов модуля (локальных переменных, типов, подпрограмм). Обращение к этим ресурсам возможно только из подпрограмм, описанных в том же модуле.

Секция инициализации содержит операторы, которые выполняют следующие действия, необходимые для нормальной работы процедур модуля (например, открываются файлы, инициализируют некоторые переменные и т.п.). Операторы секции инициализации выполняются один раз (при подключении модуля) до начала выполнения основной программы. Эта секция в модуле может отсутствовать.

Программа, которая использует ресурсы нескольких модулей, должна в области описаний содержать спецификацию используемых модулей:

Uses <имя модуля 1>, <имя модуля 2>,

В спецификации Uses необходимо указывать только те модули, ресурсы которых данная программная единица (программа или модуль) использует непосредственно. Если подключаемый модуль использует другие модули, то их подключение уже описано в нем. Секции инициализации подсоединяемых модулей выполняются в порядке их подключения.

В виде модулей в Borland Pascal реализованы библиотеки подпрограмм, использование которых существенно упрощает разработку программ.

Вместе с системой программирования на Borland Pascal поставляются следующие библиотеки:

  • System – основная библиотека – содержит описание всех стандартных процедур и функций, таких, как математические функции, функции преобразований, процедуры и функции обработки строки и т.п. Ресурсы данной библиотеки доступны любой программе без специального указания.

  • Crt – библиотека управления экраном в текстовом режиме – содержит описание переменных, констант и процедур и функций, обеспечивающих управление экраном, клавиатурой и динамиком.

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

  • Dos – библиотека организации взаимодействия с операционной системой MS DOS – содержит описание процедур и функций, обеспечивающих обращение к функциям операционной системы.

Поставляемые вместе с описанными модули Turbo3, Printer, Graph3, Overlay устарели и практически не используются.

При разработке собственных библиотек программисты стремятся создавать подпрограммы, имеющие широкую область применения, для чего используют специальные средства объявления параметров: открытые массивы и строки, нетипизированные параметры и параметры процедурного типа.

21

Модульное программирование - метод разработки программ, предполагающий разбиение программы на независимые модули. Считается, что:

- оптимальный по размерам модуль целиком помещается на экране дисплея;

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

1.1 Модульное программирование

Большие программы обычно разрабатывают и отлаживают по частям. Целесообразно при этом, каждая такая часть, называемая подпрограммой, была оформлена так, чтобы ее можно было использовать при решении аналогичной подзадачи в той же программе или даже при решении других задач. В Borland Pascal реализованы два типа подпрограмм: процедуры и функции.

1.1.1 Процедуры и функции

Процедуры и функции представляют собой относительно самостоятельные фрагменты программ, соответствующим образом оформленные и снабженные именем (программные блоки). По правилам Borland Pascal программные блоки – такие же ресурсы, как типы и переменные. Соответственно, они также должны быть описаны перед использованием в разделе описаний программного блока, который их использует (основной программы или вызывающей подпрограммы). Каждый блок имеет такую же структуру, как основная программа, т.е. включает заголовок, раздел описаний и раздел операторов, но заканчивается не точкой, а точкой с запятой.

Заголовок блока определяет форму вызова программы. В разделе описаний блока объявляют внутренние локальные ресурсы блока (переменные, типы, внутренние подпрограммы). Раздел операторов содержит инструкции подпрограммы в операторных скобках begin … end.

Заголовки процедур и функций описываются по-разному. В отличие от процедуры функция всегда возвращает в точку вызова скалярное значение, адрес или строку. Тип возвращаемого результата описывается в заголовке функции.

Данные для разработки процедуры и функции получают из вызвавшей их основной программы. Для размещения рабочих полей подпрограммы могут объявлять новые типы и переменные в собственном разделе описаний. Результаты же они обычно должны возвращать вызвавшей программе или подпрограмме.

Из основной программы данные могут быть получены:

  • Неявно – с использованием глобальных констант и переменных;

  • Явно – через параметры.

Неявная передача данных в подпрограммы. Каждой подпрограмме доступны все ресурсы программного блока, в разделе описаний которого эта подпрограмма объявлена. Ресурсы же основной программы доступны в любой подпрограмме. Они получили название глобальных.

В свою очередь локальные ресурсы, объявлены в разделе описания подпрограммы, из программного блока, в разделе описания которого она определена, не доступны. В том случае, если в подпрограмме объявляется ресурс, имя которого совпадает с именем глобального ресурса, соответствующий глобальный ресурс в подпрограмме становится не доступным, «перекрывается».

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

В Borland Pascal параметры в подпрограмму могут передаваться тремя способами:

  • Как значения – в подпрограмму передаются копии значений параметров, и никакие изменения этих копий не возвращаются в вызывающую программу;

  • Как переменные – в программу передаются адреса фактических параметров, соответственно все изменения этих параметров в подпрограмме на самом деле происходят с переменными, переданными в качестве фактических параметров; такие параметры при описании помечаются служебным словом var; в качестве фактических значений параметров – переменных нельзя использовать литералы;

  • Как изменяемые переменные (именованные константы) – в подпрограмму, так же как и в предыдущем случае, передаются адреса фактических параметров, но при попытке изменить значение параметра компилятор выдает сообщение об ошибке; такие параметры при описании помечаются служебным словом const.

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

<переменная>:=<имя функции>(<фактические параметры>).

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

Вызов процедуры и функции по-разному изображается на схеме алгоритма: вызов функции – в блоке «процесс» или блоке вывода, а для вызова процедуры используется специальный блок «предопределенный процесс». Схемы алгоритмов же самих подпрограмм в обоих случаях оформляются отдельно, причем вместо слова «начало» указывают имя подпрограммы, а вместо слова «конец» - указывают слово «возврат» или «return».

22