Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
на экзамен 30.12.2013..docx
Скачиваний:
1
Добавлен:
01.05.2025
Размер:
195.37 Кб
Скачать

4.2.4.2. Полный условный оператор

   Блок-схему полного условного оператора можно представить так: полной формы.

Рисунок 10. Блок-схема условного оператора

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

IF

Логическое выражение

THEN

Оператор1

ELSE

Оператор2

;

   Эта запись читается следующим образом: "если логическое выражение справедливо, то выполняется первый оператор, если ложно - второй оператор". Операторы 1 и 2 могут быть простые или составные. Точка с запятой перед словом ELSE не ставится.

   Примеры полных условных операторов:

IF x<0 THEN i:=i+1 ELSE j:=j+1;

IF (x<y) AND (x<>0) THEN begin x:=y/x; y:=y+k end ELSE begin x:=x+0.01; y:=y-k end;

 

4.2.4.3. Сокращенный условный оператор

   Блок-схему сокращенного условного оператора можно представить так:

Рисунок 11. Блок-схема условного оператора сокращенной формы.

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

IF

Логическое выражение

THEN

Оператор

;

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

   Примеры использования условного оператора в сокращенной форме:

IF x>y THEN Max:=x;

IF x<>0 THEN begin a:=y/x; Writeln('A= ', a:6:2) end;

 

4.2.4.4. Создание сложных разветвлений алгоритма

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

IF

Логическое выражение

THEN

Оператор 1

ELSE

Оператор 2

;

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

If условие 1 then if условие 2 then оператор 1 else оператор 2;

можно истолковать двояко:

1) IF условие 1 THEN

begin IF условие 2 THEN оператор 1 end

ELSE оператор 2;

2) IF условие 1 THEN

begin IF условие 2 THEN оператор 1 ELSE оператор 2 end;

   По правилам языка Паскаль имеет место 2-я трактовка, т.е. считается, что каждое слово ELSE соответствует первому предшествующему ему слову THEN. Во избежание ошибок рекомендуется четко выделять желаемую форму условного оператора с помощью операторных скобок begin ... end :

IF j<>0 THEN

begin IF x<0 THEN x:=x-1 end

ELSE

begin IF x<y THEN x:=x+0.5 ELSE y:=y+0.5 end;

   Приведем пример программы, использующей условный оператор.

Program Primer1;

Uses Crt;

Var x,y,z:Real;

Begin

TextColor(Yellow); TextBackGround(Blue);

ClrScr;

Write('x= '); Readln(x);

Write('y= '); Readln(y);

IF x<0 THEN

IF x>y THEN z:=x ELSE z:=y

ELSE

IF x<y THEN z:=x ELSE z:=y;

Writeln('z= ',z:6:2);

Readln

End.

4.2.5. Оператор перехода. Пустой оператор

В Паскале принят естественный порядок выполнения операторов, т.е. операторы обычно выполняются в порядке их следования в тексте программы. Между тем ОПЕРАТОР ПЕРЕХОДА позволяет задавать любой желаемый порядок выполнения вычислений.

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

GOTO

Метка

;

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

МЕТКА : ОПЕРАТОР ;

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

LABEL 25, 0, Loop, 21, lab1;

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

Следует помнить, что частое использование оператора перехода ухудшает наглядность программы, затрудняет ее понимание и отладку. Еще в марте 1968г. на эту тему была опубликована историческая статья голландского программиста Эдсгера Дейкстри "GOTO Statement Considered Harmful" ("о вреде оператора GOTO"). Использование оператора перехода обосновано лишь в отдельных случаях, например для досрочного выхода из цикла или перехода в конец программы для окончания ее работы:

Program Primer;

LABEL 25;

VAR N,S:Real;

Begin

Readln(S);

Readln(N);

IF N<0 THEN begin S:=N+2; GOTO 25 end;

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

25: Writeln('S= ',S:6:2)

End.

ПУСТОЙ ОПЕРАТОР не предписывает никаких действий, он представляет собой пустую последовательность символов (т.е. отсутствие символов). Как и обычные операторы, пустой оператор может быть помечен меткой. Пустой оператор отделяется от других операторов точкой с запятой.

Наиболее часто пустой оператор используется для того, чтобы поместить в программе "точку", на которую должен осуществляться переход по оператору перехода, но при этом не надо выполнять никаких дополнительных действий; например, надо просто выйти из программы - для этого ставим пустой оператор с меткой перед словом end:

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

GOTO 5;

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

5:; End.

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

1:; 2: A:=B+C;

4.2.6. Комментарии

При программировании желательно вставлять в текст создаваемой программы КОММЕНТАРИЙ - несколько фраз, поясняющих суть выполняемых программой действий. В ходе трансляции текста программы компилятор обходит комментарии, не принимает их во внимание и не включает в исполняемые коды программы. Единственное назначение комментария - служить справочной информацией для человека, читающего текст программы. Отсутствуют универсальные правила для определения мест, где следует располагать комментарии. Размещение и содержание комментариев в основном зависит от личных представлений программиста. Грамотно представленные комментарии позволяют ответить на большинство вопросов, возникающих при знакомстве с текстом программы: что делает данная программа, что обозначает каждая переменная, какова цель данного оператора, и т.д. В Паскале комментарии создаются обрамлением с обоих сторон какой-нибудь текстовой строки условными символами { } или (* *), например:

{ В этом месте программа ожидает ввода числа }

или

(* Конец раздела описаний, начинаем основную программу *).

4.2.7. Оператор цикла

4.2.7.1. Понятие о цикле

При разработке алгоритмов решения большинства задач возникает необходимость многократного повторения однотипных команд. Такой повтор может быть реализован с помощью уже знакомых нам оператора перехода и условного оператора. Предположим, что требуется пять раз вывести на экран слово "ЦИКЛ". Составим соответствующую программу:

Program Primer;

Uses Crt;

Label Loop;

Var i:Integer; {Эта переменная будет использоваться в качестве}

{счетчика повторов}

Begin

TextColor(Yellow); TextBackGround(Blue);

ClrScr; {Настроили цвет, очистили экран}

i:=1; {Установили начальное значение счетчика}

Loop: IF i<=5 THEN Begin

Writeln('ЦИКЛ');

i:=i+1; { Значение переменной- счетчика увеличиваем на единицу }

GOTO Loop         {Повторяем алгоритм от метки LOOP до тех пор,}

{пока значение счетчика не превысит 5}

End;

Readln

End.

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

4.2.7.2. Оператор цикла с параметром

Общий вид оператора цикла с параметром:

FOR i:= A TO B DO оператор;

где i - параметр цикла (счетчик повторов)- переменная целого типа (integer);

A и B - начальное и конечное значения параметра цикла- выражения того же типа, что и параметр цикла;

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

Оператор цикла типа FOR...TO...DO предусматривает последовательное увеличение на единицу параметра цикла "i" от начального значения "A" до конечного значения "B" и выполнение входящего в цикл алгоритма при каждом значении параметра цикла.

В качестве иллюстрации применения оператора цикла FOR...TO...DO рассмотрим решение с его помощью предыдущей задачи, где на экран несколько раз выводится слово "ЦИКЛ".

Program Primer;

Uses Crt;

Var i:integer;

Begin

TextColor(Yellow); TextBackGround(Blue);

ClrScr;

FOR i:=1 TO 5 DO Writeln('ЦИКЛ');

Readln

End.

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

Program Primer;

Uses Crt;

Var i,N,S:integer;

Begin

TextColor(Green); TextBackGround(Cyan);

ClrScr;

Write('N= '); Readln(N); {C клавиатуры ввели целое число в переменную “N”}

S:=0; {Задали начальное значение суммы}

FOR i:=1 TO N DO S:=S+i; { Во время каждого из повторов }

{ значение суммы "S" увеличивается }

{ на новую величину счетчика "i" }

Writeln('S= ',S:6);

Readln

End.

В этой программе оператор "S:=S+i" выполняется "N" раз, при различных значениях параметра цикла "i".

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

FOR i:=B    DOWNTO A    DO   оператор;

где i, A и B имеют прежний смысл. Отличие от предыдущего варианта цикла в том, что в операторе цикла типа FOR...DOWNTO...DO шаг наращивания параметра равен -1, при этом начальное значение счетчика повторов "B" больше конечного значения "A".

Проследим, как изменится предыдущий пример при нисходящем изменении значения параметра цикла:

Program Primer;

Uses Crt;

Var i,N,S:integer;

Begin

TextColor(Red); TextBackGround(White);

ClrScr;

Write('N= '); Readln(N);

S:=0; {начальное значение суммы}

FOR i:=N DOWNTO 1 DO S:=S+i;

Writeln('S= ',S:6);

Readln

End.

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

нельзя задавать шаг изменения значения параметра, отличный от 1 или -1;

