Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование на языке высокого уровня Паскаль. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
07.09.2026
Размер:
2 Мб
Скачать
☆
выполнения.
Совместимость типов
Операнды в выражениях должны быть совместимых типов. Совместимость типов величин, участвующих в каждой операции, достигается при выполнении по крайней мере одного из следующих условий.
Оба типа одинаковые. Оба типа вещественные. Оба типа целочисленные. Один тип является поддиапазоном другого. Оба типа являются отрезками одного и того же основного типа. Оба типа являются множественными типами с совместимыми базовыми типами. Один тип является строковым типом, другой — строковым типом или типом pchar. Один тип — pointer, другой — любой тип указателя. Один тип — pchar, другой — символьный массив с нулевой базой вида array [0 .. X] of char (только при разрешении расширенного синтаксиса директивой {$X +}). Оба типа являются указателями идентичных типов (только при разрешении расширенного синтаксиса директивой {$X+}). Оба типа являются процедурными с идентичными типами результатов, одинаковым числом параметров и соответствием между параметрами.
Совместимость по присваиванию
Этот вид совместимости требуется при присваивании значений, например в операторе присваивания или при передаче значений в подпрограмму.
Значение типа T1 является совместимым по присваиванию с типом
T2 (то есть допустим оператор T1 := T2 ), если выполняется одно
из следующих условий.
Программирование на языке высокого уровня ПаскальТ.А. Павловская
71
T1 и T2 — тождественные типы (кроме файловых или типов,
содержащих элементы файлового типа).
T1 и T2 — совместимые порядковые типы, при этом значения
типа T2 попадают в диапазон возможных значений T1.
T1 и T2 — вещественные типы, при этом значения типа T2
попадают в диапазон возможных значений T1.
T1 — вещественный тип, а T2 — целочисленный. T1 и T2 — строковые типы. T1 — строковый тип, а T2 — символьный ( char ). T1 и T2 — совместимые множественные типы, при этом все
значения типа T2 попадают в диапазон возможных значений T1.
T1 и T2 — совместимые типы указателей. T1 — тип pchar, а T2 — строковая константа (только при
разрешении расширенного синтаксиса директивой {$X+} ).
T1 — тип pchar, а T2 — символьный массив с нулевой базой
вида array [0 .. n] of char (только при разрешении расширенного синтаксиса директивой {$X+}).
T1 и T2 — совместимые процедурные типы. T1 представляет собой процедурный тип, а T2 — процедура
или функция с идентичным типом результата и соответствующими параметрами.
На этапе компиляции и выполнения выдается сообщение об ошибке, если совместимость по присваиванию необходима, а ни одно из условий предыдущего списка не выполнено.
Программирование на языке высокого уровня ПаскальТ.А. Павловская
72
Модульное программирование
Процедуры и функции: описание и использование. Виды параметров подпрограмм: значения, переменные, константы, открытые, процедурные. Рекурсия. Модули: описание и использование. Стандартные модули Паскаля.
Презентацию к данной работе Вы можете скачать здесь скачать: http://old.intuit.ru/department/pl/prinpas/4/Pascal_4.zip.
С увеличением объема программы становится невозможным удерживать в памяти все детали. Естественным способом борьбы со сложностью любой задачи является ее разбиение на части. В Паскале задача может быть разделена на более простые и понятные фрагменты — подпрограммы, после чего программу можно рассматривать в более укрупненном виде — на уровне взаимодействия подпрограмм.
Использование подпрограмм является первым шагом к повышению степени абстракции программы и ведет к упрощению ее структуры. Разделение программы на подпрограммы позволяет также избежать избыточности кода, поскольку подпрограмму записывают один раз, а вызывать ее на выполнение можно многократно из разных точек программы.
Следующим шагом в повышении уровня абстракции программы является группировка подпрограмм и связанных с ними данных в отдельные файлы ( модули ), компилируемые раздельно. Разбиение на модули уменьшает время перекомпиляции и облегчает процесс отладки, скрывая несущественные детали за интерфейсом модуля и позволяя отлаживать программу по частям (при этом, возможно, разным программистам).
Подпрограммы
Подпрограммы нужны для того, чтобы упростить структуру программы и облегчить ее отладку. В виде подпрограмм оформляются логически законченные части программы.
Подпрограмма — это фрагмент кода, к которому можно обратиться по
Программирование на языке высокого уровня ПаскальТ.А. Павловская
73
имени. Она описывается один раз, а вызываться может столько раз, сколько необходимо. Одна и та же подпрограмма может обрабатывать различные данные, переданные ей в качестве аргументов.
В Паскале имеется два вида подпрограмм: процедуры и функции. Они определяются в соответствующих разделах описания (до начала блока исполняемых операторов) и имеют незначительные отличия в синтаксисе и правилах вызова.
Само по себе описание не приводит к выполнению подпрограммы. Чтобы подпрограмма выполнилась, ее надо вызвать. Вызов записывается в том месте программы, где требуется получить результаты работы подпрограммы .Подпрограмма вызывается по имени, за которым следует список аргументов в круглых скобках. Если аргументов нет, скобки не нужны. Список аргументов при вызове как бы накладывается на список параметров, поэтому они должны попарно соответствовать друг другу. Правила соответствия рассматриваются далее.
Процедура вызывается с помощью отдельного оператора, а функция — в правой части оператора присваивания, например:
inc(i); writeln(a, b, c); { вызовы процедур } y := sin(x) + 1; { вызов функции }
Внутри подпрограмм можно описывать другие подпрограммы. Они доступны только из той подпрограммы, в которой описаны.
Процедуры
Структура процедуры аналогична структуре основной программы:
procedure имя [(список параметров)]; { заголовок } разделы описаний begin раздел операторов end;
Квадратные скобки в данном случае не являются элементом синтаксиса,
Программирование на языке высокого уровня ПаскальТ.А. Павловская
74
а означают, что список параметров может отсутствовать. Рассмотрим простой пример.
Пример. Найти разность средних арифметических значений двух вещественных массивов из 10 элементов.
Как видно из условия, для двух массивов требуется найти одну и ту же величину — среднее арифметическое. Следовательно, логичным будет оформить его нахождение в виде подпрограммы, которая сможет работать с разными массивами (пример 4.1 ).
program dif_average; const n = 10; type mas = array[1 .. n] of real; var a, b : mas; i : integer; dif, av_a, av_b : real; procedure average(x : mas; var av : real); { 1 } var i : integer; begin av := 0; for i := 1 to n do av := av + x[i]; av := av / n; end; { 2 } begin for i := 1 to n do read(a[i]); for i := 1 to n do read(b[i]); average(a, av_a); { 3 } average(b, av_b); { 4 } dif := av_a – av_b; writeln('Разность значений ', dif:6:2); end.
Листинг 4.1. Разность средних арифметических значений массивов (процедура)
Описание процедуры average расположено в строках с {1} по {2 }. В строках {3} и {4} эта процедура вызывается сначала для обработки массива а, затем — массива b. Массивы передаются в качестве аргументов. Результат вычислений возвращается в главную
Программирование на языке высокого уровня ПаскальТ.А. Павловская
75
программу через второй параметр процедуры.
Функции
Описание функции отличается от описания процедуры незначительно:
function имя [(список параметров)] : тип; { заголовок } разделы описаний begin раздел операторов имя := выражение; end;
Квадратные скобки в данном случае означают, что список параметров может отсутствовать. Функция вычисляет одно значение, которое передается через ее имя. Следовательно, в заголовке должен быть описан тип этого значения, а в теле функции — оператор, присваивающий вычисленное значение ее имени. Он не обязательно должен находиться в конце функции. Более того, таких операторов может быть несколько — это определяется алгоритмом. Рассмотрим пример применения функции для программы, приведенной в предыдущем разделе.
Пример. Найти разность средних арифметических значений двух вещественных массивов из 10 элементов (пример 4.2).
program dif_average1; const n = 10; type mas = array[1 .. n] of real; var a, b : mas; i : integer; dif : real; function average(x : mas) : real; { 1 } var i : integer; { 2 } av : real; begin av := 0; for i := 1 to n do av := av + x[i];
Программирование на языке высокого уровня ПаскальТ.А. Павловская
76
average := av / n; { 3 } end; begin for i := 1 to n do read(a[i]); for i := 1 to n do read(b[i]); dif := average(a) – average(b); { 4 } writeln('Разность значений ', dif:6:2) end.
Листинг 4.2. Разность средних арифметических значений массивов (функция)
Оператор {1} представляет собой заголовок функции. Тип функции определен как вещественный, потому что к такому типу относится среднее арифметическое элементов вещественного массива. Оператор
{3} присваивает имени функции вычисленное значение. В операторе {4} функция вызывается дважды: сначала для одного массива, затем
для другого.
Глобальные и локальные переменные
Глобальными называются переменные, описанные в главной программе. Переменные, которые не были инициализированы явным образом, перед началом выполнения программы обнуляются. Время жизни глобальных переменных — с начала программы и до ее завершения.
Внутри подпрограмм описываются локальные переменные. Время их жизни — с начала работы подпрограммы и до ее окончания. Значения локальных переменных между двумя вызовами одной и той же подпрограммы не сохраняются, и эти переменные предварительно не обнуляются.
ПРИМЕЧАНИЕ Если переменная внутри подпрограммы определена в разделе описания констант, - начальное значение ей присваивается один раз до начала работы программы. Время жизни такой переменной — вся программа, то есть значение этой переменной сохраняется между вызовами подпрограммы. Область действия переменной —
Программирование на языке высокого уровня ПаскальТ.А. Павловская
77
подпрограмма, в которой она описана.
Глобальные переменные доступны в любом месте программы или подпрограммы, кроме тех подпрограмм, в которых описаны локальные переменные с такими же именами. Локальные переменные могут использоваться только в подпрограмме, в которой они описаны, и всех вложенных в нее.
Понятно, что никаких дополнительных усилий по передаче глобальных переменных в подпрограмму не требуется: они видны в ней естественным образом. Этот способ обмена информацией между главной программой и подпрограммой — самый простой, но он же и самый плохой.
В подавляющем большинстве случаев для обмена данными между вызывающей и вызываемой подпрограммами предпочтительнее использовать механизм параметров. Если все данные передаются подпрограммам через списки параметров, для локализации места ошибки достаточно просмотреть заголовки подпрограмм, а затем — тексты только тех из них, в которые передается интересующая нас переменная.
ВНИМАНИЕ Подпрограмму надо писать таким образом, чтобы вся необходимая для ее использования информация содержалась в ее заголовке.
Виды параметров подпрограмм
Список параметров, то есть величин, передаваемых в подпрограмму и обратно, содержится в ее заголовке. Для каждого параметра обычно задаются его имя, тип и способ передачи. Либо тип, либо способ передачи могут не указываться.
В заголовке подпрограммы нельзя вводить описание нового типа — там должны использоваться либо имена стандартных типов, либо имена типов, описанных программистом ранее в разделе type.
В Паскале существует четыре вида параметров: значения, переменные,
Программирование на языке высокого уровня ПаскальТ.А. Павловская
78
константы и нетипизированные параметры.
Кроме того, по другим критериям можно выделить особые виды параметров:
открытые массивы и строки; процедурные и функциональные параметры; объекты.
Параметры-значения
Параметр-значение описывается в заголовке подпрограммы следующим образом:
имя : тип;
Например, передача величины целого типа в процедуру Р записывается так:
procedure P(x : integer);
Имя параметра может быть произвольным. Параметр х можно представить себе как локальную переменную, которая получает свое значение из главной программы при вызове подпрограммы. В подпрограмму передается копия значения аргумента.
Механизм передачи следующий: из ячейки памяти, в которой хранится переменная, передаваемая в подпрограмму, берется ее значение и копируется в область сегмента стека, называемую областью параметров. Подпрограмма работает с этой копией, следовательно, доступа к ячейке, где хранится сама переменная, не имеет. По завершении работы подпрограммы стек освобождается. Такой способ называется передачей по значению. Ясно, что им можно пользоваться только для величин, которые не должны измениться после выполнения подпрограммы, то есть для ее исходных данных.
При вызове подпрограммы на месте параметра, передаваемого по значению, может находиться выражение (а также, конечно, его частные
Программирование на языке высокого уровня ПаскальТ.А. Павловская
79
случаи — переменная или константа). Тип выражения должен быть совместим по присваиванию с типом параметра.
Например, если в вызывающей программе описаны переменные
var x : integer; c : byte; y : longint;
то следующие вызовы подпрограммы Р, заголовок которой описан выше, будут синтаксически правильными:
P(x); P(c); P(y); P(200); P(x div 4 + 1);
Недостатками передачи по значению являются затраты времени на копирование параметра, затраты памяти в стеке и опасность его переполнения, когда речь идет о параметрах, занимающих много места, например массивах большого размера.
Параметры-переменные
Признаком параметра-переменной является ключевое слово var перед описанием параметра:
var имя : тип;
Например, параметр-переменная целого типа в процедуре Р записывается так:
procedure P(var x : integer);
При вызове подпрограммы в область параметров копируется не значение переменной, а ее адрес, и подпрограмма через него имеет доступ к ячейке, в которой хранится переменная. Этот способ передачи параметров называется передачей по адресу. Подпрограмма работает непосредственно с переменной из вызывающей программы и, следовательно, может ее изменить, поэтому результаты работы подпрограммы должны быть только параметрами-переменными.
При вызове подпрограммы на месте параметра-переменной может находиться только ссылка на переменную точно того же типа. Исходные
Программирование на языке высокого уровня ПаскальТ.А. Павловская
80
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]