| |
|Краткий курс лекций |
|"Основы программирования на языке Паскаль" |
| |
| |
|Введение. |
| Прежде всего, следует напомнить, что изучение языка программирования |
|представляет собой знакомство с формальными правилами записи алгоритмов для|
|их последующего выполнения компьютером. Формальность сия проистекает из |
|самих принципов, заложенных в архитектуру вычислительных устройств, и |
|жесткости математической логики. Поэтому, постарайтесь воспринять все |
|довольно строгие правила как неизбежность, настроить себя на серьезную, |
|скрупулезную, порой сложную работу. Однако не стоит бояться, расстраиваться|
|и сетовать на судьбу: немного аккуратности, внимания, знания предыдущего |
|материала - и вы уже программист. |
| |
|Основные понятия. |
| Как и любой алгоритм, являющийся, как вы помните, последовательностью |
|инструкций, программа на языке Паскаль состоит из команд (операторов), |
|записанных в определенном порядке и формате. |
| Команды позволяют получать, сохранять и обрабатывать данные различных |
|типов (например, целые числа, символы, строки символов, т.д.). Однако кроме|
|команд в записи программы участвуют еще так называемые "служебные слова". |
|Это и есть элементы формальности, организующие структуру программы. Их не |
|так много, но их значение трудно переоценить. Служебные слова можно |
|использовать только по своему прямому назначению. Переопределять их не |
|разрешается. |
| Вам уже известно, что основное назначение компьютера - облегчить |
|человеку работу с большими объемами информации, поэтому подавляющее |
|большинство программ построено по одному, довольно простому принципу: |
|получение данных из внешнего мира (ввод), обработка их по соответствующему |
|алгоритму, хранение необходимой информации и вывод во внешний (по отношению|
|к компьютеру) мир полученных результатов. Все эти действия реализуются |
|через имеющиеся в языках программирования команды, алгоритмические |
|структуры и структуры данных. |
| |
|Основная структура программы. |
| Правила языка Паскаль предусматривают единую для всех программ форму |
|основной структуры: |
|Program ; |
| |
|Begin |
| |
|End. |
| Здесь слова Program, Begin и End являются служебными. Правильное и |
|уместное употребление этих слов является обязательным. |
| Угловые скобки в формате указывают на то, что вместо них при реальном |
|программировании должно быть подставлено конкретное значение. Сама запись |
|программы в принципе может производиться вообще в одну стоку. При этом ее |
|части должны отделяться друг от друга хотя бы одним пробелом. Однако, такая|
|запись неудобна для чтения, недостаточно наглядна, поэтому я рекомендую |
|придерживаться приведенной структуры, а в теле программы по возможности |
|записывать по одному оператору в строке. |
| Имя программы выбирается программистом самостоятельно в соответствии с|
|правилами построения идентификаторов. |
| Все объекты, не являющиеся зарезервированными в Паскале, наличие |
|которых обусловлено инициативой программиста, перед первым использованием в|
|программе должны быть описаны. Это производится для того, чтобы компьютер |
|перед выполнением программы зарезервировал память под соответствующие |
|объекты и поставил в соответствие этим участкам памяти идентификаторы. |
|Раздел описаний может состоять из пяти подразделов: |
| 1. Описание меток (Label). |
| 2. Описание типов (Type). |
| 3. Описание констант (Const). |
| 4. Описание переменных (Var). |
| 5. Описание процедур и функций (Procedure, Function). |
| При отсутствии необходимости в каком-либо виде объектов, |
|соответствующий подраздел может быть опущен. |
| |
|Алфавит языка. |
| Основу любого языка составляет алфавит, то есть конечный, |
|фиксированный набор символов, используемых для составления текстов на |
|данном языке (в нашем случае - программ). Конечно, стройность картины |
|немного портит наличие диалектов, создающихся стихийно и очень часто |
|включающих в себя апокрифические (неканонические) буквы и знаки. В |
|программировании эта проблема решается введением понятия "стандарт языка". |
|Оно практически неприменимо к языкам человеческим, вечно развивающимся и |
|изменяющимся. Мы с вами в основном будем говорить о той самодостаточной |
|части языка Паскаль, которая входит в различные его компьютерные реализации|
|в неизменном виде. В плане изучения, я не вижу большого смысла излагать вам|
|строгие правила стандарта, хотя такие существуют. Ограничимся некоторыми |
|замечаниями, раскрывающими все же формальности употребления символов в |
|языке Паскаль. |
| Итак, алфавит языка Паскаль составляют: |
| 1) буквы латинского алфавита; |
| 2) арабские цифры; |
| 3) специальные знаки. |
| Использование символов первой группы чаще всего вопросов не вызывает, |
|но свои тонкости здесь имеются. Во-первых, это употребление заглавных и |
|строчных букв. Большинство существующих трансляторов не различают буквы |
|разных регистров. Таким образом, записи "progRaM" и "PROGram" будем считать|
|идентичными. Во-вторых, некоторые символы латиницы и кириллицы совпадают по|
|начертанию. Нельзя ли вместо буквы "К" латинской написать "K" русскую? |
|Ответ: в тетради (если вы их сможете различить) - пожалуйста, в программе |
|на ЭВМ - ни в коем случае. На вид они может быть и похожи, но уж коды-то у |
|них совершенно разные, а компьютер, как вам известно, оперирует внутри себя|
|не буквами, а их числовыми кодами. |
| По поводу привычных арабских цифр сказать можно только то, что с их |
|помощью записываются не только числа. Цифры в качестве обыкновенных |
|символов могут использоваться в различных других конструкциях языка. |
| Сложнее всего обстоит дело со специальными знаками, поэтому их |
|придется разобрать подробно, иногда забегая вперед, но вы пока можете |
|пропускать мимо ушей непонятные термины, не забывая, однако, записывать все|
|в тетрадь. Потом, при изучении соответствующих структур, вы будете иметь |
|возможность заглянуть в этот раздел для того, чтобы уточнить какой знак в |
|данном месте необходимо использовать. |
| Наиболее часто употребляемым специальным символом является пробел (в |
|значимых местах мы будем обозначать его в записях знаком "V"). Его |
|использование связано с форматами основной структуры программы, разделов |
|описаний, операторов. Не следует путать наличие пробела с отсутствием |
|символа. |
| . конец программы, разделение целой и дробной частей вещественного |
|числа (десятичная точка), разделение полей в переменной типа Record; |
| , разделение элементов списков; |
| .. указание диапазона; |
| : используется в составе оператора присваивания, а также для |
|указания формата вывода в операторе Writeln; |
| ; отделяет один раздел программы от другого, разделяет операторы; |
| ' используется для ограничения строковых констант; |
| - + * / ( ) арифметические знаки (используются по своему |
|назначению); |
| < > знаки отношений; |
| = используется в составе оператора присваивания, в разделах |
|описаний констант и типов, используется как знак отношения (равно); |
| @ имя специального оператора определения адреса переменной, |
|подпрограммы; |
| ^ используется для именования динамических переменных; |
| {} ограничение комментариев в программе; |
| [ ] заключают в себе индексы элементов массивов; |
| _ символ подчеркивания используется также как любая буква, |
|например, в идентификаторах - вместо пробела; |
| # обозначение символа по его коду; |
| $ обозначение директивы компилятора, обозначение шестнадцатеричного|
|числа. |
| Возникает вопрос, а как же быть с русскими буквами и другими знаками, |
|имеющимися на клавиатуре? Некоторые версии Паскаля допускают их |
|использование в программе, но стандарт языка этого не подразумевает. |
|Поэтому включать эти символы в программу можно только в качестве строковых |
|констант или внутри комментария, то есть там, где транслятор при компиляции|
|их игнорирует. При использовании этих знаков в качестве данных, они |
|равноправны со всеми символами, которые может хранить в памяти и |
|обрабатывать компьютер. |
| |
|Идентификаторы. |
| Имена операторов, переменных, констант, типов величин, имя самой |
|программы назначаются программистом и называются в Паскале |
|идентификаторами. Существуют правила, которым должны отвечать все |
|идентификаторы: |
|идентификатор должен быть уникальным, то есть одним и тем же именем разные |
|объекты не могут быть названы; |
|идентификатор имеет ограничение по длине (зависит от конкретной реализации |
|языка на компьютере); |
|идентификатор может состоять только из символов латинского алфавита, цифр и|
|знака подчеркивания ("_"); |
|идентификатор не может начинаться с цифры. |
| |
|Константы. |
| Из всех подразделов описаний сейчас мы рассмотрим только описание |
|констант и переменных, остальные - позже. |
| Вообще говоря, в Паскале константами являются любые явно заданные в |
|программе данные (например, 7493, 'привет', 54.899). Следует обратить ваше |
|внимание на то, что при записи числовых констант с дробной частью эта часть|
|отделяется от целой не запятой, как, возможно, вы привыкли, а точкой. Для |
|записи очень больших по модулю или очень малых (близких к нулю) чисел |
|существует возможность записи их в так называемой экспоненциальной форме. С|
|такой записью вы встречались в математике и физике, но называли ее |
|стандартным видом числа. |
| Пример: 2 . 4 5 6 7 Е - 0 6 |
| ^мантисса ^порядок |
| Здесь буква "Е" отделяет мантиссу (совокупность значащих цифр числа с |
|десятичной точкой после первой) от порядка (показателя степени десятки в |
|стандартном виде числа). Вам предстоит научиться как читать числа в таком |
|виде, так и записывать. |
| Константы, представляющие собой строковые величины, заключаются в |
|апострофы. |
| Если одна и та же величина используется в программе несколько раз, то |
|удобнее было бы обозначить ее каким-нибудь именем и использовать это имя |
|везде, где требуется записать соответствующую константу. Кроме сокращения |
|размера исходного текста программы, это позволит избежать случайных ошибок,|
|а также упростит отладку программы. Описание именованных констант |
|начинается служебным словом Const. Далее следуют записи вида: |
|=; |
|Пример: |
|Const |
|Pi=3.14; |
|Name1='Татьяна'; |
|Name2='Виктор'; |
|R21=6.33187E+03; |
|W_W_W=934122; |
|Понятие переменной. Типы. |
| Данные, как вы знаете, хранятся в памяти компьютера, но для указания |
|на конкретную информацию очень неудобно все время записывать физические |
|адреса ячеек. Эта проблема в языках программирования высокого уровня, в |
|частности в Паскале, решена введением понятия переменной. Переменная в |
|Паскале - именованный участок памяти для хранения данных определенного |
|типа. Значение переменной (информация в соответствующих ячейках памяти) в |
|ходе выполнения программы может быть изменено. Константами же, как вы уже |
|знаете, называются величины, значение которых в ходе выполнения программы |
|изменено быть не может. Конкретные переменные и константы представляют |
|собой объекты уникальные и отличаются друг от друга именем. |
| В качестве данных в программах на языке Паскаль могут выступать числа,|
|символы, целые строки символов. Заметьте, что с этими различными видами |
|информации выполняются совершенно разные действия. Например, с числовыми |
|величинами производятся арифметические операции, чего невозможно сделать с |
|символьными. Кроме того, разные виды данных требуют различного объема |
|памяти для хранения. В соответствии с этими соображениями в языке Паскаль |
|введено понятие "Тип" (TYPE). Тип переменной указывает на то, какие данные |
|могут быть сохранены в этом участке памяти, и в каких действиях эта |
|переменная может участвовать. Существуют зарезервированные (базовые) типы в|
|языке Паскаль, но, как далее вы убедитесь, есть также возможность создавать|
|свои собственные, определяемые программистом типы переменных. |
| К базовым типам относятся: |
|тип целых чисел - Integer |
|тип "длинных" целых чисел - Longint |
|тип действительных (вещественных) чисел (то есть - с дробной частью) - Real|
| |
|тип неотрицательных целых чисел от 0 до 255 - Byte |
|тип неотрицательных целых чисел от 0 до 65535 - Word |
|символьный тип - Char |
|строковый тип - String |
|логический тип - Boolean |
| Физически типы данных отличаются друг от друга количеством ячеек |
|памяти (байтов), отводимых для хранения соответствующей переменной. |
|Логическое же отличие проявляется в интерпретации хранящейся информации. |
|Например, переменные типа Char и типа Byte занимают в памяти по одному |
|байту. Однако в первом случае содержимое ячейки памяти интерпретируется как|
|целое беззнаковое число, а во втором - как код (ASC) символа. |
| В отличие от констант, неименованных переменных не существует. Все |
|используемые в программе переменные должны быть описаны в соответствующем |
|разделе описания. |
| Раздел описания переменных начинается служебным словом Var, после |
|которого следуют записи следующего вида: :; |
| Список может состоять из нескольких имен (при этом они разделяются |
|запятыми), а также и из одного имени. Тип, указываемый после двоеточия, |
|определяет, какие данные теперь могут храниться в описанных таким образом |
|переменных. Для каждого используемого в программе типа переменных в разделе|
|их описания должна быть, как минимум, одна собственная строка. |
| Пример: |
|Var |
|A,B,H_22,Angle : Real; |
|Name3 : String; |
|Flag : Boolean; |
|I,J,K,Count : Word; |
|Оператор присваивания. Арифметические выражения. |
| Самым простым действием над переменной является занесение в нее |
|величины соответствующего типа. Иногда говорят об этом, как о присвоении |
|переменной конкретного значения. Такая команда (оператор) в общем виде |
|выглядит на языке Паскаль следующим образом: |
| :=; |
| Выражение, указанное справа от знака ":=", должно приводить к значению|
|того же типа, какого и сама переменная, или типа, совместимого с переменной|
|относительно команды присваивания. Например, переменной типа Real можно |
|присвоить значение типа Integer или Word (впрочем, наоборот делать нельзя).|
|Выражение будет сначала вычислено, затем, его результат будет положен в |
|ячейки памяти, отведенные для переменной. |
| Что же представляет собой выражение на языке Паскаль? Многое зависит |
|от типа выражения. Рассмотрим сначала выражения арифметические, то есть те,|
|результатом которых является число. |
| В состав арифметического выражения на языке Паскаль могут входить: |
|числовые константы; |
|имена переменных; |
|знаки математических операций; |
|математические функции и функции, возвращающие число; |
|открывающиеся и закрывающиеся круглые скобки. |
| Правила построения выражений напоминают математические с некоторыми |
|уточнениями. Выражение записывается в одну строку (никакой многоэтажности),|
|между операндами обязательно должен стоять знак операции (Запись "2x" - не |
|допускается), знаки некоторых операций и названия некоторых функций отличны|
|от привычных вам. |
| Операции: |
|+ сложение; |
|- вычитание; |
|/ деление; |
|* умножение; |
|MOD остаток от деления (записывается так: A MOD B; читается: остаток от|
|деления A на B); эта операция применима только к целым числам; |
|DIV целочисленное деление (записывается так A DIV B; читается: |
|результат деления A на B без дробной части); эта операция тоже применяется |
|только для целых операндов. |
| Аргументы функций всегда записываются в круглых скобках: |
|SIN(X) sin x; |
|COS(X) cos x; |
|ARCTAN(X) arctg x; |
|ABS(X) абсолютное значение x (в математике - |x|); |
|SQR(X) возведение x в квадрат; |
|SQRT(X) извлечение квадратного корня; |
|TRUNC(X) отбрасывание дробной части х; |
|ROUND(X) округление х до ближайшего целого числа; |
| После выполнения второго оператора присваивания в участке памяти, |
|отведенном под переменную R, окажется результат указанного выражения, |
|однако, к сожалению, узнать его мы не сможем, поскольку пока не имеем |
|возможности "заглянуть" в память машины, вывести значение переменной хотя |
|бы на экран. |
| |
|Составной оператор |
| Этот оператор, строго говоря, оператором не является. Дело в том, что |
|также как арифметические действия иногда бывает необходимо заключать в |
|скобки, последовательности команд (операторов) тоже иногда требуют |
|объединения. Это позволяют сделать так называемые операторные скобки. |
|Формат (общий вид) составного оператора таков: |
|Begin |
|; |
|; |
|...... |
| |
|End; |
| Возможно, такая структура напоминает вам основную структуру программы.|
|Действительно, отличие только в том, что после End в конце составного |
|оператора ставится точка с запятой, а в конце программы - точка. По своей |
|сути вся программа представляет собой большой составной оператор. |
| Обратите внимание на то, что точка с запятой перед End может не |
|ставиться. |
| Составной оператор предоставляет возможность выполнить произвольное |
|количество команд там, где подразумевается использование только одного |
|оператора. Как вы узнаете потом, такая необходимость встречается довольно |
|часто. |
| |
|Операторы ввода и вывода информации |
| Если вы помните, при рассмотрении примера работы оператора |
|присваивания мы столкнулись с необходимостью узнать результат выполнения |
|программы. Мы разобрались с тем, как информацию сохранять (в переменных), |
|как обрабатывать (с использованием выражений), но два фундаментальнейших |
|информационных процесса остались вне нашего внимания: получение информации |
|и передача ее во внешний по отношению к компьютеру мир. Пока наши программы|
|могут использовать лишь информацию, которая находится непосредственно в |
|тексте программы. Узнать, какие значения в данный момент имеют переменные, |
|также не представлялось возможным. Программирование в таких условиях теряет|
|смысл. |
| Взаимодействие устройств обработки и хранения информации с внешней |
|средой (хотя бы с пользователем) является совершенно необходимым. За такой |
|интерфейс в языке Паскаль отвечают операторы ввода-вывода информации. Эти |
|инструкции позволяют ввести аргументы, параметры расчетов во время |
|выполнения программы (а не на этапе ее написания), осуществить вывод |
|рассчитанных данных в понятном человеку виде. |
| Сначала операторы ввода (форматы операторов): |
|Read(); |
|Readln(); |
| В таком формате эти команды позволяют вводить данные в переменные во |
|время выполнения программы с клавиатуры. Элементами списка ввода могут быть|
|имена переменных, которые должны быть заполнены значениями, введенными с |
|клавиатуры. |
| Выполнение операторов ввода происходит так: ход программы |
|приостанавливается, на экран выводится курсор, компьютер ожидает от |
|пользователя набора данных для переменных, имена которых указаны в списке |
|ввода. Пользователь с клавиатуры вводит необходимые значения в том порядке,|
|в котором они требуются списком ввода, нажимает Enter. После этого |
|набранные данные попадают в соответствующие им переменные и выполнение |
|программы продолжается. |
| Примечание: данные при вводе разделяются пробелами. |
| Разница между работой процедур Read и Readln (от Read line) состоит в |
|следующем: после выполнения Read значение следующего данного считывается с |
|этой же строчки, а после выполнения Readln - с новой строки. |
| Для вывода информации в Паскале также есть две команды: |
|Write(); |
|Writeln(); |
| Такой формат использования Write и Writeln позволяет выводить на экран|
|монитора данные из списка вывода. Элементами списка вывода могут являться |
|имена переменных, выражения, константы. Прежде чем вывести на экран |
|компьютер значения выражений сначала вычислит. Элементы списка, также как и|
|в операторах ввода, разделяются запятыми. |
| Различие между двумя операторами вывода таково: после выполнения |
|оператора Writeln (от Write line) происходит переход на новую строчку, а |
|после выполнения инструкции Write, переход на новую строчку не происходит и|
|печать по последующим командам вывода Write или Writeln будет происходить |
|на той же строчке. При вызове оператора Writeln без параметров просто |
|происходит переход на новую строчку. |
| Приведем пример использования операторов ввода и вывода: |
|Program Inteface; |
|Var |
| R,S : Real; |
|Begin |
| Write('Введите радиус круга '); {Печать на экране просьбы о вводе} |
| Readln(R); {Ввод значения в |
|переменную R с клавиатуры} |
| S:=4*ARCTAN(1)*SQR(R); {Вычисление площади круга (pR2)} |
| Writeln('Площадь круга радиусом ',R,' равна ',S) |
|End. |
| Эта программа запрашивает у пользователя значение радиуса круга, |
|обеспечивает возможность ввести его значение, рассчитывает и выводит на |
|экран величину площади круга с таким радиусом. Таким образом, появляется |
|возможность, не внося изменений в текст программы, вводить различные |
|значения радиуса и получать, соответствующие им значения площади круга. Для|
|этого достаточно несколько раз запустить программу. Также эта программа |
|демонстрирует следующее правило: выдача результатов должна быть |
|прокомментирована так, чтобы был ясен смысл напечатанных чисел. |
|Действительно, ведь можно было бы ограничиться Writeln(S), но значение |
|выведенного программой числа в этом случае было бы ясно только тому, кто |
|эту программу написал. |
| |
|Метки. Оператор безусловного перехода. |
| Каждый дом на улице имеет свой номер, все люди имеют собственные |
|имена, даже ячейки памяти компьютера имеют каждая свой адрес. Все это |
|принято для того, чтобы иметь возможность однозначно указать на |
|определяемый объект. Точно также, для указания на операторы в программах |
|применяются метки. |
| Метка в стандарте языка Паскаль представляет собой целое |
|неотрицательное число. Все используемые в программе метки должны быть |
|перечислены в разделе описания меток, начинающемся служебным словом Label, |
|например: |
| Label 1, 2, 8; |
| Одной меткой можно пометить только один оператор. Метка от помеченного|
|оператора отделяется двоеточием. |
|Пример: |
| 6: Writeln(14/2); |
| Во всех приведенных ранее программах операторы выполнялись один за |
|другим в том порядке, в котором они были записаны в тексте. Такая |
|алгоритмическая структура называется прямым следованием. Однако, в языке |
|Паскаль изначально существует оператор, нарушающий прямолинейное выполнение|
|программы, передающий управление в произвольную ее точку. Такая инструкция |
|называется безусловным переходом и имеет такой формат: |
| Goto ; |
| Оператор, к которому происходит переход должен быть помечен данной |
|меткой. |
| Использовать оператор безусловного перехода следует крайне осторожно |
|во избежание получения ошибочных результатов или полного "зацикливания" |
|программы. Вообще, употребление данной команды среди программистов |
|считается дурным тоном. Как вы убедитесь, всегда существует возможность |
|обойтись без него. |
| |
|Условный оператор |
|Одной из основных алгоритмических структур является ветвление |
|(альтернатива). |
| Если условие выполняется, то будет выполнена инструкция "1", если нет,|
|то - инструкция "2". Несмотря на то, что в схеме присутствуют два действия,|
|выполнено будет только одно, так как условие либо ложно, либо истинно. |
|Третьего не дано. Такая схема позволяет решать задачи, в которых в |
|зависимости от сложившихся обстоятельств требуется совершить то или иное |
|действие. Нет никакого сомнения, что число задач такого рода огромно. Более|
|того, очень сложно придумать реально значимое задание, алгоритм выполнения |
|которого содержал бы в себе простое прямое следование команд. Даже |
|примитивный пример, взятый из курса математики, как вы увидите, не может |
|быть решен без использования ветвления. Итак, необходимо вычислить значение|
|выражения y=1/x. Вам известно, что данная функция не всегда имеет значение,|
|то есть не для всех значений аргумента существует значение результата. Наша|
|задача так составить алгоритм, чтобы исполнитель ни в коем случае не встал |
|в тупик, даже при получении нуля в качестве аргумента. Сформулировать это |
|на естественном языке не трудно: |
|1. Получить значение x. |
|2. Если x=0, то сообщить, что выражение значения не имеет, иначе - |
|вычислить y как 1/x. |
| Таким образом используется приведенная выше алгоритмическая структура.|
|Она может быть выражена простыми словами: |
| Если {Если выполняется условие} |
| то {то выполнить действие № 1 } |
| иначе {иначе - выполнить действие № 2 } |
|все |
| Как это записать на Паскале? Да точно так же, только по-английски. |
| Формат условного оператора на языке Паскаль: |
| If |
| Then |
| Else ; |
| Обратите внимание на то, что в Then- и Else- части стоит только один |
|оператор. Но что делать, чтобы решить задачу, в которой по выполнению или |
|невыполнению условия нужно совершить не одно, а несколько действий? Здесь |
|приходит на помощь уже известный вам составной оператор. В операторные |
|скобки можно заключить любое количество операторов. |
| Вариант условного оператора в этом случае: |
|If |
|Then Begin end |
|Else Begin < группа операторов 2> end; |
| Знак "точка с запятой" не ставится перед служебным словом Else, но |
|операторы в группах, естественно, отделяются друг от друга этим знаком. |
| Теперь поговорим об условиях. В программах на языке Паскаль условия |
|представляют собой выражения, значением которых является величина |
|логического (Boolean) типа. Это может быть как просто переменная указанного|
|типа, так и сложная последовательность высказываний, связанных логическими |
|операциями. |
| В простых условиях могут применяться знаки операций сравнения: |
|>(больше), =(больше или равно), |
|=(D1*(45-2)) {Значение выражения в левой части больше либо |
|равно значению выражения из правой части} |
| S'ABC' {Значение переменной S не равно строковой константе 'ABC'} |
| Приведем пример решения еще одной задачи: "Из двух чисел выбрать |
|наибольшее". |
| На первый взгляд решение очевидно, но оно не столь тривиально, как |
|кажется. |
|Program Example; |
|Var A,B,C : Real; {A,B - для хранения аргументов, C - результат} |
|Begin |
|Writeln('Введите два числа'); |
|Readln(A,B); {Вводим аргументы с клавиатуры} |
|If A>B Then C:=A Else C:=B; {Если A>B, то результат - A, иначе результат - |
|B} |
|Writeln(C); {Выводим результат на экран} |
|End. |
| Еще один классический пример: "По заданным коэффициентам решить |
|квадратное уравнение". Эта задача сложнее, поэтому перед тем как писать |
|программу составим алгоритм, записав его в виде блок-схемы. |
|Сначала вводим коэффициенты, затем вычисляем дискриминант. Теперь возникает|
|две возможности: либо отсутствие действительных корней в случае |
|отрицательного дискриминанта, либо эти корни можно все-таки вычислить и |
|вывести на экран в случае неотрицательного дискриминанта (случай равенства |
|дискриминанта нулю входит сюда же, корней - два, только они одинаковые J). |
| При записи алгоритма на языке программирования следует учесть, что в |
|ветви "нет" не одно действие, а три, поэтому следует применить составной |
|оператор. Арифметические выражения не забывайте записывать в соответствии с|
|правилами языка Паскаль. В остальном, эта программа не сложнее предыдущей. |
| |
| |
| |
|Program Sq1; |
|Var A, B, C, D, X1, X2 : Real; |
|Begin |
|Writeln ('Введите коэффициенты квадратного уравнения'); |
|Readln (A,B,C); |
|D:=B*B-4*A*C; |
|If D:?); |
| |
|Begin |
| |
|End; |
|Раздел описаний может иметь такие же подразделы, как и раздел описаний |
|основной программы (описание процедур и функций - в том числе). Однако все |
|описанные здесь объекты "видимы" лишь в этой процедуре. Они здесь локальны |
|также, как и имена формальных параметров. Объекты, описанные ранее в |
|разделе описаний основной программы и не переопределенные в процедуре, |
|называются глобальными для этой подпрограммы и доступны для использования. |
|Легко заметить схожесть структуры программы целиком и любой из ее процедур.|
|Действительно, ведь и процедура и основная программа реализуют некий |
|алгоритм, просто процедура не дает решения всей задачи. Отличие в заголовке|
|и в знаке после End. |
|Формат описания функции: |
|Function (:; |
|< Имя форм. параметра 2>:?) : ; |
| |
|Begin |
| |
|End; |
|В теле функции обязательно должна быть хотя бы команда присвоения такого |
|вида: :=; |
|Указанное выражение должно приводить к значению того же типа, что и тип |
|результата функции, описанный выше. |
|Вызов процедуры представляет в программе самостоятельную инструкцию: |
|(, < Фактический параметр 2>?); |
|Типы фактических параметров должны быть такими же, что и у соответсвующих |
|им формальных. |
|Вызов функции должен входить в выражение. При вычислении значения такого |
|выражения функция будет вызвана, действия, находящиеся в ее теле, будут |
|выполнены, в выражение будет подставлено значение результата функции. |
|Приведем простейший пример использования подпрограммы. |
|Задача: "Найти максимальное из трех введенных чисел". Для решения |
|воспользуемся описанием функции, принимающей значение максимального из двух|
|чисел, которые передаются в нее в виде параметров. |
|Program Fn; |
|Var |
|A,B,C :Real; |
|Function Max(A,B:Real):Real; {Описываем функцию Max с формальными} |
|Begin {параметрами A и B, которая принимает } |
|If A>B Then Max:=A {значение максимального из них } |
|Else Max:=B {Здесь A и B - локальные переменные } |
|End; |
|Begin |
|Writeln('Введите три числа'); |
|Readln(A,B,C); |
|Writeln('Максимальным из всех является ', Max(Max(A,B),C)) |
|End. |
|Обратите внимание на краткость тела основной программы и на прозрачность |
|действий внутри функции. Формальные параметры A и B, используемые в |
|подпрограмме, не имеют никакого отношения переменным A и B, описанным в |
|основной программе. |
|Существует два способа передачи фактических параметров в подпрограмму: по |
|значению и по ссылке. В первом случае значение переменной-фактического |
|параметра при вызове подпрограммы присваивается локальной переменной, |
|являющейся формальным параметром подпрограммы. Что бы потом ни происходило |
|с локальной переменной, это никак не отразится на соответствующей |
|глобальной. Для одних задач это благо, но иногда требуется произвести в |
|подпрограмме действия над самими переменными, указанными в качестве |
|фактических параметров. На помощь приходит второй способ. Происходит |
|следующее: при обращении к подпрограмме не происходит формирования |
|локальной переменной-формального параметра. Просто на время выполнения |
|подпрограммы имя этой локальной переменной будет указывать на ту же область|
|памяти, что и имя соответствующей глобальной переменной. Если в этом случае|
|изменить локальную переменную, изменятся данные и в глобальной. |
|Передача параметров по ссылке отличается тем, что при описании подпрограммы|
|перед именем переменной-формального параметра ставится служебное слово Var.|
|Теперь использование в качестве фактических параметров выражений или |
|непосредственных значений уже не допускается - они должны быть именами |
|переменных. |
|Еще один классический пример. Задача: "Расположить в порядке неубывания три|
|целых числа". |
|Program Pr; |
|Var |
| S1,S2,S3 :Integer; |
|Procedure Swap(Var A,B: Integer);{Процедура Swap с параметрами-переменными}|
| |
|Var C : Integer; {C - независимая локальная переменная} |
|Begin |
| C:=A; A:=B; B:=C {Меняем местами содержимое A и B} |
|End; |
|Begin |
|Writeln('Введите три числа'); |
|Readln(S1,S2,S3); |
|If S1>S2 Then Swap(S1,S2); |
|If S2>S3 Then Swap(S2,S3); |
|If S1>S2 Then Swap(S1,S2); |
|Writeln('Числа в порядке неубывания:V',S1,S2,S3) |
|End. |
| |
|Работа с файлами |
|Тип-файл представляет собой последовательность компонент одного типа, |
|расположенных на внешнем устройстве (например, на диске). Элементы могут |
|быть любого типа, за исключением самого типа-файла. Число элементов в файле|
|при описании не объявляется. Работа с физическими файлами происходит через |
|так называемые файловые переменные. |
|Для задания типа-файла следует использовать зарезервированные слова File и |
|Of, после чего указать тип компонент файла. |
|Пример: |
|Type |
|N = File Of Integer; {Тип-файл целых чисел} |
|C = File Of Char; {Тип-файл символов} |
|Есть заранее определенный в Паскале тип файла с именем Text. Файлы этого |
|типа называют текстовыми. |
|Введя файловый тип, можно определить и переменные файлового типа: |
|Var |
|F1 : N; |
|F2 : C; |
|F3 : Text; |
|Тип-файл можно описать и непосредственно при введении файловых переменных: |
|Var |
| Z : File Of Word; |
|Файловые переменные имеют специфическое применение. Над ними нельзя |
|выполнять никаких операций (присваивать значение, сравнивать и т.д.). Их |
|можно использовать лишь для выполнения операций с файлами (чтение, запись и|
|т.д.). |
|Элементы файла считаются расположенными последовательно, то есть так же, |
|как элементы линейного массива. Отличие же состоит в том, что, во-первых, |
|размеры файла могут меняться, во-вторых, способ обращения к элементам |
|совсем другой: невозможно обратиться к произвольному элементу файла; |
|элементы его просматриваются только подряд от начала к концу, при этом в |
|каждый момент времени доступен только один элемент. Можно представить себе,|
|что для каждого файла существует указатель, показывающий в данный момент на|
|определенный компонент файла. После проведения операции чтения или записи |
|указатель автоматически передвигается на следующий компонент. |
|Перед тем, как осуществлять ввод-вывод, файловая переменная должна быть |
|связана с конкретным внешним файлом при помощи процедуры Assign. |
|Формат: |
| Assign(,); |
|Имя файла задается либо строковой константой, либо через переменную типа |
|Sting. Имя файла должно соответствовать правилам работающей в данный момент|
|операционной системы. Если строка имени пустая, то связь файловой |
|переменной осуществляется со стандартным устройством ввода-вывода (как |
|правило - с консолью). |
|После этого файл должен быть открыт одной из процедур: |
|Reset(); |
|Открывается существующий файл для чтения, указатель текущей компоненты |
|файла настраивается на начало файла. Если физического файла, |
|соответствующего файловой переменной не существует, то возникает ситуация |
|ошибки ввода-вывода. |
|Rewrite(); |
|Открывается новый пустой файл для записи, ему присваивается имя, заданное |
|процедурой Assign. Если файл с таким именем уже существует, то он |
|уничтожается. |
|После работы с файлом он, как правило, должен быть закрыт процедурой Close.|
| |
|Close(); |
|Это требование обязательно должно соблюдаться для файла, в который |
|производилась запись. |
|Теперь рассмотрим непосредственную организацию чтения и записи. |
|Для ввода информации из файла, открытого для чтения, используется уже |
|знакомый вам оператор Read. Правда, в его формате и использовании вы |
|заметите некоторые изменения: |
|Read(, ); |
|Происходит считывание данных из файла в переменные, имена которых указаны в|
|списке ввода. Переменные должны быть того же типа, что и компоненты файла. |
| |
|Вывод информации производит, как можно догадаться оператор Write(, ); |
|Данные из списка вывода заносятся в файл, открытый для записи. |
|Для текстовых файлов используются также операторы Readln и Writeln с |
|соответствующими дополнениями, относящимися к файловому вводу-выводу. |
|Любопытно, что вывод данных на монитор и ввод с клавиатуры в языке Паскаль |
|тоже являются действиями с файлами. Они даже имеют свои предопределенные |
|файловые переменные текстового типа: Output и Input соответственно. |
|Переменная Output всегда открыта для записи, Input - для чтения. Если не |
|указывать файловые переменные в операторах ввода-вывода (придем к формату, |
|рассмотренному в теме "Операторы ввода-вывода"), то в случае записи по |
|умолчанию выбирается файл Output, в случае чтения - Input. |
|Как вы знаете, любой файл конечен и продолжать чтение из него информации |
|можно лишь до определенного предела. Как этот предел установить? Проверить,|
|окончен ли файл, можно вызовом стандартной логической функции Eof() |
|Она вырабатывает значение True, если файл окончен, и False - в противном |
|случае. |
|Решим следующую задачу: "Написать программу, которая вводит с клавиатуры |
|список фамилий учащихся, а затем распечатывает его, кроме тех учащихся, у |
|которых фамилия начинается с буквы 'Ш'". |
|Так как заранее количество данных не известно, то для их хранения |
|используем файл. Тип элементов - строковый. |
|Program L; |
|Var |
|I,N : Integer; |
|F : File Of String; |
|S : String; |
|Begin |
|Assign(F,'Spis.lst'); {Связываем переменную F с файлом Spis.lst} |
|Writeln('Введите количество учащихся'); |
|Readln(N); {Вводим количество учащихся} |
|Rewrite(F); {Создаем файл для записи в него данных} |
|For I:=1 To N Do {Для всех учащихся} |
|Begin |
|Writeln('Введите фамилию'); |
|Readln(S); |
|Write(F,S) |
|End; |
|Close(F); |
|Reset(F); |
|Writeln; Writeln('Список учащихся:'); |
|While Not(Eof(F)) Do |
|Begin |
|Read(F,S); |
|If S[1]'Ш' Then |
|Writeln(S) |
|End; |
|Close(F) |
|End. |