не желательно изменять внутри цикла значения параметра цикла, начальное и конечное значения параметра;

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

4.2.7.3. Оператор цикла с предусловием

Если число повторений, выполняемых в цикле, заранее не известно или шаг приращения счетчика (параметра) цикла отличен от единицы, то необходимо использовать оператор цикла с предусловием. Оператор цикла этого вида имеет вид:

WHILE

условие

DO

оператор

;

где условие - это логическое выражение, от значения которого зависит- продолжать повторы или завершить цикл;

оператор - любой простой или составной оператор.

Выполнение оператора начинается с вычисления значения логического выражения. Если оно имеет значение "True" (истина), то выполняется оператор (операторы), входящий в цикл. Выполнение цикла продолжается до тех пор, пока логическое выражение в его заголовке не примет значение "False" (ложно). Если выражение равно "False" при первом же витке цикла, то работа цикла завершится, а входящие в него операторы не выполнятся ни разу. Поскольку в цикле типа WHILE...DO условие завершения его работы проверяется до выполнения входящего в него оператора, такой цикл называется "оператор цикла с предусловием".

Пример использования оператора цикла с предусловием:

Program Primer;

Var K:integer;

Begin

K:=0;

WHILE K<=10 DO

begin K:=K+2; Write('K= ',K:3) end;

Readln

End.

4.2.7.4. Оператор цикла с постусловием

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

REPEAT

оператор1, оператор2, ... , операторN

UNTIL условие;

где оператор1, оператор2, ... , операторN - операторы тела цикла;

условие - логическое выражение, диктующее завершение повторов.

Оператор цикла с постусловием начинается с выполнения операторов внутри цикла. Затем проверяется истинность логического условия, стоящего после слова UNTIL. Если это условие справедливо (True), то осуществляется выход из цикла. Если же значение логического выражения ложно (False), то выполнение операторов тела цикла повторяется, после чего снова проверяется истинность логического условия.

Пример программы, использующей оператор цикла с постусловием:

Program Primer;

Var K:Integer;

Begin

K:=0;

REPEAT

K:=K+2; Write('K= ',K:3)

UNTIL K>10;

Readln

End.

4.2.7.5. Правила использования операторов цикла

При использовании операторов цикла следует учитывать следующие особенности:

  1. Операторы, входящие в цикл Repeat...Until, всегда выполняются хотя бы один раз, поскольку истинность логического выражения в цикле этого типа проверяется после операторов, входящих в тело цикла. При использовании цикла типа WHILE...DO могут быть ситуации, когда операторы, входящие в цикл, не будут выполнены ни разу, если логическое выражение изначально имеет значение "FALSE".

  2. Цикл Repeat...Until выполняется, пока логическое выражение имеет значение "FALSE". Цикл While...Do выполняется, пока логическое выражение имеет значение "TRUE". Этот нюанс следует учитывать при замене цикла одного типа другим.

Program Whl;

Var i:integer;

Begin

i:=1;

WHILE i<=10 DO

begin

Writeln('Привет');

i:=i+1

end;

Readln

End.

Program Rep;

Var i:integer;

Begin

i:=1;

REPEAT

Writeln('Привет');

i:=i+1

UNTIL i>10;

Readln

End.

  1. Если тело цикла "WHILE...DO" состоит из нескольких операторов, их следует обрамлять операторными скобками "begin...end", образующими составной оператор. В цикле типа "REPEAT...UNTIL" операторные скобки не нужны.

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

k1:=1;    WHILE k1<5 DO Writeln('Бесконечный цикл');

Если в программе встретится такой фрагмент, то экран заполнится строками с фразой "Бесконечный цикл", выдача которой в режиме прокрутки (Scrolling) будет длиться до тех пор, пока программистом не будут приняты действия по принудительному завершению работы программы. Вывести программу из бесконечного цикла можно, дважды нажав сочетание клавиш “Ctrl” и “Break”, после чего надо нажать клавишу “ESC”.

Зацикливания не произойдет, если операторы, входящие в тело цикла, будут влиять на условие, определяющее завершение цикла:

k1:=1;

WHILE k1<5 DO

Begin

Writeln('Цикл');

k1:=k1+1

end;

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

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

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

REPEAT

...........

UNTIL X=B;

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

где X, B : Real, будет неправильным, хотя с математической точки зрения он верен. Условие "X=B" скорее всего никогда не выполнится, в результате произойдет "зацикливание" программы. Не следует управлять циклом с помощью логического выражения, в котором вещественные переменные проверяются на строгое равенство.

4.2.8. Оператор варианта "CASE"

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

CASE селектор OF

метка1: оператор1;

метка2: оператор2;

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

меткаN: операторN

ELSE альтернативный оператор

END;

Оператор CASE состоит из селектора (переменной целого, символьного или логического типа) и списка операторов, каждому из которых предшествует метка варианта, представляющая собой значение того же типа, что и селектор. При работе оператора CASE будет выполнен тот входящий в него оператор, чья метка равна текущему значению селектора. Если ни одна из меток не содержит значения селектора, то не выполняется ни один оператор. Следует оговориться, что Турбо-Паскаль, в отличие от стандартного Паскаля, допускает использование в операторе CASE ключевого слова ELSE. В случае отсутствия меток, равных значению селектора, выполняется оператор, стоящий за словом ELSE (альтернативный оператор). Подчеркнем, что "метку варианта" не следует путать с "меткой оператора", используемой в операторе перехода GOTO. Метки варианта не описываются в блоке LABEL раздела описаний программы и не используются в операторе перехода GOTO.

Примеры использования оператора CASE:

..........

...........

Label Final;

Var

Var

Var Operator:Char;

i,m:integer;

Symbol:Char;

Rez:integer;k:integer;

Begin

Begin

Begin

CASE i OF

CASE Symbol OF

CASE Operator OF

0: m:= 0;

'=': k:=1;

'+': Rez:=Rez+1;

1: m:= -1;

'!': k:=2;

'-': Rez:=Rez-1;

2: m:= 1

'.': k:=3

ELSE GOTO Final

End;

End;

End;

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

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

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

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

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

Final: ...............

End.

End.

End.

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

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

Var i,m:integer;

Begin

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

CASE i OF

0:         m:=0;

1,2,3: m:=4;

4:         m:=-1

End;

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

End.

Войти в оператор варианта можно только через его начало: CASE селектор OF;

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

4.2.9. Массивы

4.2.9.1. Одномерные массивы

4.2.9.1.1. Понятие о массиве

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

МАССИВ - упорядоченная группа фиксированного количества переменных одного типа, имеющая общее имя.

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

"Упорядоченная"- означает, что переменные в массиве хранятся не хаотично, а в установленном порядке, по очереди.

"Фиксированное количество" означает, что количество переменных в массиве не бесконечно, оно ограничено определенным числом (размерностью массива), которое указывается при описании массива.

"Одного типа" - означает, что переменные, входящие в массив, должны хранить данные одного типа (Real, Integer, Char, Boolean и т.д.), который называется типом элементов массива.

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

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

Каждый элемент массива имеет свое имя, представляющее собой имя массива и стоящие за ним квадратные скобки, в которых указывается индекс элемента - целое число, равное порядковому номеру этого элемента в массиве. Таким образом, для ссылки на отдельный элемент массива используется запись вида: имя массива[индекс]. Например: A[1], D[24], Massiv[5], Mas[12].

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

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

KWatt1

KWatt2

KWatt3

...

KWatt30

KWatt31

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

Массив “KWatt”:

KWatt[1]

KWatt[2]

KWatt[3]

...

KWatt[31]

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

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

{начальное значение счетчика цикла равно 1}

i:=1;

{начальное значение переменной Max, предназначенной}

Max:=0;

{для хранения максимального значения массива, равно 0}

REPEAT

{начинаем цикл}

IF KWatt[i]>Max

{если значение очередного элемента массива}

THEN

{превышает текущее значение переменной Max,}

Max:=KWatt[i];

{то переменная Max меняет свое значение на}

{значение элемента массива}

i:=i+1

{увеличиваем значение счетчика на единицу}

UNTIL i>31;

{цикл заканчивается, если значение счетчика цикла превысит число 31}

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

мы без труда догадаемся, что здесь идет поиск максимального числа (Max) из набора однотипных данных (KWatt[i]).

4.2.9.1.2. Описание массивов

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

VAR Имя массива : ARRAY[размерность] OF тип элементов ;

К имени массива предъявляются те же требования, что и к имени переменной.

Размерность - это диапазон целых чисел, каждое из которых является порядковым номером (индексом) одной из ячеек массива. Обычно диапазон индексов задают, начиная от единицы: [1..100]. Это удобно, но не обязательно. Важно лишь, чтобы правая граница диапазона была больше или равна левой границе.

Program Primer;

Const Max=100;

Var A:Array[1..50] of Real;

{массив "А" состоит из 50-ти вещественных чисел}

