Г Л А В А 2. ПРОГРАММИРОВАНИЕ НА TURBO PASCAL. Язык Паскаль был разработан Виртом в начале 70-х годов, как язык обучения программированию. Если у Вас есть опыт программирования, то Вам будет не трудно его освоить. В этой главе описываются основные элементы языка и их использование. Если Вы только начинаете программировать на Паскале, то лучше изучить какой-нибудь учебник по Паскалю. Прежде чем читать эту главу, имеет смысл обратиться к главе 7 "Справочник по интегрированной среде разработки" и к главе 8 "Редактор от A до Z", изучить работу различных меню и текстового редактора системы Turbo Pascal. Если Вы еще не инсталлировали Turbo Pascal, как описано во введении, сделайте это сейчас. Элементы программирования. Большинство программ создаются для решения какой-нибудь задачи. Решение задачи достигается обработкой информации или данных. Поэтому, как программисту, Вам необходимо знать, как: - завести информации в программу - ввод; - сохранять информацию - данные; - задать правильные команды обработки данных - операции; - получить данные из программы - вывод. Вы можете написать и упорядочить свои команды так, чтобы: - некоторые из них выполнялись при выполнении некоторого условия или ряда условий - условное выполнение; - другие выполнялись некоторое число раз - циклы; - другие собирались в отдельные части, которые могут быть выполнены в нескольких местах программы - подпрограммы. Итак, перечислены семь основных понятий программирования: ввод, данные, операции, вывод, условное выполнение, циклы и подпрограммы. Этот список неполный, но он содержит основные понятия, присущие всем программам. Многие языки программирования, включая Паскаль, имеют свои особенности. Но когда Вы хотите быстро изучить новый язык, Вы можете посмотреть как он реализует эти семь элементов и начать работать. Краткое описание каждого элемента: Ввод. Это информация, поступающая с клавиатуры, диска или порта ввода/вывода. Данные. Это константы, переменные и структуры, содержащие числа (целые и вещественные), текст (символы и строки) или адреса (переменных и структур). Операции. Осуществляют присваивание значений, вычисление выражений (сложение, деление и т.д.), сравнение значений (равно, не равно, больше и т.д.). Вывод. Это означает вывод и запись информации на экран, на диск или в порт ввода/вывода. Условное выполнение. Это выполнение одной или набора команд, если выполняется (истинно) некоторое условие (и, если условие не выполняется, то эти команды пропускаются или выполняется другой набор команд) или если элемент данных имеет указанное значение или диапазон значений. Циклы. В циклах набор команд выполняется определенное число раз, пока истинно некоторое условие, или пока условие не станет истинным. Подпрограммы. Набор инструкций, объединенных именем, которые выполняются в любом месте программы, где есть вызов по имени. Рассмотрим, как использовать эти элементы в Turbo Pascal. Типы даных. В процессе программирования программист имеет дело с информацией, представляющей из себя пять основных типов: целые числа, вещественные числа, символы и строки символов, булевские данные и указатели. Целые числа - это числа, с помощью которых Вы учились считать (1, 5, -21 и 752, например). Вещественные числа имеют дробные части (3.14159) и экспоненты (2.579x10**24). Они также известны как числа с плавающей точкой. Символы - это любые буквы алфавита, символы и цифры 0-9. Они могут использоваться отдельно (а, z, !, 3) или объединяться в символьные строки ('Это только проверка'). Булевские выражения имеют только два значения: TRUE или FALSE (истина или ложь). Они используются в условных выражениях. Указатели - это адреса ячеек памяти, содержащих информацию. Целые числа. В стандартном Паскале целочисленный тип определяется в пределах от -MaxInt до MaxInt, где MaxInt - набольшее возможное целое значение, допустимое для процессора. В Turbo Pascal поддерживается целочисленный тип MaxInt = 32,767, допуская значение -32,768. Переменная целочисленного типа занимает 2 байта. В Turbo Pascal, кроме того, поддерживается четыре других целочисленных типов данных, каждый из которых имеет свой диапазон значений. Таблица 2.1. Целочисленные типы данных. ------------------------------------------------------------------- Тип Диапазон Размер в байтах ------------------------------------------------------------------- Byte 0..255 1 (целое длиной в байт) Shortint -128..127 1 (короткое целое) Integer -32768..32767 2 (целое) Word 0..65535 2 (длиной в слово) Longint -2147483648..2147483647 4 (длинное целое) ------------------------------------------------------------------- Заключение: Turbo Pascal позволяет использовать шестнадцатиричные целые значения (основание 16). При описании шестнадцатиричной константы перед ней указывается знак доллара $, например $27=39. Вещественный тип данных. В стандартном Паскале тип Real представляет значение с плавающей точкой, содержащее мантиссу и экспоненту - степень числа 10. Количество значащих цифр в мантиссе и диапазон значений экспоненты зависят от компьютера. В Turbo Pascal данные вещественного типа имеют размер в 6 байт, с 11 значащими цифрами мантиссы и экспоненты от 10**-38 до 10**38. Кроме того Turbo Pascal поддерживает стандарт IEEE 754 для двоичной арифметики с плавающей точкой. В этом случае добавляются типы данных с Single, Double, Extended и Comp: Single - размер 4 байта, допускается 7 значащих цифр и диапазон экспоненты от 10**-45 до 10**38; Double - размер 8 байт, допускается 15 значащих цифр и диапазон экспоненты от 10**-324 до 10**308; Extended - размер 10 байт, допускается 19 значащих цифр и диапазон экспоненты от 10**-4951 до 10**4931. Если у вас есть процессор 8087, и включена работа с числовым сопроцессором ({$N+}), Turbo Pascal генерирует инструкции 8087 для поддержки этих типов и выполнения всех операций с плавающей точкой на 8087. Если у Вас нет 8087, но Вы хотите использовать IEEE типы, Вы можете указать Turbo Pascal эмулировать процессор 8087, разрешая и эмуляцию 8087 и обработку с плавающей точкой (директивы {$E+,N+}). Turbo Pascal подключает специальную библиотеку, которая выполняет операции с плавающей точкой, так же как процессор 8087. Таблица 2.2 Вещественные типы данных. ------------------------------------------------------------------- Тип Диапазон Значение Размер в цифры байтах ------------------------------------------------------------------- Real 2.9х10Е-39..1.7х10Е38 11-12 6 (вещественный) Single(с одинар- 1.5х10Е-45..3.4х10Е38 7-8 4 ной точностью) Double(с двойной 5.0х10Е-324..1.7х10Е308 15-16 8 точностью) Extended(повышен- 1.9х10Е-4951..1.1х10Е4932 19-20 10 ной точности) Comp(сложный) -2Е+63+1..2Е+63-1 19-20 8 *Comp - только целые значения ------------------------------------------------------------------- Вызовем редактор Turbo Pascal и заведем программу: program DoRatio; var A, B: Integer; Ratio: Real; begin Write('Enter two numbers: '); Readln(A, B); Ratio := A div B; Writeln('The ratio is ', Ratio) end. Сохраним ее в файле DORATIO.PAS с помощью функции основного меню File/Save As. Нажмите ALT-R для компиляции и запуска программы. Введем два значения, 10 и 3, и получим результат 3.000000. Ожидая ответа 3.3333333333, мы получили результат 3. Получили такой результат, потому что был использован оператор "div" для деления целых чисел. Исправим оператор "div" на Ratio := A / B; сохраним код (F2), откомпилируем и выполним. Новый результат 3.3333333333, как и ожидали. Оператор деления "/" обеспечивает более точный результат. Символьные и строковые типы данных. Научившись записывать числовые данные, выучим запись и использование символьных и строковых данных. Паскаль позволяет определять тип Char, имеющий размер в один байт и содержащий один символ. Символьные константы содержат один символ, заключенный в апострофы ('A','e','г','2'). Заметим, что '2' означает символ 2, а 2 означает целое число 2 (и 2.0 - вещественное число) . program DoRatio; var A, B: Integer; Ratio: Real; Ans: Char; begin repeat Write('Enter two numbers: '); Readln(A, B); Ratio := A / B; Writeln('The ratio is ', Ratio); Write('Do it again? (Y/N) '); Readln(Ans); until UpCase(Ans) = 'N'; end. После вычисления коэффициента, выдается сообщение: Do it again? (Y/N). (Повторить? (Да/Нет)). Программа находится в состоянии ожидания одного из указанных символов и нажатия клавиши "Enter". Если Вы нажмете "n" или заглавную "N", то условие "until" будет выполнено и цикл закончится. В случае, если Вы ответите "Y" ("y"), то выполнение цикла будет продолжено. "N" и "n" не одно и тоже, потому что они имеют различные значения в коде ASCII. Каждый символ имеет свой код ASCII, представленный 8-битным значением (символ занимает 1 байт). Приложение B в Руководстве программиста содержит список кодов ASCII для всех символов. В Turbo Pascal существуют два дополнительных способа описания символьных констант: с помощью символа "^" и символа числа "#". Символы с кодами от 0 до 31 - управляющие символы. Они обозначаются аббревиатурами (CR - возврат каретки, LF - перевод строки, ESC - выход) или с помощью двух клавиш, одна из которых Ctrl + буква. Значение буквы получается прибавлением 64 к управляющему коду. Например, управляющий символ кода ASCII 7 известен как Bel или CtrlG. Turbo Pascal дает возможность представить символы с помощью "^", за которым следует буква (или символ). Так, "^G" то же самое, что и Ctrl-G. "^G" можно использовать в операторах Turbo Pascal: Writeln (^G). Этот метод применим только к управляющим символам. Вторая возможность обозначения - использование символа номера "#", за которым следует код ASCII. Так, #7 то же самое, что и "^G", #65 - 'A', a #233 - один из специальных псевдографических символов IBM PC. В большинстве случаев используются строки символов. В стандартном Паскале не поддерживается тип строк символов. В Turbo Pascal реализована эта возможность. Рассмотрим программу program Hello; var Name: String(30); begin Write('What is your name? '); Readln(Name); Writeln('Hello, ', Name) end. Переменная Name объявлена, как string (строка), и под нее резервируется 30 байт (для 30 символов). Кроме того, Turbo Pascal отводит еще один байт, в котором содержится текущая длина строки. В этом случае, независимо от того, какой длины будет введено имя, оператор Writeln распечатает имя указанной длины. Если будет введено имя больше 30 символов, то будут использоваться только первые 30 символов, а остальные будут проигнорированы. При описании строковой переменной можно указывать ее размер, но не более 255. По умолчанию длина строковой переменной - 255 символов. Turbo Pascal предлагает несколько процедур и функций, работающих со строковыми переменными. Их описание дано в главе 1 Справочного руководства по библиотеке. Булевские данные. Встроенный тип Boolean данных в Turbo Pascal имеет два возможных значения: True и Falsе (истина и ложь). Можно объявить переменную типа Boolean, и присвоить ей значение True или False, или же, что более важно, присвоить ей значение выражения, которое при вычислении принимает одно из этих значений. Булевское выражение - это выражение, которое принимает значение True или False. Оно состоит из выражений отношений, булевских операторов, булевских переменных и/или других булевских выражений. Например: while (Index <= Limit) and not Done do... while содержит булевское выражение. Булевское выражение в этом случае все, что находится между ключевыми словами while и do. Done - это переменная (или функция) булевского типа. Указатели. Все рассмотренные типы данных содержат непосредственно данные. Указатель, содержащий другой тип информации - адрес. Указатель - это переменная, содержащая адрес памяти, где какие либо данные помещаются. Другими словами, он указывает на данные, как адресная книга или оглавление. Обычно указатель указывает на данные определенного типа. Расмотрим следующий пример: type Buffer = string[255]; BufPtr = ^Buffer; var Buf1: Buffer; Buf2: BufPtr; Тип данных Buffer определен, как строковая переменная размером 255 байт, в то же время BufPtr - указатель на Buffer. Переменная Buf1 имеет тип Buffer и занимает (255+1) байт памяти. Переменная Buf2 имеет тип BufPtr, это 32-битовый адрес и занимает 4 байта памяти. Куда указывает Buf2? В данный момент никуда. Прежде чем использовать BufPtr, необходимо зарезервировать (распределить) память и запомнить ее адрес в Buf2. Вы делаете это, используя процедуру New: New(Buf2); Поскольку Buf2 указывает на тип Buffer, то этот оператор выделит в памяти 256-байтовый буфер и его адрес поместит в Buf2. Как использовать Buf2 и данные, на которые он указывает? С помощью оператора ^. Например, необходимо поместить строку и в Buf1 и в буфер, на который указывает Buf2: Buf1 : = 'Эта строка помещается в Buf1'; Buf2^: = 'Эта строка помещается по указателю Buf2'; Отметим различие между Buf2 и Buf2^: Buf2 означает 4-байтовую переменную указателя; Buf2^ - 256-байтовую строковую переменую, адрес которой в Buf2. Теперь, как освободить память, на которую указывает Buf2? Используя процедуру Dispose. Эта процедура освобождает память. После того, как при помощи Dispose освобождена память, следует присвоить указателю значение nil, т.е. указатель ни на что не указывает: Dispose(Buf2); Buf2 := nil; Заметим, что значение nil присваивается указателю Buf2, а не Buf2^. Идентификаторы. До сих пор в примерах содержались идентификаторы переменных без описания ограничений и правил их образования. Рассмотрим их более подробно. Имена, которые даются константам, типам данных, переменным, функциям, известны как идентификаторы. Идентификаторы использовались для: Integer, Real, String встроенных типов данных; Hello, DoSum, Ratio названия основных программ; Name, A, B, Sum, Ratio переменных определенных; Write, Writeln, Readln имен встроенных процедур. Turbo Pascal имеет несколько правил образования идентификаторов. Краткое описание правил: - Все идентификаторы начинаются с буквы или знака подчеркивания (a..z, A..Z, _). Последующими символами могут быть буква, знак подчеркивания, цифра (0-9). Другие символы недопустимы. - Идентификаторы рассматриваются без учета регистров (прописные и строчные буквы не различаются). Это значит, что a..z тождественно A..Z. Например index тоже самое что и Index, и INDEX. - Идентификаторы могут иметь различную длину, но используются только первые 63 символа. Операторы. Итак, данные получены программой и присвоены переменым. Программе нужно их обработать и получить результат, используя операторы. Существует восемь типов операторов: присваивания, арифметические, побитовые, отношений, логические, над множествами, адресные и над строками. Большинство операторов в Паскале бинарные, имеют два операнда; унарные операторы имеют один операнд. Бинарные операторы имеют обычно алгебраическую форму, например а+b. Унарный оператор предшествует своему операнду, например -b. В сложных выражениях порядок выполнения операций определяется правилами приоритета ( см. таблицу 2.3) Таблица 2.3 Приоритет операторов. ─────────────────────────────────────────────────────────────────── Операторы Приоритет Категория ─────────────────────────────────────────────────────────────────── @, not Первый (высший) Унарные *, /, div, mod, Второй Мультиплика- and, shl, shr тивные +, -, or, xor Третий Аддитивные =, <>, <, >, Четвертый (низший) Отношения <=, >=, in ─────────────────────────────────────────────────────────────────── Операции равного приоритета выполняются слева направо, хотя компилятор может их перегруппировать для генерации оптимального кода. Последовательность операторов с одинаковым приоритетом выполняется слева направо. Выражения, заключенные в скобки, вычисляются в первую очередь, независимо от предшествующих и последующих операторов. Операторы присваивания. Основной операцией является операция присваивания: Ratio := A/ B. В Паскале операция присваивания - это комбинация двоеточия и знака равенства: ":=". В примере значение выражения А /В, стоящее справа от ":=", присваивается переменной Ratio, стоящей слева. Арифметические операторы. Паскаль поддерживает обычный стандартный набор бинарных арифметических операторов, которые выполняются над целыми и веществеными числами: - умножение (*); - деление целых (div); - деление вещественных с остатком (/); - остаток от деления (mod); - сложение (+); - вычитание (-). Кроме того, поддерживаются унарные операторы: - унарный минус (а+(-b)) - дополнение до двух; - унарный плюс (а+(+b)) - ничего не выполняет, введен для полноты. Побитовые операторы. Для операций над битами в Паскале имеются следующие операторы: - shl (shift left) Сдвигает биты влево на указанное число бит, заполняя оставшиеся справа разряды нулями - shr (shift right) Cдвигает биты вправо на указанное число бит, заполняя оставшиеся слева разряды нулями - and Выполняет логическое and (и) над парой битов, возвращает 1 , если оба бита 1 и 0 в противном случае - or Выполняет логическое or (или) над парой битов, возвращает 0 , если оба бита равны 0 и 1 в противном случае - xor Выполняет логическое исключающее или над парой битов, возвращает 1, если биты имеют разное значение и 0 в противном случае - not Операция логического дополнения бита заменяет 0 на 1 и обратно. Эти операции выполняют действия на низком уровне с целочисленными значениями . Операторы отношений. Операторы отношений сравнивают два значения, возвращая в результате булевское значение True или False. В Паскале реализуются операторы: > - больше, чем; >= - больше, чем или равно; < - меньше, чем; <= - меньше, чем или равно; = - равно; <> - не равно; in - является элементом. Почему необходимо знать, каков результат: True или False? Введем следующую программу: program TestGreater; var A, B: Integer; Test: Boolean; begin Write('Введите два числа: '); Readln(A, B); Test := A > B; Writeln('А больше чем В', Test); end. Результат программы : True, если А больше В , и False , если А меньше или равно В. Логические операторы. В Паскале есть четыре логических оператора - and, xor, or, not. Они аналогичны побитовым операторам, но имеют свои отличия. Эти логические операторы работают с логическими значениями (True и False), позволяя комбинировать выражения отношений, булевские переменные и булевские выражения. Различия между этими операторами и побитовыми операторами следующие: - Логические операторы возвращают результат True или False (булевское значение), в то время как побитовые операторы производят действие над целыми значениями. - Эти операторы не позволяют комбинировать булевские и целые выражения; другими словами, выражение Flag and Indx недопустимо, если Flag - булевский тип, а Indx - целый тип ( или наоборот). - Логические операторы and и or имеют короткую форму вычисления по умолчанию, а xor и not - нет. Допустим, имеется выражение exp1 and exp2. Если exp1 - False, то все выражение имеет значение False и выражение exp2 не вычисляется. Аналогично, в выражении exp1 or exp2, exp2 не будет вычисляться, если exp1 - True. Можно установить полную схему вычисления булевских выражений, используя директиву компилятора {$В+} или опции Complete Boolean Eval (Options/Compiler). Адресные операторы. В Паскале поддерживаются два специальных оператора над адресами: вычисление адреса (@) и оператор косвенной ссылки (^). Оператор @ возвращает адрес заданной переменной; если Sum переменная целого типа, то @Sum - адрес в памяти этой переменной. Аналогично, если ChrPtr - это указатель на тип Сhar, то ChrPtr^ - это символ, на который указывает ChrPtr^. Операторы над множествами. Операторы над множествами выполняются в соответствии с правилами логики теории множеств.Они включают: - + - объединение; - - - разность; - * - пересечение. Строковые операторы. Существует единственный оператор - "+", который выполняет конкатенацию двух строк. Вывод. Может показаться странным , что речь о выводе пойдет прежде, чем о вводе, но программа, которая не выводит какую-либо информацию, не имеет смысла. Вывод обычно принимает форму, которая зависит от выходного устройства: на экран (слова и изображения), на запоминающие устройства (дискеты и винчестер), в порты ввода/вывода. Процедура Writeln. Вы уже использовали наиболее распространенную функцию Паскаля - подпрограмму Writeln. Назначение ее - запись (вывод) информации на экран. Ее формат прост и гибок при использовании: Writeln (элемент,элемент,....); Каждый элемент - это то, что Вы хотите вывести на экран и может быть: значением , таким как целое или вещественное число (3, 42, - 1732.3), символом ('a','Z'), строкой ('Здравствуй, мир'), булевским значением (True). Кроме того, может быть именованная константа (имя константы), переменная, указатель, вызов функции, если она возвращает значение целого типа, вещественное число, символ, строку или булевский тип. Все элементы печатаются в строку в заданном порядке. После вывода курсор устанавливается на начало следующей строки. Если есть необходимость оставить курсор в этой же строке после последнего элемента, то используйте Write (элемент,элемент,...); При выводе элементов Writeln между ними автоматически пробелы не вставляются. При желании иметь их, необходимо их учесть самим: Writeln (элемент,' ',элемент,' ',....); Следующими операторами описывается вывод : A:=1; B:=2; C:=3; Name := 'Frank'; Writeln(A, B, C); 123 Writeln(A, ' ', B, ' ', C); 1 2 3 Writeln('Hi', Name); HiFrank; Writeln('Hi, ',', Name, '.'); Hi, Frank. Так же можно использовать параметры определения ширины поля для данного элемента. В этом случае оператор имеет формат: Writeln (элемент: длина,....); где длина - целое выражение (литерал, константа, переменная, вызов функции), определяющее общий размер поля для вывода элемента. Рассмотрим следующую программу и полученный в результате вывод: A:=10; B:=2; C:=100; Writeln(A, B, C); 102100 Writeln(A:2, B:2, C:2); 10 2100 Writeln(A:3, B:3, C:3); 10 2100 Writeln(A, B:2, C:4); 10 2 100 Заметим, что элемент дополняется начальными пробелами слева в соответствии с указанной длиной. Само значение выравнивается справа. Что, если размер поля меньше, чем необходимо? Во втором операторе Writeln вышеприведенного примера для С=100, длина поля меньше, чем нужно, т.е. задано 2, нужно 3. При выводе Паскаль увеличивает размер до минимально необходимого. Этот метод применим для всех допустимых элементов: целого типа, вещественных чисел, символов, строк и булевских типов. Однако, при указании ширины (размера) поля для вещественных чисел выравнивание происходит слева и распечатывается в экспоненциальной форме. х:=421.53; Writeln(x); 4.2153000000E+02 Writeln(x:8); 4.2E+02 Поэтому, Паскаль позволяет добавить второй операнд длины: элемент : длина : количество цифр. Вторая цифра указывает, сколько цифр выводить для числа с фиксированной точкой после точки: х:=421.53; Writeln(x:6:2); 421.53 Writeln(x:8:2); 421.53 Writeln(x:8:4); 421.5300 Ввод. В стандартном Паскале есть две основных функции ввода информации Read и Readln, которые используются для чтения данных с клавиатуры. Их формат: Read (элемент,элемент,...); Readln (элемент,элемент,...);, где каждый элемент - это переменная целого, вещественного, символьного типа или строка. Числа должны отделяться друг от друга пробелами или нажатием клавиши Enter. Условные операторы. Иногда бывает необходимо выполнить часть программы, если заданное условие имеет значение True или False, или когда заданное выражение принимает определенное значение. Посмотрим, как это реализуется в Паскале. Оператор if. Посмотрим, как оператор if использовался в предыдущих программах, отметив, что его общий формат: if выражение then оператор 1 else оператор 2, где выражение - любое булевское выражение (вырабатывающее в результате True или False); оператор 1 и оператор 2 - операторы Паскаля. Если выражение принимает значение True, то выполняется оператор 1; в противном случае - оператор 2. Два важных момента, на которые следует обратить внимание при использовании if/then/else. Во-первых, оператор else не является обязательным, другими словами, допустимо использовать оператор if в следующем виде: if выражение then оператор 1 В этом случае оператор 1 выполняется только тогда, когда выражение имеет значение True. В противном случае пропускается оператор 1 и выполняется следующий оператор. Во-вторых, если необходимо выполнить более одного оператора, в случае, когда выражение принимает значение, True или False, то следует использовать составной оператор. Составной оператор - это ключевое слово begin, несколько операторов разделенных точкой с запятой и ключевое слово end. В примере используется один оператор: if B = 0.0 then Writeln('деление на нуль невозможно.'). Использование составного оператора в предложении else: else begin Ratio := A / B; Writeln('Отношение =' , Ratio) end; Оператор выбора case. Оператор case - мощное средство выбора альтернатив. Позволяет уменьшить количество операторов if. Оператор case состоит из выражения (селектора) и списков операторов, каждому из которых предшествует метка того же типа, что и селектор. Это значит, что в данный момент выполняется тот оператор, у которого значение совпадает с текущем значением селектора. Если совпадения значений не происходит, то не выполняется ни один из операторов, входящих в case или же выполняются операторы, стоящие после необязательного слова else (else - расширение стандартного Паскаля). Метка case состояит из любого количества констант или поддиапазонов, разделенных запятыми, за которым следует двоеточие (:), например: case BirdSight of 'C', 'c': Curlens := Curlens + 1; 'H', 'h': Herons := Herons + 1; 'E', 'e': Egrets := Egrets + 1; 'T', 't': Terns := Terns + 1; end; {case} Диапазон записывается в виде двух констант, разделенных двумя точками "..". Тип константы должен соответствовать типу селектора. Оператор, стоящий после двоеточия (:), выполняется в том случае, если значение селектора совпадает со значением константы или, если его значение попадает в диапазон значений. Цикл. В случае, когда при выполнении какого-либо условия (или невыполнения), необходимо выполнять группу операторов повторно, используются циклы. Существует три основных вида циклов: цикл while, цикл repeat и цикл for. Рассмотрим их. Цикл while. Цикл while используется для проверки некоторого условия в начале цикла. Введите следующую программу: program Hello; var Count: Integer; begin Count := 1; while(Count <= 10) do begin Writeln('Здравствуй и прощай!'); Inc(Count); end; Writeln('Это конец'); end. Во-первых, сначала переменной Count присвоится значение равное 1. Затем, при входе в цикл проверяется условие: значение Count меньше или равно 10. Если да, то выполняется тело цикла (операторы, находящиеся между ключевыми словами begin....end.) На экран выводится сообщение "Здравствуй и прощай". Значение Count увеличивается на 1. Возврат на начало цикла. Значение Count проверяется заново и тело цикла выполняется вновь, до тех пор пока значение переменной Count удовлетворяет условию. Как только значение Count становится равным 11, цикл завершается, и на экран выводится сообщение "Это конец". Формат оператора цикла while: while выражение do оператор; В цикле while вычисляется выражение. Если оно имеет результат - True, выполняется оператор. В противном случае выполнение цикла завершается. Цикл Repeat....Until. Второй цикл repeat...until рассмотрим на примере программы DORATIO.PAS: program DoRatio; var A, B: Integer; Ratio: Real; Ans: Char; begin repeat Write('ВВедите два числа'); Readln(A, B); Ratio := A / B; Writeln('Отношение равно', Ratio); Writeln('Повторить? (Y/N)'); Readln(Ans); until Upcase(Ans) = 'N'; end. Как описывалось ранее, в этой программе повторяется выполнение операторов, пока ответ на вопрос - n или N (Повторить? Y/N). Другими словами repeat и until, повторяются, до тех пор, пока значение выражeния при until не будет Тrue. Формат цикла: repeat оператор; оператор; ........ оператoр; until выражение. Существуют три основных отличия от цикла while: - операторы в цикле repeat выполняются хотя бы один раз, потому что проверка выражения осуществляется в конце тела цикла. В цикле while, если значение выражения False, тело его пропускается сразу. - цикл repeat выполняется пока выражение не станет True, в то время, как цикл while выполняется до тех пор, пока выражение имеет значение True. При замене одного типа цикла на другой необходимо на это обращать особое внимание. Рассмотрим программу HELLO, где цикл while заменен на цикл repeat: program Hello; var Count: Integer; begin Count := 1; repeat Writeln('Здравствуй и прощай!'); Inc(Count); until Count > 10; Writeln('Это конец'); end. Отмeтим, что теперь переменная Count проверяется на значение больше 10 (а в while было Count <= 10). В заключение, в цикле repeat может использоваться просто группа операторов, а не состaвной оператор. При использовании этого цикла не используются слова begin...end, как в случае с циклом while. Запомните, что цикл reрeat выполнится хотя бы один раз, в то время, как цикл while может ни разу не выполниться в зависимости от значения выражения. Цикл for. Цикл for существует во многих языках программирования. В Паскале тоже. Однако, вариант этого цикла в Паскале как эффективен, так и ограничен. Обычно, набор операторов выполняется фиксированное число раз, пока переменная (индексная) принимает значение в указанном диапазоне. Модифицируем знакомую программу Hello следующим образом. program Hello var Count: Integer; begin for Count := 1 to 10 do Writeln('Здравствуй и прощай!'); Writeln('Это конец'); end. При выполнении этой программы видно, что цикл for выполняется так же, как и циклы while и repeat. Фактически эквивалентно циклу while. Формат цикла for: for индекс:=выражение1 to выражение2 do оператор где индекс - скалярная переменная (целого типа, символьного, булевcкого и любого перечислимого типа); выражение1 и выражение2 - выражения типа, совместимого с типом индекса; оператор - одиночный или составной оператор. Индекс увеличивается на 1 после каждого выполнения цикла. Индекс можно уменьшать на 1. Для этого ключевое слово to заменяется на downto. Цикл for эквивалентен следующей программе с циклом while: index :=exprl; while index <= expr2 do begin оператор; Inc(index) end; Главный недостаток цикла for - это возможность уменьшить или увеличить индекс только на 1. Основные преимущества - краткость, возможность использования символьного и перечислимого типа в диапазоне значений. Процедуры и функции. Вы изучили условное и итеративное выполнение операторов программы. Теперь посмотрим, как можно выполнить один и тот же набор команд в разных местах программы и с разными данными. Можно объединить эту группу операторов в подпрограмму, которую можно вызвать по необходимости. В Паскале есть два вида подпрограмм: процедуры и функции. Главное различие между ними - это то, что функция возвращает значение и может быть использована в выражении: X := sin(А); в то время, как процедура может быть вызвана : writeln("Это проверка"); Однако перед знакомством с процедурами и функциями, необходимо рассмотреть структуру программ. Структура программ. В стандартном Паскале программы имеют жесткий формат: program имя программы label метки; const объявление констант; type определение типов данных; var объявление переменных; procedure и function; begin тело программы end. Наличие всех пяти секций объявлений - label, const, type, var, procedure и function - в Вашей программе необязательно. Однако для стандартного Паскаля, если они присутствуют, порядок их следования строго регламентирован, и в программе они должны присутствовать только один раз. За секцией объявлений, следуют процедуры и функции, и только затем тело программы. Turbo Pascal обеспечивает более гибкую структуру программы. Главное - это оператор program должен быть первым, а тело программы последним. Порядок описания остальных секций жестко не регламентирован, но идентификаторы должны быть объявлены до их использования во избежание ошибок компиляции. Структура процедуры и функции. Процедуры и функции, известные под общим именем как подпрограммы могут быть описаны в любом месте программы, но до тела главной программы. Формат процедур: procedure имя процедуры (параметры); label метки; const объявление констант; type определения типов данных; var объявления переменных; procedure и function; begin тело главной процедуры; end; Функции имеют такой же формат, как и процедуры, только они начинаются с заголовка function и заканчиваются типом данных возвращаемого значения: function имя функции (параметры): тип данных; Имеются только два различия между программами, процедурами и функциями: - процедуры и функции имеют заголовок procedure или function, соответственно, а не program; - процедуры и функции заканчиваются точкой с запятой (;), а не точкой (.). Процедуры и функции могут иметь описания своих констант, типов данных, переменных и свои процедуры и функции. Но все эти элементы могут быть использованы только в тех процедурах и функциях, где они объявлены. Пример программы. Рассмотрим версию программы DORATIO, в которой используются процедура получения двух значений и функция, определяющая их отношение: program DoRatio; var A, B: Integer; Ratio: Real; procedure GetData(var X, Y: Integer); begin Writeln('Введите два числа:'); Readln(X, Y); end; function GetRatio(I, J: Real); begin GetRatio(I / J); end; begin GetData(A, B); Ratio := GetRatio(A, B); Writeln('Отношение равно ', Ratio); end. Это, конечно, не улучшение первоначальной программы, так как она имеет больший размер и медленнее выполняется. Но она показывает как используются и работают процедуры и функции. После компиляции и запуска программы первым выполняется оператор GetData(A,B). Этот тип оператора известен как вызов процедуры. При обработке вызова выполняются операторы в GetData, при этом X и Y (формальные параметры) заменяются на А и В (фактические параметры). Ключевое слово var перед X и Y в операторе вызова GetData говорит о том, что фактические параметры должны быть переменными и что значения переменных могут быть изменены и возвращены вызывающей программе. При завершении работы GetData управление возвращается в главную программу на оператор, следующий за вызовом GetData. Следующий оператор - вызов функции GetRatio. Отметим некоторые отличия. Во-первых, GetRatio возвращает значение, которое должно быть использовано; в этом случае, оно присваивается Ratio. Во-вторых, значение присваивается GetRatio в главной программе; этим функция определяет, какое значение возвращается. В-третьих, нет ключевого слова var перед формальными параметрами I и J. Это означает, что они могут быть любыми целочисленными выражениями, такими как Ratio:= GetRatio(A+B,300); и что если даже их значения будут изменены в функции, то новые значения не возвратятся обратно в вызывающую программу. Кстати, это не является отличием процедуры от функции. Можно использовать оба типа параметров для обоих типов программ. Комментарии. Иногда бывает необходимо вставить в программу замечания, напоминающие или информирующие о том, что означает переменная, какие действия выполняет функция или оператор. Эти замечания называют комментариями. Паскаль позволяет вставлять в программу сколько угодно комментариев. Комментарий начинается левой фигурной скобкой ({). Она указывает компилятору: игнорировать все, пока не встретится правая фигурная скобка(}). Комментарий может занимать несколько строк: { Это пример длинного комментария, занимающего несколько строк} Кроме того, существует альтернативная форма комментария. Начинается "(*" и заканчивается "*)". Комментарий, начинающийся с "(*" игнорирует все фигурные скобки, и наоборот.