Песни о Паскале — страница 44 из 112



Рис.78 – Структура программы на языке Паскаль

Каждую секцию открывает своё ключевое слово. Три секции: Const, Type и Var – образуют описательную часть программы. Здесь компилятор черпает информацию о размещении данных в памяти. Секции с описаниями процедур и функций и главная программа формируют исполнительную часть, – здесь содержатся исполняемые операторы (секция кода). Все секции, кроме главной программы, необязательны. Но, при необходимости, секции могут повторяться и чередоваться в любом порядке, соблюдая два простых правила:

• любой объект программы – будь то константа, тип, переменная или процедура – объявляется до своего применения;

• главная программа располагается в тексте последней (хотя исполнение начинается именно с нее!).

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

Структура процедур и функций

Процедуры и функции – основные строительные блоки программ, в крупных проектах их сотни. Главная программа обычно содержит несколько операторов, а основная работа отдается процедурам и функциям. Такой подход не только упрощает разработку, отладку и понимание программ, но и существенно уменьшает их размер (объём занимаемой памяти). Всё, что требует алгоритм, достигается вызовом одних процедур и функций из тела других, – то есть применением вложенных вызовов. Глубина вложения таких «матрешек» практически не ограничена. Опытный программист обычно разбивает большую программу на ряд мелких и простых процедур и функций.

Внутренняя структура процедур и функций схожа со структурой программы. Это своего рода программы в программе, потому их и называют подпрограммами. На рис. 79 показана упрощенная структура процедуры с условным именем ABC.



Рис.79 – Структура процедуры

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

• любой объект объявляется до своего применения;

• тело процедуры или функции обязательно и размещается последним.

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

Обмен данными с подпрограммами

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

• через глобальные переменные;

• через параметры процедур и функций;

• возвратом результата через имя функции.

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

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

Табл. 4 – Три способа передачи данных через параметры

Способ передачи данныхПример заголовка процедурыПример вызова
По значению:в процедуру передается значение параметра.Procedure ABC (arg:integer);ABC(10);ABC(X+3);
По ссылке CONST:В процедуру передается ссылка на константу или переменную, содержащую данные.Procedure ABC (const arg:integer);ABC(10);ABC(X);
По ссылке VAR:В процедуру передается ссылка на переменную, содержащую данные.Procedure ABC (var arg:integer);ABC(X)

Опытного программиста отличает умение эффективно передавать данные; табл. 5 поможет вам выбрать наиболее удачный способ такой передачи.

Табл. 5 – Рекомендуемые способы передачи данных

Куда передавать данныеРекомендуемый способ
Только в процедуру или функцию1) По значению (простые типы) 2) По ссылке CONST (сложные типы)
Только из процедуры и функции1) Через имя функции (одно значение) 2) По ссылке VAR (несколько значений)
В обоих направленияхПо ссылке VAR (любые данные)

В каждом случае предпочтительный способ указан первым. Данные простых типов лучше передавать внутрь подпрограмм по значению. По ссылке CONST передают строки и другие сложные типы данных (скоро мы изучим их). Через имя функции возвращают лишь один результат. А если надо вернуть несколько результатов, или вернуть сложный тип данных, используют ссылки VAR.

Встроенные процедуры и функции

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

Текстовые файлы

Напоследок напомню об основных средствах обработки текстовых файлов.

Для чтения из файлов применяют следующие процедуры и функции:


Assign(F, ...) - Связать файловую переменную с файлом

Reset(F)       - Открыть файл для чтения

Read(F, ...)   - Прочитать часть строки файла

Readln(F, ...) - Прочитать строку файла и перейти к следующей

Eoln(F)        - Проверить на конец строки

Eof(F)         - Проверить на конец файла

Close(F)       - Закрыть файл


Для записи в файл применяют такие процедуры:


Assign(F, ...)  - Связать файловую переменную с файлом

Rewrite(F)      - Открыть файл для записи

Write(F, ...)   - Записать часть строки файла

Writeln(F, ...) - Записать строку файла и перейти к следующей

Close(F)        - Закрыть файл


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


var F_In, F_Out : Text;

begin

  Assign(F_In,’’);	Reset(F);	{ F_In связали с клавиатурой }

  Assign(F_Out,’’);	Rewrite(F);	{ F_Out связали с экраном }

	. . .

end.


Второй приём заключается в применении специального имени "CON" — от слова Console (оно предусмотрено в MS-DOS и Windows).


  Assign(F_In,’Con’);	Reset(F);	{ F_In связали с клавиатурой }

  Assign(F_Out,’Con’);	Rewrite(F);	{ F_Out связали с экраном }


В операционных системах MS-DOS и Windows существует несколько специальных имен файлов, вот некоторые из них:


AUX  - Первый асинхронный коммуникационный порт

CON  - Клавиатура и экран (CONsole)

NUL  - Фиктивное устройство (для тестирования)

PRN  - Первый параллельный принтер


Аналогичные имена применяют и в UNIX-подобных системах.

Наконец, для действий с текстовыми файлами можно применять две встроенные в язык файловые переменные: INPUT и OUTPUT. Они не нуждаются ни в объявлении, ни в открытии, ни в закрытии файлов:


  Readln(Input, S);    { - то же самое, что Readln(S) }

  Writeln(Output, S);  { - то же самое, что Writeln(S) }


Файловые переменные INPUT и OUTPUT можно передавать в качестве фактических параметров внутрь процедур и функций, а также связывать их с дисковыми файлами. Вот пример копирования файла из «MyText.in» в «MyText.out»:


var S: string;

begin

  Assign(Input,’MyText.in’);   Reset(Input);

  Assign(Output,’MyText.out’); Rewrite(Output);

  While not Eof do begin

    Readln(S);

    Writeln(S);

  end;

  Close(Input); Close(Output);

end.


Что дальше?

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