B:Array[1..Max] of integer;

{массив "В" состоит из ста целых чисел}

Mas:Array[1999..2000] of integer;

{массив "Mas" состоит из 2-х целых чисел}

Mas2:Array[-700..-1] of Real;

{массив "Mas2" состоит из 700 вещественных чисел}

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

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

4.2.9.1.3. Использование значений массивов, ввод и вывод значений массивов

Как уже отмечалось, для ссылки на отдельные элементы массива используется переменная с индексом: Имя массива[индекс]. Чтобы получить доступ к конкретному элементу массива, в качестве индекса можно использовать не только целое число, соответствующее порядковому номеру этого элемента в массиве, но и выражение, значение которого равно упомянутому целому числу. Например, при обращении к элементам некоторого массива "A: Array[1..100] of Real", в качестве индекса можно использовать любое арифметическое выражение, значением которого будет целое число из диапазона 1..100:

A[56]; A[i+7]; A[i div j] .

Вводить и выводить значения из массивов целесообразно поэлементно, используя в цикле операторы Readln, Write, Writeln и оператор присваивания.

Program Vvod_Vivod;

Var i:integer;

A:Array[1..20] of Real;

B:Char;

Begin

Writeln('Введите числа в массив: ');

FOR i:=1 TO 20 DO

begin Write('A[',i,']= '); Readln(A[i]) end;

Writeln('Массив заполнен, будете выводить');

Write('значения на экран? ("Y"-да, "N"-нет)=>');

Readln(B);

IF UpCase(B)="Y" THEN

{если прописной вариант введенной}

FOR i:=1 TO 20 DO Writeln('A[',i,']=',A[i]:6:2);

{буквы является "Y", то}

Readln

End.

Приведем другие примеры использования массивов.

  1. Попарное суммирование элементов массивов А и В.

Program Prim1;

Const N=10;

Var i:integer;

A,B,C:Array[1..N] of Real;

Begin

FOR i:=1 TO N DO

begin

Write('A[',i,']= '); Readln(A[i]);

Write('B[',i,']= '); Readln(B[i])

end;

FOR i:=1 TO N DO C[i]:=A[i]+B[i];

Writeln('----------------------------------');

FOR i:=1 TO N DO Writeln('C[',i,']=',C[i]:6:1);

Readln

End.

  1. Объединим в массиве “С” массивы “А” и “В” так, чтобы их элементы чередовались: элементы из массива “А” занимали нечетные ячейки, а элементы массива “В” - четные.

Program Prim2;

Const N=10;

Var i:integer;

A,B:Array[1..N] of Real;

C:Array[1..N*2] of Real;

Begin

FOR i:=1 TO N DO

begin

Write('A[',i,']= '); Readln(A[i]);

Write('B[',i,']= '); Readln(B[i])

end;

FOR i:=1 TO N DO

begin

C[2*i-1]:=A[i];

C[2*i]:=B[i]

end;

Writeln('------------------------------');

FOR i:=1 TO 2*N DO Writeln('C[',i,']=',C[i]:6:1);

Readln

End.

4.2.9.1.4.Двумерные массивы

Одномерный массив (вектор) имеет вид таблицы из одной строки, ячейки которой заполнены значениями. Рассматривая ДВУМЕРНЫЙ массив, можно провести аналогию с таблицей, имеющей несколько строк и столбцов. Если отдельный элемент одномерного массива мы обозначали именем массива с индексом (А[i]), то для обозначения элемента двумерного массива (матрицы) потребуются два индекса: один - для указания номера строки, другой - для указания номера столбца, на пересечении которых находится нужный элемент: А[i,j]. Двумерные массивы описываются сходно с массивами одномерными:

Const Str=4;

Stolb=5;

Var A:Array[1..Str,1..Stolb] of Real;

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

FOR i:=1 TO Str DO

FOR j:=1 TO Stlb DO Readln(A[i,j]);

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

FOR i:=1 TO Str DO

FOR j:=1 TO Stlb DO Writeln('A[',i,',',j,']=',A[i]:6:2);

здесь Str- число строк, Stlb- число столбцов.

4.2.9.1.5. Полная переменная

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

Если полные переменные А и В имеют один и тот же тип (были описаны одинаково) и всем элементам массива "А" были присвоены значения, то для присвоения полной переменной "В" точно такого же значения достаточно выполнить оператор присваивания В:=А.

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

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

Над значениями полных переменных в Паскале не выполняются операции сравнения.

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

VAR X:Real;

Y:Array[1..1] of Real;

недопустимы операторы присваивания

X:=Y; Y:=X; X:=Y+0.5; Y:=3.14159;

4.3. Подпрограммы

4.3.1. Понятие о подпрограмме

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

4.3.2. Основные сведения о процедурах

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

Program......

Uses........

Label.......

Const.......

Type........

Var.........

Procedure   Заголовок процедуры;

Begin

Раздел операторов процедуры

End;

Процедура имеет ту же структуру, что и главная программа (PROGRAM): разделы Label, Const, Type, Var и выполняемую часть.

Procedure имя процедуры;

Label....

Const....

Type.....

Var......

Begin

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

End;

Как можно видеть, имеется только два отличия процедуры от основной программы: процедура начинается с заголовка "Procedure", а не "Program", и заканчивается не точкой, а точкой с запятой.

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

Чтобы выполнить процедуру, надо упомянуть ее имя в требуемом месте программы.

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

Даны X и Y. Найти: U=Max(X+Y, X*Y); V=Max(0.5, U).

Запишем программу решения этой задачи без использования процедуры:

Program Max;

Var x,y,u,v:Real;

a,b,s:Real;

Begin

Write('x= '); Readln(x);

Write('y= '); Readln(y);

a:=x+y; b:=x*y;

IF a>b THEN s:=a ELSE s:=b;

u:=s;

a:=0.5; b:=u;

IF a>b THEN s:=a ELSE s:=b;

v:=s;

Writeln('U= ',U:5:1, 'V= ',V:5:1);

Readln

End.

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

4.3.3. Процедуры без параметров

В приведенном примере условные операторы в точности совпадают друг с другом, поэтому можно считать, что один и тот же условный оператор присутствует в программе дважды. Чтобы избежать двукратного повторения этого оператора в основной программе, представим его процедурой, которой дадим имя "Proced":

Procedure Proced;

begin

IF a>b THEN s:=a ELSE s:=b

end;

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

Program Max;

Var x,y,u,v:Real;

a,b,s:Real;

Procedure Proced;

begin

IF a>b THEN s:=a ELSE s:=b

end;

Begin

Write('x= '); Readln(x);

Write('y= '); Readln(y);

a:=x+y; b:=x*y;             PROCED; u:=s;

a:=0.5; b:=u;                  PROCED; v:=s;

Writeln('U= ', u:5:1, 'V= ',v:5:1);

Readln

End.

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

4.3.4.Процедуры с параметрами

Созданная нами процедура "Proced" неудобна в употреблении, так как поставщиками исходных данных для нее могут быть только переменные "a" и "b". Это приводит к тому, что эта процедура должна всегда сопровождаться указанными переменными, и каждый раз перед обращением к ней приходится присваивать переменным "a" и "b" значения. Чтобы устранить это ограничение и тем самым сделать процедуру более универсальной, удобной в использовании, язык Паскаль позволяет передавать информацию внутрь подпрограммы с помощью ПАРАМЕТРОВ, которые конкретизируются (приобретают значения) при каждом вызове процедуры. Различают две разновидности параметров - параметры формальные и параметры фактические.

ФОРМАЛЬНЫЕ ПАРАМЕТРЫ - это переменные, которые используются только внутри процедуры во время ее работы и играют роль приемника информации, поступающей извне. Поставщиками информации (конкретных значений) для формальных параметров являются ФАКТИЧЕСКИЕ ПАРАМЕТРЫ.Фактическими параметрами могут служить переменные, константы, числа, выражения. При вызовах процедуры в разных частях основной программы, могут меняться фактические параметры, но формальные параметры, находящиеся внутри процедуры и воспринимающие значения от фактических параметров, остаются без изменений, меняются только хранимые ими значения.

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

Procedure Proced(p1,p2:Real);

begin

IF p1>p2 THEN s:=p1 ELSE s:=p2

end;

Чтобы передать формальным параметрам p1 и p2 конкретные значения, надо при вызове процедуры указать имя процедуры, и затем в круглых скобках задать список фактических параметров; фактическим параметром может быть любое выражение того же типа, что и формальный параметр, в частности- константа или переменная, арифметическое выражение или просто число.

Program Max;

Var  x,y,u,v:Real;

s:Real;

Procedure Proced(p1,p2:Real);

begin

IF p1>p2 THEN s:=p1 ELSE s:=p2

end;

begin

Write('x= '); Readln(x);

Write('y= '); Readln(y);

Proced(x+y,x*y); u:=s;

Proced(0.5,u); v:=s;

Writeln('U= ', u:5:1, 'V= ',v:5:1);

Readln

End.

Выполнение процедуры Proced(x+y,x*y) равносильно выполнению такого блока:

Var p1,p2:Real;

begin

p1:=x+y; p2:=x*y;

IF p1>p2 THEN s:=p1 ELSE s:=p2

end;

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

4.3.5. Формальные параметры-значения и формальные параметры-переменные

Различают два вида формальных параметров: параметры-значения и параметры-переменные. Рассмотренные нами формальные параметры являютсяПАРАМЕТРАМИ-ЗНАЧЕНИЯМИ.

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

Использование параметров-значений позволяет повысить автономность работы процедуры, дает возможность избежать жесткой связи процедуры с переменными из основной программы при вводе исходных данных в процедуру. Вместе с тем, в нашем примере процедура "Proced" остается жестко связанной с основной программой при выводе результатов расчета из процедуры. В используемом нами примере результат вычислений присваивается одной и той же переменной "s", хотя его надо присвоить в одном случае- переменной "u", в другом случае- переменной "v". В итоге, после выполнения процедуры в программе приходится записывать дополнительный оператор присваивания: u:=s или v:=s .

Этот недостаток можно устранить, если в процедуре не фиксировать переменную "s", которой присваивается полученный процедурой результат, а сделать ее формальным параметром процедуры. Такой формальный параметр, способный передавать свое значение любой внешней переменной, называютПАРАМЕТРОМ-ПЕРЕМЕННОЙ.

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

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

Запишем наш пример с использованием параметра-переменной:

Program Max;

Var x,y,u,v:Real;

Procedure Proced(p1,p2:Real; Var Rez:Real);

begin

IF p1>p2 THEN Rez:=p1 ELSE Rez:=p2

end;

Begin

Write('x= '); Readln(x);

Write('y= '); Readln(y);

Proced(x+y,x*y,u);

Proced(0.5,u,v);

Writeln('U= ', u:5:1, 'V= ',v:5:1);

Readln

End.

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

При передаче результата вычислений переменной "u", работа процедуры равносильна выполнению следующего блока:

Var p1,p2,Rez:Real;

Begin

p1:=x+y; p2:=x*y;

IF p1>p2 THEN Rez:=p1 ELSE Rez:=p2;

u:=Rez

End;

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

Pr(Var a,b,c,d:Real);

часть параметров-переменных может принимать исходные данные, а часть- выдавать в основную программу результаты.

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

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

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

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

Program Param;

Var a,b:integer;

Procedure Proc(c:integer; var d:integer);

begin

c:=c+c; d:=d+d; Writeln(c:3,d:3)

end;

Begin

a:=1; b:=2;

Writeln(a:3,b:3);

Proc(a,b);

Writeln(a:3,b:3);

Readln

End.

При выполнении этой программы на экран будут выведены такие данные:

1

2

2

4

1

4

Удвоение формального параметра-значения "с" в процедуре не повлекло изменения значения соответствующего ему фактического параметра (переменной "а" из основной программы). Изменение второго формального параметра, описанного как параметр-переменная "d", передалось в основную программу, потому что одновременно изменился фактический параметр (переменная "b").

4.3.6. Использование массивов в качестве параметров процедур

Как известно, массив можно рассматривать не только как группу упорядоченных переменных, объединенных одним именем, но и как одну переменную, называемую полной переменной. Если имеются две полные переменные “A” и “B”, одинаковые по размерам и типу хранимых ими значений, то значение “A” может быть присвоено переменной “B” с помощью одного оператора присваивания B:=A; т.е. не обязательно передавать значения из одного массива в другой поэлементно. Таким образом, массивам внутри процедуры можно передавать значения извне с помощью формальных и фактических параметров, оформленных в виде полных переменных. При использовании массивов в качестве параметров процедур существует ряд ограничений. Во-первых, нельзя обрабатывать одной и той же процедурой массивы разных типов и размеров. Во-вторых, в заголовке процедур для указания типов формальных параметров- полных переменных запрещается использовать безымянные типы, например A:Array[1..20] of Real. Правильно будет предварительно описывать имя типа массива в разделе описаний программы:

Type

Mas1=Array[1..20] of Real;

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

Procedure Proced(Var A:Mas1);

begin

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

end;

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

Требуется найти U=Max{Xi}, V=Max{Yi}, где i= 1,2,3,...,N.

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

Program Primer;

Const N=20;

Type Mas=Array[1..N] of Real;

Var i:integer;

u,v:Real;

x,y:Mas;

Procedure Max(a:Mas; Var s:Real);

begin

s:=A[1];

FOR i:=1 TO N DO IF A[i]>s THEN s:=A[i]

end;

Begin

FOR i:=1 TO N DO

begin

Write('X[',i,']= '); Readln(x[i]);

Write('Y[',i,']= '); Readln(y[i]);

end;

Max(x,u); Max(y,v);

Writeln('U= ',U:5:1,'V= ',V:5:1);

Readln

End.

Поскольку в данной программе фактическим параметром является переменная (массив в виде полной переменной), то в качестве формального параметра, принимающего исходные данные, может быть использован не только параметр-значение, но и параметр-переменная: Procedure Max(Var A:Max; Var S:Real).

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

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

4.3.7. Принцип локализации

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

Указанные трудности в Паскале устраняются благодаря ПРИНЦИПУ ЛОКАЛИЗАЦИИ, суть которого состоит в том, что вводимые (описываемые) в какой-либо процедуре программные объекты (метки, константы, переменные, процедуры и функции, используемые для внутри-процедурных потребностей) существуют только в пределах данной процедуры.

Имена, используемые для описания переменных, констант и других программных объектов внутри подпрограммы, называются ЛОКАЛЬНЫМИ для данной подпрограммы. Программные объекты, описанные в основной программе, называются ГЛОБАЛЬНЫМИ.

Использование ЛОКАЛЬНЫХ ПОДПРОГРАММ означает использование вложенных модулей (подпрограмма вызывает вставленную в нее другую подпрограмму). При создании программ, имеющих вложенные модули, следует придерживаться следующих правил:

желательно описывать программные объекты в том модуле (подпрограмме), где они используются;

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

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

Пример: задан выпуклый четырехугольник ABCD с диагональю AC. Найти его площадь.

Четырехугольник можно рассматривать как два треугольника со сторонами a,b,c. Дважды вычислив площадь треугольника (S) и сложив полученные значения, мы найдем искомый результат.

Как видно из формул, решение задачи предполагает двукратное использование процедуры вычисления площади треугольника, оперирующей величиной "p", имеющей вспомогательный характер. Составим программу, решающую эту задачу:

Program Primer;

Var a,b,c,d,e,s1,s2:Real;

Procedure STR(a,b,c:Real; Var s:Real);

Var p:Real;

begin

p:=(a+b+c)/2;     s:=SQRT(p*(p-a)*(p-b)*(p-c))

end;

Begin

Write('A= '); readln(A);

{вводим длины сторон и диагональ}

Write('B= '); readln(B);

{четырехугольника}

Write('C= '); readln(C);

Write('D= '); readln(D);

Write('E= '); readln(E);

STR(A,B,E,S1);

STR(D,E,C,S2);

Writeln('Площадь фигуры= ',S1+S2:5:1);

Readln

End.

ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ в теле процедуры имеют тот же смысл, что и до входа в процедуру, и их значение может быть изменено процедурой. Таким образом, с помощью глобальных переменных можно осуществлять непосредственную связь процедуры с внешним блоком, минуя связь через параметры.

ЛОКАЛЬНЫЕ ПЕРЕМЕННЫЕ описываются в теле процедуры, их используют в вычислениях внутри процедуры, но не для передачи значений вовне. Переменная, локализованная в теле процедуры, при выходе из процедуры прекращает существование, а при каждом очередном вхождении в процедуру возникает заново.

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

4.3.8. Рекурсия

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

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

  1. Вычисление факториала

Program Factorial;

Var F,N:integer;

Procedure FACT(N:integer; Var F:integer);

begin

IF N=0 THEN F:=1

ELSE

begin

FACT(N-1,F); F:=N*F

end

end;

Begin

Write('Введите число= '); Readln(N);

FACT(N,F);

Writeln(F);

Readln

End.

В представленном выше примере рекурсивная процедура FACT вызывает сама себя до тех пор, пока не будет выполнено условие N=0. При каждом новом вызове процедуры FACT создается новое множество локальных переменных (формальных параметров-переменных “F”). Таким образом, рекурсивный вызов не изменяет переменные, расположенные вне вызываемой процедуры.

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

  1. Распечатать в обратном порядке цифры положительного целого числа "N".

Procedure BackDigit (N:integer);

begin

Write(N mod 10);

IF (N div 10)<>0 THEN BackDigit(N div 10);

end;

mod - выделение остатка от частного;

div - выделение целой части частного.

Рекурсивный вызов может быть КОСВЕННЫМ:

Procedure A(x:integer);

begin

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

B(x);

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

end;

Procedure B(y:integer);

begin

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

A(y);

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

end;

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

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

Procedure B(y:integer); FORWARD;

{описание раздела операторов процедуры "В"}

{откладывается на дальнейшее}

Procedure A(x:integer);

begin

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

B(x);

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

end;

Procedure B;          {формальные параметры описаны ранее}

begin

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

A(y);

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

end;

Теперь в процедуре "А" допустимо обращение к процедуре "В", ведь последняя уже описана, точнее известны ее формальные параметры и компилятор может правильно организовать ее вызов. Заголовок "Procedure B" перед текстом процедуры "В" содержит только имя процедуры, т.к. список формальных параметров был указан выше.

4.3.9. Функции

В Паскале существует 2 типа подпрограмм: процедуры и функции. Основные вопросы организации работы с процедурами мы рассмотрели. Перейдем к изучению функций.

Нам известно понятие функции из математики- с помощью функций задаются зависимости одних значений (значения функции) от других значений (аргументы функции). Функциональные зависимости задаются таблично, графически, аналитически. В Паскале функции задаются алгоритмом определения их значений. В Паскале допустимы только такие функции, значения которых относятся к простым типам (Real, integer, Char, String). Значением функции не может быть сложный тип данных, например массив.

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

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

FUNCTION Имя функции(р1:тип1;р2:тип2;...;рN:типN):тип функции;

begin

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

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

end;

где р1,р2,...,рN- формальные параметры;

тип1, тип2, ..., типN- типы параметров.

Формальными параметрами функции могут быть параметры-значения и параметры-переменные.

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

описание начинается служебным словом FUNCTION;

в заголовке указывается тип значения описываемой функции;

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

Пример вычисления факториала с помощью функции:

Program Primer;

Var N:integer;

Function FACT(n:integer):integer;

Var i,k:integer;

begin

k:=1;

FOR i:=1 TO n DO k:=k*i;

Fact:=k

end;

Begin

Write('N= '); Readln(n);

Writeln('Факториал числа N =',FACT(n):5);

Readln

End.

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

Например, вычислим p=a5+(a-k)-k:

Program Prim2;

Var a,p:Real;

k:integer;

Function Stepen(x:Real; n:integer):Real;

begin

Stepen:=EXP(n*LN(x))

end;

Begin

Write('A= '); Readln(a);

Write('K= '); Readln(k);

p:=Stepen(a,5)+Stepen((a-k),-k);

Writeln('p= ',p:5:1);

Readln

End.

При написании алгоритма функции нельзя использовать имя функции как имя переменной в правой части оператора присваивания:

Function FACT(n:integer):integer;

Var i:integer;

begin

FACT:=1;

FOR i:=1 TO n DO FACT:=FACT*i

end;

Такое описание функции является неверным, т.к. в этой записи "FACT" может быть либо переменной, либо вызовом функции без параметров. Однако в нашем примере "FACT" описана как функция с параметрами, поэтому при компиляции такой программы будет дано сообщение об ошибке.

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

Если результаты работы подпрограммы чаще используются в качестве ПРОМЕЖУТОЧНЫХ значений вычислений, то лучше использовать функцию.

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

Пример: вычислить p=k!+2+(3k)!-5!

здесь k!, (3k)!, 5! являются промежуточными значениями, используемыми для вычисления "р". В этом случае для определения факториала числа удобнее применить функцию:

Program Prim3;

Var p,k:integer;

Function FACT(n:integer):integer;

Var i,k:integer;

begin

k:=1;

FOR i:=1 TO n DO k:=k*i; FACT:=k

end;

Begin

Write('k= '); Readln(k);

p:=FACT(k)+2+FACT(3*k)-FACT(5);

Writeln('p= ',p:5);

Readln

End.

Решим эту же задачу с использованием процедуры:

Program Prim4;

Var p,k,m1,m2,m3:integer;

Procedure FACT(n:integer; Var b:integer);

Var i,k:integer;

begin

k:=1;

FOR i:=1 TO n DO k:=k*i;

b:=k

end;

Begin

Write('K= '); Readln(k);

FACT(k,m1); FACT(3*k,m2); FACT(5,m3);

p:=m1+2+m2-m3;

Writeln(p:5);

Readln

End.

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

4.3.10. Побочные эффекты функций

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

Допустим, в основной программе описаны глобальные переменные

Var a,b:Real;

а в разделе функций описана функция, выражающая зависимость F(x)=2x2+0.5 :

Function F(x:Real):Real;

begin

F:=2*x*x+0.5;

A:=0

end;

Пусть в тексте основной программы встречается такой фрагмент:

A:=3.14; B:=F(3); Writeln(A,B).

Каков будет результат? Казалось бы- 3.14 и 18.5, но благодаря побочному эффекту, компьютер распечатает числа 0 и 18.5 : функция F( ) изменила значение глобальной переменной “А” с 3.14 на 0.

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

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

5. СИСТЕМА МЕНЮ ТУРБО-ПАСКАЛЯ

5.1. Действия в среде меню

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

Основное (главное) меню Турбо-Паскаля занимает верхнюю строку экрана дисплея и состоит из 7 пунктов:

File   Edit   Run    Compile   Options   Debug   Break/Watch

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

  1. Переход в главное меню из окна редактирования и возврат обратно осуществляется с помощью клавиш F10 и ESC.

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

  3. Чтобы выбрать нужный пункт, надо установить на него светлый прямоугольник и нажать клавишу "ENTER". Чтобы отказаться от выбранного пункта и вернуться в текстовый редактор, надо нажать "ESC".

  4. При выборе некоторых пунктов появляется дополнительное окно, в котором указывается принятое по умолчанию или установленное ранее значение определенного параметра. Если нужно ввести новый параметр, следует начать ввод символов, и старое значение исчезнет, сменившись вводимыми символами. Если существующий параметр надо отредактировать, то следует подвести курсор к нужному месту в строке и ввести новые символы в режиме вставки или замены (режимы вставка/замена переключаются клавишей "INS"). При редактировании текста параметра также доступны клавиши "Backspace" и "DEL". Первая стирает символ слева от курсора, вторая- символ, на который указывает курсор. Чтобы компьютер запомнил отредактированный вариант параметра, надо нажать "ENTER". Чтобы отказаться от редактируемого варианта параметра и оставить предыдущее значение без изменений, надо нажать "ESC".

  5. Из любого режима работы в Турбо-Паскале можно перейти к нужному пункту главного меню (что сопровождается появлением "спускающегося меню", закрепленного за этим пунктом), нажав одновременно клавиши "ALT" и клавишу с буквой, начальной в названии пункта:

Alt/F  -   File, Alt/E  -  Edit, Alt/R  -  Run   и т.д.

  1. Можно перейти из режима редактирования текста программы к некоторым наиболее употребляемым операциям, минуя главное меню. Для этого используются функциональные клавиши, а также их сочетания с клавишами SHIFT, ALT, CTRL. Некоторые из этих сочетаний клавиш мы рассмотрели, знакомясь с основными принципами работы в среде Турбо-Паскаля.

  2. Работая со "спускающимся меню", можно перейти к любой его опции простым нажатием “горячей клавиши” с начальной буквой названия опции.

Рассмотрим коротко назначение 7-ми пунктов главного меню.

FILE

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

EDIT

Переход из меню в режим создания или редактирования программы.

RUN

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

COMPILE

Компиляция программы.

OPTIONS

Управление режимами компиляции и компоновки программы, настройка режимов работы среды Турбо-Паскаля.

DEBUG

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

BREAK/WATCH

Управление информацией в окне отладки.

5.2. Опции пункта меню FILE

После обращения к пункту FILE главного меню разворачивается следующее дополнительное меню:

FILE

Load              F3

Pick        Alt-F3

New

Save              F2

Write to

Directory

Change dir

OS shell

Quit         Alt-X

Опция Load (Загрузить)

Загружает текст программы из дискового файла в память редактора Турбо-Паскаля. Этот режим работы можно также вызвать, находясь в окне редактора, минуя главное меню, нажав клавишу "F3". При вызове опции "Load" на экране появится небольшое окно с надписью "Load file name" (имя загружаемого файла) и именем файла, который последний раз загружался с помощью этой опции. При первом обращении к этой опции имя предыдущего файла в окне отсутствует и его заменяет ключ выбора группы файлов "*.PAS". Можно полностью указать имя вновь загружаемого файла, а можно отредактировать то имя, которое указано в окне. Если загружаемый файл имеет стандартное расширение "*.PAS", то расширение в имени файла можно не указывать.

Если пользователем указано имя, состоящее из одних пробелов или принят ключ выбора группы файлов "*.PAS", то на экране появится еще одно окно, в котором в алфавитном порядке будут перечислены все файлы с расширением "*.PAS" из текущего каталога. В конце списка указываются подкаталоги, зарегистрированные в текущем каталоге, а также ссылка на каталог верхнего уровня, если текущий каталог не корневой. Чтобы просмотреть другой каталог, надо перевести на его имя светлый прямоугольник (указатель), пользуясь клавишами управления курсором, и нажать клавишу "ENTER". Такой переход не вызывает смену текущего каталога, но дает доступ к файлам указанного каталога. Чтобы загрузить в окно редактирования нужный файл, можно поступить одним из следующих способов:

  1. Переместить курсор на имя нужного файла в списке и нажать "ENTER".

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

Если перед загрузкой нового файла в окне редактора уже находился текст, который не был предварительно сохранен на диске, то на экране появится запрос: "Файл не сохранен. Сохранить (Да/Нет?)". Если после этого нажать "Y", то файл будет записан на диск. Если нажать "N", то файл в памяти будет уничтожен и на его место загрузится с диска новый файл.

Нажатие клавиши "ESC" приведет к отказу от выбранной опции и вернет управление в подменю пункта "FILE".

Опция Pick

Позволяет выбрать файл в списке из 8-ми файлов, которые последними загружались в окно редактирования. Информация об этих файлах хранится в специальном файле-списке "turbo.pck". При выборе опции PICK на экране появляется окно, в котором в столбец выведены имена файлов. Вверху находится имя файла, находящегося в текущий момент в редакторе. Далее указываются другие файлы в порядке, обратном тому, как они загружались ранее в память редактора. Внизу списка стоит надпись "-load file-". Указателем (светлым прямоугольником) можно выбрать любой из файлов и нажать "ENTER", после чего файл загрузится в окно редактора, а курсор поместится в то место программы, где последний раз вносились изменения при редактировании этого файла. При выборе пункта "-load file-" (загрузить файл), режим работы системы Турбо-Паскаля будет полностью совпадать с режимом опции "LOAD". Альтернативным вариантом вызова опции "PICK" является одновременное нажатие клавиш "Alt-F3".

Опция New (Новый)

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

Опция Save (Сохранить)

Записывает файл из памяти текстового редактора на диск. Файл записывается под своим именем, однако если это имя- "NONAME.PAS", поступит запрос о необходимости переименования файла. Опцию "SAVE" можно также вызывать из окна редактирования нажатием клавиши "F2".

Опция Write to (Записать)

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

Опция Directory (Каталог)

Служит для выбора файла в текущем каталоге и его загрузки в память текстового редактора. После обращения к этой опции на экране появится дополнительное окно с фразой "ENTER FILE NAME" (введите имя файла) и ключом выбора группы файлов "*.*". Далее можно установить нужный вид ключа либо ввести имя конкретного файла. В последующем действия совпадают с режимом работы опции "LOAD".

Опция Change Dir (Сменить каталог)

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

Опция OS Shell (Временный выход в DOS)

Позволяет временно выйти в DOS, не прекращая работы с Турбо-Паскалем. Этот режим работы дает доступ ко всем стандартным средствам DOS, например можно отформатировать дискету, распечатать файл на принтере и даже запустить какую-нибудь программу (с учетом того, что временно покинутый Турбо-Паскаль остается в оперативной памяти и занимает в ней около 230 Кбайт). Для возврата в Турбо-Паскаль надо ввести команду "EXIT", и на экране компьютера восстановится то же изображение, которое было перед вызовом опции "OS SHELL".

Опция Quit (Выход).

Этот подпункт меню полностью завершает работу с Турбо-Паскалем, Паскаль выгружается из оперативной памяти. Управление компьютером передается операционной системе. Опцию "QUIT" можно также вызвать из окна редактирования нажатием клавиш ALT-X.

5.3. Пункт меню RUN

После выбора в главном меню пункта "RUN" разворачивается спускающееся меню:

RUN

Run                       Ctrl-F9

Program reset      Ctrl-F2

Go to cursor                 F4

Trace into                     F7

Step over                      F8

User screen            Alt-F5

Опция Run (запуск программы)

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

При выполнении программы экран Турбо-Паскаля находится в режиме "USER SCREEN" (окно пользователя). После окончания работы программы "окно пользователя" исчезает, и выводившиеся на экран результаты вычислений моментально закрываются окном текстового редактора. Чтобы детально ознакомиться с результатами работы программы, выведенными на экран "окна пользователя", надо выбрать в меню опцию "USER SCREEN" либо нажать клавиши "Alt-F5".

Опцию "RUN" можно вызвать из режима редактирования с помощью клавиш "CTRL-F9".

Опция Program Reset (восстановление состояния программы)

Эта опция прекращает отладку программы, удаляет программу из памяти и закрывает все открытые файлы. Опцию можно также вызвать из окна текстового редактора нажатием клавиш "CTRL-F2".

Опция Go To Cursor (выполнить до курсора)

После выбора этой опции программа работает как обычно, но останавливается перед выполнением первого оператора из строки, на которую указывает курсор. После этого на экране появляется окно редактора, а строка с курсором выделяется светлым прямоугольником. Курсор можно перевести на другую строку и вновь выбрать опцию GO TO CURSOR. После этого программа будет выполнена от начала до нового места остановки. Опцию GO TO CURSOR можно также вызвать из режима редактирования нажатием клавиши F4. Отказаться от режима выполнения программы до курсора можно с помощью опции PROGRAM RESET.

Опция Trace Into (трассировка с заходом)

После выбора этой опции Турбо-Паскаль переходит в режим трассировки - программа выполняется построчно, с остановками после каждой строки в ожидании повторного выбора опции Trace Into или нажатия клавиши F7. Если выполняемая строка содержит обращение к процедуре или функции, то управление будет передано внутрь процедуры или функции и программа остановится перед выполнением первой строки подпрограммы. Чтобы отказаться от режима трассировки, надо обратиться к опции PROGRAM RESET, либо нажать клавиши CTRL-F2.

Опция Step Over (трассировка с перешагиванием)

Этот режим работы схож с TRACE INTO, но при вызове процедуры или функции эти подпрограммы выполняются за один шаг и компьютер останавливается на операторе, следующим за оператором вызова подпрограммы. Говоря иначе, в режиме STEP OVER при выполнении подпрограмм режим трассировки временно отключается. STEP OVER можно вызвать из окна текстового редактора нажатием клавиши F8.

Опция User Screen (окно пользователя)

Эта опция позволяет увидеть, каким было состояние экрана дисплея после завершения прогона программы. Режим просмотра окна пользователя можно также вызвать из окна текстового редактора клавишами ALT-F5. Повторное нажатие этих клавиш возвращает экран компьютера в исходное состояние.

5.4. Пункт меню COMPILE

Выбор пункта меню COMPILE сопровождается появлением дополнительного меню:

COMPILE

Compile                 Alt-F9

Make                           F9

Build

Destination        Memory

Find Error

Primary file:

Get info

Опция Compile (компиляция)

В этом режиме Турбо-Паскаль компилирует программу, текст которой находится в окне редактирования. Если компиляция прошла успешно, появится надпись "PRESS ANY KEY" (нажмите любую клавишу). В случае обнаружения в тексте программы ошибки, Турбо-Паскаль автоматически переходит в режим редактирования, курсор устанавливается на строке программы, содержащей ошибку, на экране появляется сообщение о существе ошибки.

Опция Make (создание)

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

Опция Build (построение)

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

Ключ Destination (назначение)

С помощью этой опции можно указать системе, куда поместить "EXE" - файл (результат компиляции программы, текст которой находится в окне редактора). Откомпилированная программа может быть записана на диск, а может остаться в оперативной памяти в зависимости от того, в каком состоянии находится ключ DESTINATION - DISK или MEMORY. Переключение из одного состояния в другое осуществляется нажатием клавиши ENTER.

Опция Find Error (поиск ошибки)

Позволяет отыскивать ошибки при выполнении программы. Если опции DEBUG INFORMATION и INTEGRATED DEBUGGING находятся в состоянии ON, то при возникновении ошибки в запущенной из Турбо-Паскаля программе, ошибка обнаруживается и указывается автоматически: курсор будет установлен на строку, содержащую ошибочный оператор, а в служебной строке (второй сверху строке экрана) появится информация о причине ошибки. Если же перечисленные две опции находятся в состоянии OFF или программа запущена не из Турбо-Паскаля, то ошибка не будет обнаружена.

Опция Primary File (основной файл)

Эта опция используется при работе с программами, включающими в себя несколько модулей или вспомогательных (включаемых) файлов. С помощью опции PRIMARY FILE Турбо-Паскалю указывается имя основного (начального) файла программы. Если это имя задано, то независимо от того, какая часть программы загружена в данный момент в память текстового редактора, компиляция программы в режиме MAKE и BUILD будет начинаться с основной части и компилятор сможет правильно построить программу.

Опция Get Info (получение информации)

При обращении к этой опции на экране появляется окно с информацией о текущем файле с расширением "*.PAS". Данная информация включает:

  1. Текущий каталог;

  2. Имя текущего файла;

  3. Размер файла (максимальный размер- 64615 байт);

  4. Размер дополнительной памяти;

  5. Количество откомпилированых строк;

  6. Доступен ли код программы;

и т.д.

5.5. Пункт меню OPTIONS

Опции пункта меню OPTIONS позволяют настраивать среду Турбо-Паскаля удобным для пользователя образом. В пункт меню OPTIONS входят следующие подпункты:

OPTIONS

Compiler

Linker

Environment

Directories

Parameters

Save options

Retrieve options

Опция Compiler (компилятор)

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

Опция Linker (компоновщик)

Позволяет управлять работой компоновщика, который обеспечивает формирование связей между модулями программы. У этой опции есть свое дополнительное меню с двумя опциями: MAP FILE и LINK BUFFER.

MAP FILE: задает (ON) или отменяет (OFF) режим формирования табличного файла Турбо-Паскаля. Этот файл имеет расширение "*.MAP", в данный файл компоновщик помещает карту распределения памяти компонуемой программы.

LINK BUFFER: позволяет указать компилятору Турбо-Паскаля, где следует размещать таблицы связей между модулями и где временно хранить компонуемую программу- в оперативной памяти (значение опции будет MEMORY) или на магнитном диске (опция находится в режиме DISK). Используя оперативную память, компоновщик будет работать значительно быстрее, однако при разработке больших программ ему может не хватить памяти и он не соберет программу. Использование диска высвобождает оперативную память, но замедляет процесс компоновки.

Опция Environment (состояние среды)

Позволяет настроить среду Турбо-Паскаля для удобства работы конкретного пользователя. У этой опции есть свое дополнительное меню:

ENVIRONMENT

Config Auto save       On

Edit Auto save            On

Backup files              Off

Tab size                         8

Zoom windows           Off

Screen size

Подпункт Config Auto Save

Позволяет задать режим автоматического сохранения текущей настройки среды Турбо-Паскаля в файле конфигурации "TURBO.TP". Если CONFIG AUTO SAVE стоит в режиме ON, то настройка среды будет сохранена автоматически при выходе из Турбо-Паскаля (выход в DOS через опции OS SHELL или QUIT).

Подпункт Edit Auto Save

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

Подпункт Backup Files

Если эта опция находится в режиме ON, то при записи редактируемой программы на диск, файл с предыдущей версией текста программы не стирается, а сохраняется под своим именем с расширением *.BAK .

Подпункт Tab Size

Этой опцией устанавливается длина шага табуляции (перемещения курсора вправо при нажатии клавиши "Tab"). Шаг табуляции может быть в пределах от 2 до 16 знакомест, по умолчанию принимается шаг 8. Если режим табуляции отключен нажатием клавиш CTRL-O-T, то при нажатии клавиши "Tab" курсор будет перемещаться в текущей строке так, чтобы остановиться под началом очередного слова в предыдущей строке. Если при этом включен режим вставки (клавиша "Insert"), то часть текущей строки справа от курсора будет сдвинута вправо, в противном случае курсор переместится без изменения строки.

Подпункт Zoom Windows

Раздвигает текущее окно (Edit или Watch) до максимально возможных размеров.

Подпункт Screen Size

Задает количество строк в экране. По умолчанию задается размер экрана в 25 строк. Если компьютер оснащен дисплеем EGA или VGA, можно при желании установить размер экрана соответственно в 43 или 50 строк.

Подпункт Directories (каталоги)

Выбор этой опции сопровождается появлением очередного дополнительного меню:

DIRECTORIES

Turbo directory:

EXE & TPU directory:

Include directories:

Unit directories:

Object directories:

Pick file name:    Turbo.pck

Current pick file:

Подпункт Turbo Directory:

Указывает каталог, в котором Турбо-Паскаль будет искать файл с настройкой конфигурации среды (файл "Turbo.tp") и справочный файл Turbo.hlp, если при загрузке Турбо-Паскаля они не были найдены в текущем каталоге. Обычно здесь указывается каталог, содержащий саму систему Турбо-Паскаль.

Подпункт EXE & TPU directory:

Указывает каталог, в котором будут записываться откомпилированые программы в виде "EXE- файлов" и откомпилированые модули в виде файлов с расширением "*.TPU". Если отдельный каталог не указан, то эти файлы будут записаны в текущий каталог. Не желательно, чтобы файлы "*.EXE" и "*.TPU" смешивались с файлами системы Турбо-Паскаль.

Подпункт Include directories:

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

Подпункт Unit directories:

Указывает каталог, в котором хранятся файлы модулей, в том числе стандартных модулей Турбо-Паскаля (CRT, PRINTER, GRAPH, DOS, WIN и т.д.), если их нет в текущем каталоге.

Подпункт Object directories:

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

Подпункт Pick file name:

Как известно, Турбо-Паскаль автоматически дает файлу-списку имя "Turbo.pck" (см. опцию FILE). Опция "PICK FILE NAME" позволяет присваивать файлу-списку любое произвольное имя, которое будет запомнено в файле TURBO.TP, хранящем конфигурацию (настройку) системы Турбо-Паскаль. Такой подход позволяет нескольким пользователям, работающим на одном компьютере, иметь свои личные файлы-списки.

Подпункт Current Pick file:

Эта опция сохраняет информацию о текущем файле-списке (он может иметь имя отличное от стандартного "Turbo.pck").

Опция Parameters

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

Опция Save Options

Позволяет сохранить всю настройку среды Турбо-Паскаля (параметры опций COMPILER, ENVIRONMENT и DIRECTORIES) в стандартном файле конфигурации TURBO.TP либо другом, нестандартном файле с расширением "*.TP", если такой был создан.

Опция Retrieve Options

Выбор этого подпункта меню включает режим создания нового файла конфигурации, отличного от стандартного TURBO.TP . Наличие разных файлов конфигурации позволяет нескольким пользователям мирно уживаться на одном компьютере, храня любимые настройки среды Turbo-Pascal в индивидуальном *.TP - файле. Имя такому файлу дается с помощью режима Retrieve options.

5.6. Пункт меню DEBUG

DEBUG

Evaluate                    Ctrl-F4

Call Stack                 Ctrl-F3

Find Procedure

Integrated Debugging     On

Stand-alone debugging   Off

Display swapping       Smart

Refresh display

Опция Evaluate

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

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

Для перемещения между полями Evaluate, Result и New Value используются клавиши "стрелка вверх" и "стрелка вниз". "Окно вычисления" Evaluate служит для ввода имени переменной или выражения, значения которых требуется узнать. Чтобы поместить имя переменной в окно вычисления, можно воспользоваться одним из 2-х способов:

  1. Имя набирается обычным способом на клавиатуре;

  2. В режиме редактирования текста программы курсор устанавливается на имя требуемой переменной или выражение, после чего выбирается опция Evaluate с помощью меню или нажатием CTRL-F4. Символ, под которым стоял курсор в тексте программы, высветится в окне вычисления. Если в имени переменной больше одного символа, остаток имени можно ввести, последовательно нажимая клавишу управления курсором "Вправо".

После нажатия клавиши ввода "Enter", в окне RESULT появится число, равное значению переменной из окна EVALUATE. Если рассматривается полная переменная (массив), в окне RESULT появится последовательность чисел, являющихся значениями элементов массива.

Поле New Value (новое значение) позволяет пользователю произвольно изменять значения переменных, названных в поле "вычисление" (Evaluate).

Окно вычислений Evaluate можно использовать также в качестве калькулятора, вводя в него выражения, например (346.74·98.1)/44.28. После нажатия клавиши ENTER, в окне RESULT появится искомый результат вычислений.

Опция Call Stack

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

Опция Find Procedure

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

Опция Integrated Debugging

Когда эта опция находится в состоянии "ON" (включено), то разрешена отладка программ в среде Турбо-Паскаля. При этом можно назначать точки останова, выполнять программу по шагам и работать с командами отладки в меню "RUN". Если установлено значение "OFF", то выполнение программы по шагам или назначение точек останова поддерживаться не будут.

Опция Stand-Alone Debugging

Если эта опция находится в состоянии "ON" и в опции COMPILE/DESTINATION установлено значение "DISK", то в файл с расширением "*.EXE" (выполняемый файл, результат компиляции текста программы) добавляется информация для отладки, которая может использоваться автономным турбо-отладчиком, вне среды Турбо-Паскаля.

Опция Display Swapping

При работе в среде Турбо-Паскаль, на экран обычно выводится главное меню и два окна- окно редактирования Edit и окно просмотра Watch. Одно из этих окон является активным и занимает большую часть экрана, второе окно при этом свернуто в одну строку, расположенную в самом низу экрана. Переключение между этими окнами осуществляется нажатием клавиши F6. Кроме перечисленных двух окон, в Турбо-Паскале также имеется окно "USER SCREEN", которое появляется на экране при выполнении программы и в которое выводятся результаты работы программы. После завершения работы программы окно USER SCREN исчезает, уступая место окну редактирования или просмотра.

С помощью опции DISPLAY SWAPPING можно управлять переключением перечисленных окон. Опции DISPLAY SWAPPING может быть присвоено одно из 3-х значений- SMART (эффективное), ALWAYS (пошаговое) и NEVER (без переключения).

  1. Значение SMART. В этом режиме отладчик просматривает выполняемый код программы (откомпилированный вариант программы) и анализирует, влияет ли он на экран (выводит ли программа на экран какую-либо информацию). Во время вывода информации, экран автоматически переключается в режим USER SCREEN, а затем возвращается в исходное положение.

  2. ALWAYS. Переход к экрану USER SCREEN осуществляется на каждом шаге трассирования программы (трассирование- пошаговое выполнение программы, когда Турбо-Паскаль выполняет очередную строку программы и делает паузу, ожидая нажатия клавиши F7 или F8).

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

Опция Refresh Display

Если выводимая программой информация наложилась на текст программы (опция DISPLAY SWAPPING имела значение NEVER), текст можно обновить опцией REFRESH DISPLAY.

5.7. Пункт меню BREAK/WATCH

Выбор этого пункта главного меню вызывает появление на экране дополнительного вертикального подменю со следующими пунктами:

Break/Watch

Add watch                Ctrl-F7

Delete watch

Edit watch

Remove all watches

Toggle breakpoints Ctrl-F8

Clear all breakpoints

View next breakpoint

Если опция INTEGRATED DEBUGGING из пункта меню DEBUG установлена в значение "ON" (т.е. встроенный отладчик системы включен), то использование команд из пункта меню BREAK/WATCH позволяет добавлять и удалять записи из окна просмотра WATCH, редактировать их, а также устанавливать и отменять точки останова, переключать их.

Опция Add Watch

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

Опция Delete Watch

Эта опция удаляет из окна WATCH текущее просматриваемое выражение (режим удаления доступен в том случае, если окно просмотра WATCH является видимым). Удалить текущее выражение просмотра можно также с помощью клавиш DEL или CTRL-Y.

Опция Edit Watch

Данная опция выводит текущее выражение просмотра (текущую переменную из окна WATCH) в дополнительном окне с заголовком "input" (ввод), где оно может быть изменено. При нажатии клавиши ENTER исходное выражение будет заменено измененным. При нажатии клавиши ESC изменения будут отменены.

Опция Remove All Watches

Удаляет все выражения из окна просмотра.

Опция Toggle Breakpoints

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

Опция Clear All Breakpoints

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

Опция View Next Breakpoint

Опция перемещает в окне редактирования (EDIT) курсор к следующей точке останова, при этом никакие операторы не выполняются. Если точка останова была последней, то активизируется первая точка останова.

6. ОТЛАДКА ПРОГРАММ В СРЕДЕ ТУРБО-ПАСКАЛЬ

6.1. Стиль программирования, облегчающий отладку

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

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

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

  2. Желательно разбивать текст программы на процедуры и функции. Не следует писать большие процедуры (содержащие более 20-30 строк). Если процедура получается большой, лучше разбить ее на несколько подпрограмм меньших размеров.

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

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

  5. Текст программы должен быть "рыхлым", не следует писать операторы компактно, вплотную друг к другу. Желательно, чтобы на строке было не более одного оператора. Поскольку отладчик Турбо-Паскаля работает построчно, такой подход облегчит локализацию ошибки. На одной строке в виде списка можно писать лишь те операторы, которые надежны в отношении отладки и в проверке не нуждаются: A:=10; B:=3.14; Str:='Строка символов'; C:=True; .

  6. Выполняемые в программе действия надо как можно чаще сопровождать комментариями { }, (* *). Известные программисты Керниган и Плоджер в своей книге "Элементы стиля программирования" рекомендуют, чтобы комментарием сопровождался каждый оператор программы.

6.2. Основные виды ошибок программирования

В ходе отладки программы приходится сталкиваться с тремя видами ошибок:

  1. Синтаксические ошибки - текст программы не отвечает требованиям языка Паскаль. Такие ошибки выявляются сразу при попытке компиляции и запуска программы.

  2. Ошибки периода выполнения программы (RUNTIME ERROR) - ошибки, возникающие при выполнении программы, когда текст программы формально записан правильно, но при выполнении программы в результате неблагоприятного стечения обстоятельств возникает ошибочная ситуация и компьютер не может продолжить работу (например, в случае деления на ноль).

  3. Ошибки в алгоритме (семантические ошибки) - программа работает без сбоев, но результаты получаются неверные.

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

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

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

  2. Unknown identifier - идентификатор (имя переменной, константы, процедуры и т.п.) не был упомянут в разделе описаний программы.

  3. Duplicate identifier - попытка дважды описать один и тот же идентификатор.

  4. Syntax error - синтаксическая ошибка, например строка символов не была заключена в кавычки.

  5. Line too long - компилятор не может обрабатывать текст программы со строками длиннее 126 символов. Скорее всего, программист забыл поставить апостроф, закрывающий текстовую строку, записываемую в переменную или выводимую на экран.

  6. Type identifier expected - не указан тип идентификатора.

  7. Variable identifier expected - на этом месте в программе должна стоять переменная.

  8. Error in type - объявление типа данных не может начинаться с этого символа.

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

  10. Begin expected - нужен begin.

  11. End expected - нужен end.

  12. Integer expression expected - требуется выражение типа integer.

  13. Boolean expression expected - требуется выражение типа boolean.

  14. Do expected - пропущено слово "Do".

  15. Of expected - пропущено слово "of".

  16. Then expected - пропущено слово "then".

  17. To expected - пропущено слово "to".

  18. String variable expected - требуется строковая переменная.

  19. Error in expression - данный символ не может участвовать в выражении таким образом.

  20. Division by zero - деление на ноль.

  21. Constant and case types do not math - тип меток и тип селектора в операторе CASE не соответствуют друг другу.

  22. Label not within current block - оператор GOTO не может ссылаться на метку, находящуюся вне текущего модуля.

  23. Label already defined - такая метка уже есть.

  24. Floating point overflow operation - величина вещественного числа вышла за пределы диапазона, допускаемого Паскалем (обычно при делении на ноль).

  25. Invalid procedure or function reference - неправильный вызов подпрограммы.

6.3. Средства, которыми располагает отладчик Турбо-Паскаля

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

Трассирование (клавиши F7 или F8)

С помощью трассирования можно выполнить одну строку программы, остановиться и просмотреть результаты расчета. Если в программе есть процедура, то ее можно выполнить сразу за один шаг (F8) или трассировать построчно (F7).

Выполнение до курсора (F4)

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

Вычисление и модификация (CTRL-F4)

Для эпизодической проверки значений переменных, на экран можно выводить окно вычислений EVALUATE. С помощью этого окна можно также изменять текущее значение той или иной переменной. Отменить все задействованные средства отладки (кроме точек останова) можно клавишами CTRL-F2.

Просмотр (CTRL-F7)

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

Прерывание выполнения программы (CTRL-F8)

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

Точкой останова можно сделать любую строку программы. Для этого на нужную строку устанавливается курсор и нажимается CTRL-F8, после чего строка будет выделена красной подсветкой. Программа запускается нажатием CTRL-F9 и выполняется обычным способом. При достижении точки останова программа останавливается, на экране появляется окно редактора "EDIT" с участком текста, где находится точка останова. Если в окно просмотра WATCH были помещены имена переменных, они будут сопровождаться своими текущими значениями. После останова программы можно воспользоваться любыми средствами отладки: можно продолжить программу трассированием или выполнением до курсора (F7,F8,F4). Можно проверять и изменять значения переменных (CTRL-F4), добавлять и удалять выражения из окна просмотра, устанавливать или отменять точки останова, можно просмотреть выводимую программой на экран информацию (ALT-F5). Чтобы начать выполнение программы с начала, надо нажать CTRL-F2, CTRL-F9. Продолжить программу до следующей точки останова - CTRL-F9. Чтобы отменить точку останова, надо поместить на нее курсор и нажать CTRL-F8. Для просмотра всех точек останова в программе, надо несколько раз воспользоваться опцией VIEW NEXT BREAKPOINT из пункта главного меню BREAK/WATCH. При этом точки останова будут циклически, одна за другой, появляться в окне EDIT вместе с близлежащими участками текста.