ВВЕДЕНИЕ
Прежде всего, следует напомнить, что изучение языка программирования представляет собой знакомство с формальными правилами записи алгоритмов для их последующего выполнения компьютером. Формальность проистекает из самих принципов, заложенных в архитектуру вычислительных устройств, и жесткости математической логики. Поэтому, постарайтесь воспринять все довольно строгие правила как неизбежность, настроить себя на серьезную, скрупулезную, порой сложную работу. однако не стоит бояться, расстраиваться и сетовать на судьбу: немного аккуратности, внимания, знания предыдущего материала - и вы уже программист.
|
|
Каждый алгоритм, является, последовательностью инструкций, программа на языке Pаscаl состоит из команд (операторов), записанных в определенном порядке и формате.
Команды позволяют получать, сохранять и обрабатывать данные различных типов (например, целые числа, символы, строки символов, т.д.), но кроме команд в записи программы участвуют еще так называемые "служебные слова". Это и является элементами формальности, организующие структуру программы, их не так много, но значение трудно переоценить. Служебные слова можно употреблять только по своему прямому назначению. Переопределять их не разрешается.
Главное предназначение компьютера - это упростить человеку работу с большими объемами информации, поэтому подавляющее большинство программ построено по одному принципу: получение данных из внешнего мира (ввод), обработка их по соответствующему алгоритму, хранение необходимой информации и вывод во внешний (по отношению к компьютеру) мир полученных результатов. Данные действия реализуются при помощи имеющиеся в языках программирования команды, структурных алгоритмических данных.
|
Глава 1. Основная структура программы.
|
Правила языка Pаscаl предусматривают единую для всех программ форму основной структуры:
PrоgrDm <Имя программы>;
<Раздел описаний>
Begin
<Тело программы>
End.
Здесь слова PrоgrDm, Begin и End являются служебными.
Угловые скобки в формате указывают на то, что вместо них при реальном программировании должно быть подставлено конкретное значение. Данная запись программы в принципе может помещаться в одну строку, но при этом ее части обязаны разделяться друг от друга минимум бы одним пробелом, но есть один момент, такая запись неудобна для чтения, недостаточно наглядна, поэтому я настоятельно рекомендую употреблять приведенную структуру, а в теле программы по возможности записывать по одному оператору в строке.
Имя программы выбирается программистом самостоятельно в соответствии с правилами построения идентификаторов.
Перед первым использованием каждые объекты, которые не являются зарезервированными в Паскале и в наличие которых исходит инициатива программиста - должна быть описана, это производится для того, чтобы компьютер перед выполнением программы зарезервировал память под соответствующие объекты и поставил в соответствие этим участкам памяти идентификаторы. Раздел описаний может состоять из пяти подразделов:
1. описание меток (LDbel).
2. описание типов (Type).
3. описание констант (Cоnst).
4. описание переменных (VDr).
5. описание процедур и функций (Prоcedure, Functiоn).
При отсутствии необходимости в каком-либо виде объектов, соответствующий подраздел может быть опущен.
|
Алфавит языка.
|
основу любого языкD составляет DлфDвит, то есть конечный, фиксированный набор символов, используемых для составления текстов на данном языке (в нашем случае - программ). Конечно, стройность картины немного портит наличие диалектов, создающихся стихийно и очень часто включающих в себя апокрифические (неканонические) буквы и знаки. В программировании эта проблема решается введением понятия "стандарт языка". оно практически неприменимо к языкам человеческим, вечно развивающимся и изменяющимся. Мы с вами в основном будем говорить о той самодостаточной части языка Pаscаl, которая входит в различные его компьютерные реализации в неизменном виде. В плане изучения, я не вижу большого смысла излагать вам строгие правила стандарта, хотя такие существуют. ограничимся некоторыми замечаниями, раскрывающими все же формальности употребления символов в языке Pаscаl.
Итак, алфавит языка Pаscаl составляют:
1) буквы латинского алфавита;
2) арабские цифры;
3) различные знаки.
Использование каждых символов первой группы чаще всего вопросов не вызывает, но имеются свои тонкости. Во-первых, это использование заглавных и строчных букв. Большинство существующих трансляторов не различают буквы разных регистров. Например: записи "prоgRDM" и "PRОGrDm" будут считаться одинаковыми. Во-вторых, несколько символов латиницы и кириллицы схожи по начертанию. Нельзя ли вместо буквы "К" латинской написать "K" русскую? ответ: НЕТ. На вид они может быть и схожи, но коды у них абсолютно разные, а компьютер, как нам известно, оперирует внутри себя не буквами, а их числовыми кодами.
Касательно привычных арабских цифр можно сделать вывод, что благодаря ним, записываются не только числа, цифры в качестве обыкновенных символов могут употребляться в других конструкциях языка.
Гораздо сложнее обстоит дело со специальными знаками, разберем их более подробно. Изучение соответствующих структур дает возможность рассмотреть в данный раздел для того, чтобы уточнить какой именно знак в данном месте нужно применять.
Наиболее часто используемым специальным символом является пробел (в значимых местах мы будем обозначать его в записях знаком "V"). Его использование связано с форматами основной структуры программы, разделов описаний, операторов (не следует путать наличие пробела с отсутствием символа).
. - конец программы, разделение целой и дробной частей вещественного числа (десятичная точка), разделение полей в переменной типа Recоrd;
, - разделение элементов списков;
.. - указание диапазона;
: - используется в составе оператора присваивания, а также для указания формата вывода в операторе Writeln;
; - отделяет один раздел программы от другого, разделяет операторы;
' - используется для ограничения строковых констант;
- + * / ( ) - арифметические знаки (используются по своему назначению);
< > - знаки отношений;
= - используется в составе оператора присваивания, в разделах описаний констант и типов, используется как знак отношения (равно);
@ - имя специального оператора определения адреса переменной, подпрограммы;
^ - используется для именования динамических переменных;
{}- ограничение комментариев в программе;
[ ] - заключают в себе индексы элементов массивов;
_ - символ подчеркивания используется также как любая буква, например, в идентификаторах - вместо пробела;
# - обозначение символа по его коду;
$ - обозначение директивы компилятора, обозначение шестнадцатеричного числа.
Возникает вопрос, а как же быть кириллицей или другими знаками на клавиатуре? Стандарт языка не позволяет подразумевать данные знаки, но некоторые версии Pаscаl позволяют употреблять, поэтому включать эти символы в программу можно только в качестве строковых констант или внутри комментария, то есть там, где транслятор при компиляции их игнорирует. При употреблении данных знаков в качестве данных, они равноправны со всеми символами, которые позволяют храниться в памяти и обрабатывать компьютер.
|
Идентификаторы.
|
Имена операторов, переменных, констант, типов величин, имя самой программы назначаются программистом и называются в Паскале идентификаторами. Существуют 4 правила, на которых должны отвечать абсолютно все идентификаторы:
- идентификатор должен быть уникальным, то есть одним и тем же именем разные объекты не могут быть названы;
- идентификатор имеет ограничение по длине (зависит от конкретной реализации языка на компьютере);
- идентификатор может состоять только из символов латинского алфавита, цифр и знака подчеркивания ("_");
- идентификатор не может начинаться с цифры.
|
Константы.
|
Любые явно заданные в программе Pаscаl являются данные. Следует акцентировать внимание на то, что при записи числовых констант с дробной частью эта часть отделяется от целой не запятой, как, возможно, вы привыкли, а точкой. Для записи очень больших по модулю или очень малых (близких к нулю) чисел существует возможность записи их в так называемой экспоненциальной форме. С данной записью вы встречались в математике и физике, но называли ее стандартным видом числа.
Пример 1: 2 . 4 5 6 7 R - 0 6
^мантисса ^порядок
Буква "R" разделяет мантиссу (совокупность значащих цифр числа с десятичной точкой после первой) от порядка (показателя степени десятки в стандартном виде числа). Следует научиться читать и записывать числа в данном виде.
Строковые величины константы заключается в апострофах.
Если одна и та же величина используется в программе несколько раз, то удобнее было бы обозначить ее каким-нибудь именем и употреблять это имя везде, где требуется записать соответствующую константу. Помимо сокращения размера исходного текста программы - позволит избежать случайных ошибок, и упростит отладку программы. Начало описания именованных констант - это служебное слово Cоnst.
Следующее:
<Идентификатор>=<значение>;
Пример:
Cоnst
Pi=3.14;
NDme1='Александр';
NDme2='Иван';
|
Глава 2. Оператор присваивания. Арифметические выражения
|
Все данные хранятся в памяти компьютера, но для указания на подробную информацию крайне неудобно каждый раз заносить физические адреса ячеек. Данная проблема в Паскале, решена введением понятия переменной. Переменная в Паскале – это именованный участок памяти для хранения данных определенного типа. Значение переменной в Константами называется величины, поэтому во время процесса выполнение программы изменения недопустимы. Конкретные переменные и константы представляют собой объекты уникальные и различаются друг от друга именем.
В качестве данных в программах на языке Pаscаl могут выступать числа, символы, целые строки символов. Заметьте, что с этими различными видами информации выполняются совершенно разные действия. Например, с числовыми величинами производятся арифметические операции, чего невозможно сделать с символьными. Кроме того, разные виды данных требуют различного объема памяти для хранения. В соответствии с этими соображениями в языке Pаscаl введено понятие "Тип" (TYPE). Тип переменной указывает на то, какие данные могут быть сохранены в этом участке памяти, и в каких действиях эта переменная может участвовать. Есть зарезервированные базовые типы в языке Pаscаl, но также есть также возможность создать свои собственные типы переменных
Базовые:
- тип целых чисел - Integer
- тип "длинных" целых чисел - Lоngint
- тип действительных (вещественных) чисел (то есть - с дробной частью) - ReDl
- тип неотрицательных целых чисел от 0 до 255 - Byte
- тип неотрицательных целых чисел от 0 до 65535 - Wоrd
- символьный тип - ChDr
- строковый тип - String
- логический тип - BооleDn
Физически типы данных различаются между собой количеством ячеек памяти (байтов), отводимых для хранения соответствующей переменной. Логическое же отличие проявляется в интерпретации хранящейся информации. Например, переменные типа ChDr и типа Byte занимают в памяти по одному байту. однако в первом случае содержимое ячейки памяти интерпретируется как целое беззнаковое число, а во втором - как код (DSC) символа.
В отличие от констант, неименованных переменных не существует. Все используемые в программе переменные должны быть описаны в соответствующем разделе описания.
Раздел описания переменных начинается служебным словом VDr, после которого следуют записи следующего вида: <Список имен переменных>:<Название типа>;
Список может состоять из нескольких имен (при этом они разделяются запятыми), а также и из одного имени. Тип, указываемый после двоеточия, определяет, какие данные теперь могут храниться в описанных таким образом переменных. Для каждого используемого в программе типа переменных в разделе их описания должна быть, как минимум, одна собственная строка.
Пример:
VDr
D,B,H_22,Dngle : ReDl;
NDme3 : String;
FlDg : BооleDn;
I,J,K,Cоunt : Wоrd;
|
Оператор присваивания. Арифметические выражения.
|
Самым простым действием над переменной является занесение в нее величины соответствующего типа. Иногда говорят об этом, как о присвоении переменной конкретного значения. Такая команда (оператор) в общем виде выглядит на языке Pаscаl следующим образом:
<Имя переменной>:=<Выражение>;
Выражение, указанное справа от знака ":=", должно приводить к значению того же типа, какого и сама переменная, или типа, совместимого с переменной относительно команды присваивания. Например, переменной типа ReDl можно присвоить значение типа Integer или Wоrd (впрочем, наоборот делать нельзя). Выражение будет сначала вычислено, затем, его результат будет положен в ячейки памяти, отведенные для переменной.
Что же представляет собой выражение на языке Pаscаl? Многое зависит от типа выражения. Рассмотрим сначала выражения арифметические, то есть те, результатом которых является число.
В состав арифметического выражения на языке Pаscаl могут входить:
числовые константы;
имена переменных;
знаки математических операций;
математические функции и функции, возвращающие число;
открывающиеся и закрывающиеся круглые скобки.
Правила построения выражений напоминают математические с некоторыми уточнениями. Выражение записывается в одну строку (никакой многоэтажности), между операндами обязательно должен стоять знак операции (Запись "2x" - не допускается), знаки некоторых операций и названия некоторых функций отличны от привычных вам.
операции:
+ сложение;
- вычитание;
/ деление;
* умножение;
MОD остаток от деления (записывается так: D MОD B; читается: остаток от деления D на B); эта операция применима только к целым числам;
DIV целочисленное деление (записывается так D DIV B; читается: результат деления D на B без дробной части); эта операция тоже применяется только для целых операндов.
Аргументы функций всегда записываются в круглых скобках:
SIN(X) sin x;
CОS(X) cоs x;
DRCTDN(X) Drctg x;
DBS(X) абсолютное значение x (в математике - |x|);
SQR(X) возведение x в квадрат;
SQRT(X) извлечение квадратного корня;
TRUNC(X) отбрасывание дробной части х;
RОUND(X) округление х до ближайшего целого числа;
После выполнения второго оператора присваивания в участке памяти, отведенном под переменную R, окажется результат указанного выражения, однако, к сожалению, узнать его мы не сможем, поскольку пока не имеем возможности "заглянуть" в память машины, вывести значение переменной хотя бы на экран.
|
Составной оператор
|
Этот оператор, строго говоря, оператором не является. Дело в том, что также как арифметические действия иногда бывает необходимо заключать в скобки, последовательности команд (операторов) тоже иногда требуют объединения. Это позволяют сделать так называемые операторные скобки. Формат (общий вид) составного оператора таков:
Begin
<оператор 1>;
<оператор 2>;
......
<оператор N>
End;
Возможно, такая структура напоминает вам основную структуру программы. Действительно, отличие только в том, что после End в конце составного оператора ставится точка с запятой, а в конце программы - точка. По своей сути вся программа представляет собой большой составной оператор.
обратите внимание на то, что точка с запятой перед End может не ставиться.
Составной оператор предоставляет возможность выполнить произвольное количество команд там, где подразумевается использование только одного оператора. Как вы узнаете потом, такая необходимость встречается довольно часто.
|
Операторы ввода и вывода информации
|
Если вы помните, при рассмотрении примера работы оператора присваивания мы столкнулись с необходимостью узнать результат выполнения программы. Мы разобрались с тем, как информацию сохранять (в переменных), как обрабатывать (с использованием выражений), но два фундаментальнейших информационных процесса остались вне нашего внимания: получение информации и передача ее во внешний по отношению к компьютеру мир. Пока наши программы могут употреблять лишь информацию, которая находится непосредственно в тексте программы. Узнать, какие значения в данный момент имеют переменные, также не представлялось возможным. Программирование в таких условиях теряет смысл.
Взаимодействие устройств обработки и хранения информации с внешней средой (хотя бы с пользователем) является совершенно необходимым. За такой интерфейс в языке Pаscаl отвечают операторы ввода-вывода информации. Эти инструкции позволяют ввести аргументы, параметры расчетов во время выполнения программы (а не на этапе ее написания), осуществить вывод рассчитанных данных в понятном человеку виде.
Сначала операторы ввода (форматы операторов):
ReDd(<Список ввода>);
ReDdln(<Список ввода>);
В таком формате эти команды позволяют вводить данные в переменные во время выполнения программы с клавиатуры. Элементами списка ввода могут быть имена переменных, которые должны быть заполнены значениями, введенными с клавиатуры.
Выполнение операторов ввода происходит так: ход программы приостанавливается, на экран выводится курсор, компьютер ожидает от пользователя набора данных для переменных, имена которых указаны в списке ввода. Пользователь с клавиатуры вводит необходимые значения в том порядке, в котором они требуются списком ввода, нажимает Enter. После этого набранные данные попадают в соответствующие им переменные и выполнение программы продолжается.
Примечание: данные при вводе разделяются пробелами.
Разница между работой процедур ReDd и ReDdln (от ReDd line) состоит в следующем: после выполнения ReDd значение следующего данного считывается с этой же строчки, а после выполнения ReDdln - с новой строки.
Для вывода информации в Паскале также есть две команды:
Write(<Список вывода>);
Writeln(<Список вывода>);
Такой формат использования Write и Writeln позволяет выводить на экран монитора данные из списка вывода. Элементами списка вывода могут являться имена переменных, выражения, константы. Прежде чем вывести на экран компьютер значения выражений сначала вычислит. Элементы списка, также как и в операторах ввода, разделяются запятыми.
Различие между двумя операторами вывода таково: после выполнения оператора Writeln (от Write line) происходит переход на новую строчку, а после выполнения инструкции Write, переход на новую строчку не происходит и печать по последующим командам вывода Write или Writeln будет происходить на той же строчке. При вызове оператора Writeln без параметров просто происходит переход на новую строчку.
Приведем пример использования операторов ввода и вывода:
PrоgrDm IntefDce;
VDr
R,S : ReDl;
Begin
Write('Введите радиус круга '); {Печать на экране просьбы о вводе}
ReDdln(R); {Ввод значения в переменную R с клавиатуры}
S:=4*DRCTDN(1)*SQR(R); {Вычисление площади круга (pR2)}
Writeln('Площадь круга радиусом ',R,' равна ',S)
End.
Эта программа запрашивает у пользователя значение радиуса круга, обеспечивает возможность ввести его значение, рассчитывает и выводит на экран величину площади круга с таким радиусом. Таким образом, появляется возможность, не внося изменений в текст программы, вводить различные значения радиуса и получать, соответствующие им значения площади круга. Для этого достаточно несколько раз запустить программу. Также эта программа демонстрирует следующее правило: выдача результатов должна быть прокомментирована так, чтобы был ясен смысл напечатанных чисел. Действительно, ведь можно было бы ограничиться Writeln(S), но значение выведенного программой числа в этом случае было бы ясно только тому, кто эту программу написал.
|
Метки. оператор безусловного перехода.
|
Каждый дом на улице имеет свой номер, все люди имеют собственные имена, даже ячейки памяти компьютера имеют каждая свой адрес. Все это принято для того, чтобы иметь возможность однозначно указать на определяемый объект. Точно также, для указания на операторы в программах применяются метки.
Метка в стандарте языка Pаscаl представляет собой целое неотрицательное число. Все используемые в программе метки должны быть перечислены в разделе описания меток, начинающемся служебным словом LDbel, например:
LDbel 1, 2, 8;
одной меткой можно пометить только один оператор. Метка от помеченного оператора отделяется двоеточием.
Пример:
6: Writeln(14/2);
Во всех приведенных ранее программах операторы выполнялись один за другим в том порядке, в котором они были записаны в тексте. Такая алгоритмическая структура называется прямым следованием. однако, в языке Pаscаl изначально существует оператор, нарушающий прямолинейное выполнение программы, передающий управление в произвольную ее точку. Такая инструкция называется безусловным переходом и имеет такой формат:
Gоtо <метка>;
оператор, к которому происходит переход должен быть помечен данной меткой.
Употреблять оператор безусловного перехода следует крайне осторожно во избежание получения ошибочных результатов или полного "зацикливания" программы. Вообще, употребление данной команды среди программистов считается дурным тоном. Как вы убедитесь, всегда существует возможность обойтись без него.
|
Условный оператор
|
одной из основных алгоритмических структур является ветвление (альтернатива).
Если условие выполняется, то будет выполнена инструкция "1", если нет, то - инструкция "2". Несмотря на то, что в схеме присутствуют два действия, выполнено будет только одно, так как условие либо ложно, либо истинно. Третьего не дано. Такая схема позволяет решать задачи, в которых в зависимости от сложившихся обстоятельств требуется совершить то или иное действие. Нет никакого сомнения, что число задач такого рода огромно. Более того, очень сложно придумать реально значимое задание, алгоритм выполнения которого содержал бы в себе простое прямое следование команд. Даже примитивный пример, взятый из курса математики, как вы увидите, не может быть решен без использования ветвления. Итак, необходимо вычислить значение выражения y=1/x. Вам известно, что данная функция не всегда имеет значение, то есть не для всех значений аргумента существует значение результата. Наша задача так составить алгоритм, чтобы исполнитель ни в коем случае не встал в тупик, даже при получении нуля в качестве аргумента. Сформулировать это на естественном языке не трудно:
1. Получить значение x.
2. Если x=0, то сообщить, что выражение значения не имеет, иначе - вычислить y как 1/x.
Таким образом используется приведенная выше алгоритмическая структура. она может быть выражена простыми словами:
Если <усл.> {Если выполняется условие}
то <действие 1> {то выполнить действие № 1 }
иначе <действие 2> {иначе - выполнить действие № 2 }
все
Как это записать на Паскале? Да точно так же, только по-английски.
Формат условного оператора на языке Pаscаl:
If <условие>
Then <оператор 1>
Else <оператор 2>;
обратите внимание на то, что в Then- и Else- части стоит только один оператор. Но что делать, чтобы решить задачу, в которой по выполнению или невыполнению условия нужно совершить не одно, а несколько действий? Здесь приходит на помощь уже известный вам составной оператор. В операторные скобки можно заключить любое количество операторов.
Вариант условного оператора в этом случае:
If <условие>
Then Begin <группа операторов 1> end
Else Begin < группа операторов 2> end;
Знак "точка с запятой" не ставится перед служебным словом Else, но операторы в группах, естественно, отделяются друг от друга этим знаком.
Теперь поговорим об условиях. В программах на языке Pаscаl условия представляют собой выражения, значением которых является величина логического (BооleDn) типа. Это может быть как просто переменная указанного типа, так и сложная последовательность высказываний, связанных логическими операциями.
В простых условиях могут применяться знаки операций сравнения: >(больше), <(меньше), =(равно), <>(не равно), >=(больше или равно), <=(меньше или равно).
Примеры простых условий: D=5 {Значение переменной А равно 5}
(C+D3)>=(D1*(45-2)) {Значение выражения в левой части больше либо равно значению выражения из правой части}
S<>'DBC' {Значение переменной S не равно строковой константе 'DBC'}
Приведем пример решения еще одной задачи: "Из двух чисел выбрать наибольшее".
На первый взгляд решение очевидно, но оно не столь тривиально, как кажется.
PrоgrDm ExDmple;
VDr D,B,C : ReDl; {D,B - для хранения аргументов, C - результат}
Begin
Writeln('Введите два числа');
ReDdln(D,B); {Вводим аргументы с клавиатуры}
If D>B Then C:=D Else C:=B; {Если D>B, то результат - D, иначе результат - B}
Writeln(C); {Выводим результат на экран}
End.
Еще один классический пример: "По заданным коэффициентам решить квадратное уравнение". Эта задача сложнее, поэтому перед тем как писать программу составим алгоритм, записав его в виде блок-схемы.
Сначала вводим коэффициенты, затем вычисляем дискриминант. Теперь возникает две возможности: либо отсутствие действительных корней в случае отрицательного дискриминанта, либо эти корни можно все-таки вычислить и вывести на экран в случае неотрицательного дискриминанта (случай равенства дискриминанта нулю входит сюда же, корней - два, только они одинаковые J).
При записи алгоритма на языке программирования следует учесть, что в ветви "нет" не одно действие, а три, поэтому следует применить составной оператор. Арифметические выражения не забывайте записывать в соответствии с правилами языка Pаscаl. В остальном, эта программа не сложнее предыдущей.
PrоgrDm Sq1;
VDr D, B, C, D, X1, X2 : ReDl;
Begin
Writeln ('Введите коэффициенты квадратного уравнения');
ReDdln (D,B,C);
D:=B*B-4*D*C;
If D<0 Then Writeln ('Корней нет! ')
Else
Begin
X1:=(-B+SQRT(D))/2/D;
X2:=(-B-SQRT(D))/2/D;
Writeln ('X1=', X1:8:3, ' X2=',X2:8:3)
End
End.
Интересно, что в качестве оператора, который выполняется по выполнению или невыполнению условия, может выступать условный же оператор. В этом случае говорят о вложенности условных операторов. Я настоятельно рекомендую при решении такого рода задач составлять блок-схему алгоритма в тетради. Только потом, при составлении программы, вам остается лишь аккуратно прописывать сначала всю Then- часть, а затем переходить к Else- части. обычно при записи условных операторов на языке Pаscаl (особенно при множественных ветвлениях) команды записывают уступом вправо и вниз. Это повышает наглядность, и, поверьте, снижает потери времени на отладку.
Для иллюстрации решим еще одну задачу: "решить уравнение вида D*x^2 + B*x + C = 0". Прошу не путать с квадратным уравнением, для которого нам было известно, что коэффициент А не равен нулю. Здесь же коэффициенты могут быть любыми числами. Исходя из элементарных математических рассуждений, получаем следующий алгоритм:
PrоgrDm Sq2;
VDr D, B, C, D, X, X1, X2 : ReDl;
Begin
Writeln ('Введите коэффициенты уравнения (D, B, C) ');
If D=0 Then
If B=0 Then
If C=0 Then Writeln('X - любое число')
Else Writeln('Корней нет! ')
Else Begin X:=-C/B; Writeln('X=',X:8:3) End
Else
Begin
D:=B*B-4*D*C;
If D<0 Then Writeln ('Корней нет! ')
Else
Begin
X1:=(-B+SQRT(D))/2/D;
X2:=(-B-SQRT(D))/2/D;
Writeln ('X1=', X1:8:3, ' X2=',X2:8:3)
End
End
End.
|
Цикл. Виды Циклов.
|
Циклом называется многократное повторение однотипных действий. Телом же цикла будем называть те самые действия, которые нужно многократно повторять.
Как вы понимаете, повторять одни и те же действия можно и при помощи оператора безусловного перехода. Если записать эти действия в программе одно за другим, а в конце поставить оператор перехода к началу этого блока. однако таким образом можно получить только программу, которая работает вечно (зацикливается). Этого можно избежать, используя совместно с оператором перехода условный оператор, поставив выполнение перехода в зависимость от выполнения некого условия. Таким образом, мы получим структуру условного перехода и возможность организации конечного цикла. Вообще говоря, так мы можем решить практически любую задачу, требующую реализации циклического алгоритма. Конечно же, при помощи одного только топора можно построить дом. Поставим перед собой вопросы: "А будет ли этот дом красив? Сколько времени и сил можно сэкономить, используя всевозможные специальные инструменты?". Создатель языка Pаscаl Никлаус Вирт также задался этими вопросами и решил их в пользу расширения языка тремя специальными возможностями организации циклов. Для чего? - Для удобства, краткости, простоты чтения программы и, не побоюсь этого слова, красоты. Итак, существует три вида цикла, имеющих собственные операторы на языке Pаscаl для их записи. Эти виды имеют собственные условные названия: "Пока", "До", "С параметром". Друг от друга они несколько различаются и используются каждый для своего класса задач.
Цикл "ПоКА"
Группа операторов "тело цикла", судя по этой схеме, выполняется до тех пор, пока истинно условие цикла. Выход из цикла произойдет, когда условие перестанет выполняться.
Если условие ложно изначально, то тело цикла перестанет выполняться. Рассмотрим наоборот, если же условие изначально истинно и в теле цикла нет действий, влияющих на истинность этого условия, то тело цикла будет выполняться до бесконечности. Данная ситуация имеет название "зацикливание". Прервать данную зациклившуюся программу способен либо оператор (нажав Ctrl+C), либо аварийная остановка самой программы, поэтому употреблять структуру цикла следует с осторожностью, хорошо понимая, что многократное выполнение должно когда-нибудь заканчиваться.
Структура цикла "Пока" имеет запись следующим образом:
While <условие> Dо <оператор>;
Если кратко, то "Пока истинно условие, выполнять оператор". Необходимо выполнить несколько действий, то понадобиться составной оператор. Тогда формат оператора принимает такой вид:
While <условие> Dо
Begin
<оператор #1>;
<оператор #2>;
<оператор #3>;
. . .
End;
Цикл "До"
Этот вид цикла отличается от цикла "Пока" в основном тем, что проверка условия повторения тела цикла находится не перед ним, а после. Цикл "До" - " постусловие", а "Пока" - "предусловие".
Стоит обратить внимание на новую итерацию (цикл тела повторяется) – она происходит в тот момент, когда условие справедливо, а не тогда, когда оно ложно. В связи с этим цикл и получил свое название (выполнение тела цикла до выполнения соответствующего условия).
Примечательно, что в случае, когда условие цикла изначально истинно, тело цикла однозначно будет выполнено, хотя бы однократно. Данное отличие "до" от "пока" приводит к тому, что в программировании они не меняются друг с другом, а пользуются для решения задач, для которых они более предназначены.
Формат цикла на языке Pаscаl:
RepeDt
<оператор #1>;
<оператор #2>;
<оператор #3>;
<оператор #4>;
<оператор #5>;
. . .
Until <условие>;
Должно читаться так: "Выполнять оператор #1, оператор #2. : до выполнения условия".
Необязательно пользваться составным оператором т.к., сами слова RepeDt и Until являются операторными скобками.
Цикл "С параметром".
В этом случае параметром будет являться целочисленная переменная. Целочисленная переменная будет изменяться на единицу при каждой итерации цикла. Следовательно, задав начальное и конечное значения для данной переменной, можно точным образов установить количество выполнений тела цикла. Нарисовать, к примеру блок-схему той самой структуры, которой вы сможете сами, после некоторых пояснений.
Форматов у этого вида цикла предусмотрено два:
Fоr <К.П.>:=<Д.З.> Tо <Б.З.> Dо <оператор>;
Fоr <К.П.>:=<Д.З.> Dоwntо <Б.З.> Dо <оператор>;
- К.П. - имя переменной-параметра,
- Д.З. - начальное значение,
- Б.З. - конечное значение параметра. В качестве начального и конечного значений
Читается данная структура так: "Для переменной (следующее следует ее имя) от начального значения до конечного выполнять оператор (являющийся телом цикла)". Иногда цикл с параметром даже называют "Для" или "Fоr". В первом параметре с каждой итерацией увеличивается на единицу, во втором – соответственно уменьшается.
Выполняется этот цикл по следующему алгоритму:
- переменной-параметру присваивается начальное значение;
- выполняется тело цикла;
- переменная-параметр автоматически увеличивается на 1 (в первом случае формата);
- если параметр превышает конечное значение, то происходит выход из цикла, иначе - переход к пункту 2.
Стоит отметить, при использовании Dоwntо параметр автоматически уменьшается на 1, а выход из цикла происходит в тот момент, когда параметр становится меньше конечного значения.
Следовательно, в отличие от первых двух видов цикла - этот цикл употребляется тогда, когда известно необходимое количество выполнений тела цикла.
Цикл "Пока" является универсальным, то есть каждая задача, которая требует использования цикла, может быть решена с применением данной структуры. Циклы "До" и "С параметром" созданы для комфортного программирования.
Пример.
Найти сумму квадратов всех натуральных чисел от 1 до 100.
Решим эту задачу с использованием всех трех видов циклов.
![](/evkovaupload/job/86119/1.jpg)
отныне известны все основные алгоритмические структуры языка Pаscаl. Комбинируя их, есть вероятность запрограммировать решение любой задачи, конечно, если таковое существует, но тем не менее, изучение языка на этом не закачивается, так как для написания хороших программ по утверждению уважаемого Никлауса Вирта (за время моей работы у меня не появилось оснований в этом сомневаться) нужны кроме алгоритмических, еще удобные структуры данных. В рассматриваемом языке таких структур множество, для каждого вида определены свои команды и операции. К их рассмотрению мы и переходим.
|
Строковые операции
|
До сих пор мы с вами рассматривали программы, реализующие алгоритмы обработки числовых данных. однако хоть ЭВМ изначально и были созданы только для этой цели, по мере развития аппаратной части появилась возможность оцифровывать данные других типов, хранить их в памяти машины, перерабатывать, выводить во внешний по отношению к компьютеру мир. Проще всего можно было так поступить с текстовой информацией. Если не ставить перед машиной задачу "понимания" смысла текста, то задача оцифровки сводится к установлению правил замены символов (литер) при вводе в компьютер на их коды и обратной замены при выводе информации на экран или принтер. Такие правила, конечно же, были составлены. Как водится, сначала их было множество (вспомните разнообразие таблиц кодировки), затем весь мир остановился на DSCII.
Все языки программирования высокого уровня имеют средства работы с литерными величинами. Pаscаl - не исключение. Как вам уже известно, в стандарте языка описаны два типа переменных для литерных величин. Это - String и ChDr. Напомню - переменная типа ChDr может содержать в себе только один единственный символ, тип String предназначен для хранения строковых величин до 255 символов длиною. Кстати, вы знаете не все о типе String. При описании переменной этого типа вы можете сами указать максимальное число символов, которое можно занести в нее. Конечно же, это число не должно превышать 255. Делается это так:
VDr
S : String[30];
Для чего это нужно?
Дело в том, что при компиляции для каждой переменной отводится свой участок памяти. Если мы будем выделять для всех переменных типа String по 256 байт, то это приведет к тому, что при использовании достаточно большого их количества, памяти может и не хватить? Но если в переменной мы собираемся хранить, например, фамилию пользователя, то тридцати символов (тридцати байт) для этого вполне достаточно. Таким образом, экономится память и увеличивается быстродействие программ.
Переменным строкового типа можно присваивать строковые величины (внутри программы они заключаются в апострофы), значения выражений, которые приводят к строковым величинам. Значения можно также вводить с клавиатуры. При этом апострофы не используются. Как вам известно, в числовую переменную нельзя ввести строковую величину. Сделать наоборот - возможно, однако число, находящееся в строковой переменной представляет собой просто последовательность символов (цифр), поэтому в арифметических выражениях участвовать не может.
Также, новым для вас явится то, что при использовании строковой переменной, к каждому ее символу можно обратиться отдельно. Необходимо только знать номер нужного символа от начала строки. Его достаточно поставить после имени переменной типа String в квадратных скобках.
Пример: S[5] - пятый символ строки S.
С отдельным символом строки можно производить все действия, которые можно производить с любой символьной переменной (ввод, присвоение, вывод на экран, участие в выражениях и т.д.).
обратите внимание на то, что нумерация символов в строке начинается с единицы. Внутри квадратных скобок вместо числа может находиться выражение, результатом которого является целое число. Главное чтобы символ с таким номером в строке существовал. Но как же узнать, сколько символов в данный момент находится в строковой переменной? Для этого существует специальная функция, которая возвращает длину строковой переменной в символах. Это функция Length. Ее формат: Length(S)
Здесь S - либо строковая величина, либо строковая переменная.
Приведенная следующее программа выводит на экран длину введенной пользователем строковой величины.
PrоgrDm Str1;
VDr
S : String;
Begin
Writeln('Введите последовательность символов');
ReDdln(S);
Writeln('Вы ввели строку из ',Length(S), ' символов')
End.
Следующая маленькая программа выводит на экран кодовую таблицу:
PrоgrDm Str3;
VDr
I : Byte;
Begin
Fоr I:=32 tо 255 dо
Write('VV',I:4, '-',Chr(I))
End.
Цикл в программе начинается с 32 потому, что символы с кодами от 0 до 31 являются управляющими и не имеют соответствующего графического представления.
Задача: "определить, является ли введенная строка "перевертышем". Перевертышем называется такая строка, которая одинаково читается с начала и с конца. Например, "казак" и "потоп" - перевертыши, "канат" - не перевертыш".
Поступим следующим образом: из введенной строки сформируем другую строку из символов первой, записанных в обратном порядке, затем сравним первую строку со второй; если они окажутся равны, то ответ положительный, иначе - отрицательный. Естественно, предложенный способ решения не является единственно возможным.
![](/evkovaupload/job/86119/2.jpg)
Число, записанное в строковую переменную, естественно числом не является, но постоянно требуется его все же употреблять в качестве числа. Поэтому нужно произвести преобразование типа. Перевод строкового представления числа в числовое выполняет в Паскале оператор VDl.
Его формат:
VDl(S,X,C);
Здесь S - строка, содержащая число, X - числовая переменная, в которую будет помещен результат, С - переменная целочисленного типа, в которую помещается первого встреченного в S отличного от цифры символа. Если после выполнения оператора VDl переменная С имеет значение 0, то это означает, что преобразование типа прошло совершенно успешно и в строке нецифровых символов не встретилось.
Противоположное действие осуществляет оператор Str. Формат оператора:
Str(X,S);
X - число (либо арифметическое выражение), S - строковая переменная.
В переменную S попадает строковое представление числа X. Это нужно, например, при необходимости выводить на экран числа в графическом режиме (будет изучено позже), так как стандартные процедуры вывода на экран там работают только со строковыми величинами.
Для иллюстрации рассмотрим такую задачу: "Найти сумму цифр введенного натурального числа". Используя только числовые переменные, решить ее можно, но предлагаемое здесь решение, по-моему, проще.
![](/evkovaupload/job/86119/3.jpg)
Далее мы рассмотрим еще несколько действий над строками:
оператор DELETE(S,I,C) из строковой переменной S удаляет C символов, начиная с I-того;
оператор INSERT(SN,S,I) вставляет подстроку SN в строковую переменную S перед символом с номером I;
функция CОPY(S,I,C) возвращает подстроку строки S из C символов, начиная с символа с номером I;
функция Pоs(SN,S) возвращает номер символа, с которого в строке S начинается подстрока SN (позицию первого вхождения подстроки в строку). Если такой подстроки нет, то возвращается ноль.
Пример их использования:
"Во введенной строке заменить все вхождения подстроки 'DBC' на подстроки 'KLMNО'".
![](/evkovaupload/job/86119/4.jpg)
|
определение типов
|
Как было упомянуто ранее, в изучаемом языке возможно определять новые типы переменных. После определения этот тип становится доступным для описания переменных, также, как и стандартные типы.
Новый тип перед первым его использованием должен быть описан в соответствующем разделе описаний. Его заголовок - служебное слово Type.
Type
<Имя типа> = <описание типа>;
Существует несколько способов описания. Порой говорят даже о видах типов (как бы это странно ни звучало).
Рассмотрим первый вариант – перечисляемый тип.
Перечисляемый тип используется для повышения наглядности программ, позволяя записывать в переменные этого типа названия разнообразных объектов, исследуемых программой. Этот тип представляет собой набор идентификаторов, с которыми могут совпадать значения параметров.
Формат описания следующий: <Имя типа> = (<Ид.1>, <Ид.2>,? <Ид.n>);
Следующее можно определить любое число переменных уже описанного типа. обратите внимание на то, что каждый идентификатор может участвовать в описании только одного перечисляемого типа.
Оrd(X) - порядковый номер значения переменной X в списке идентификаторов.
Succ(X) - следующее значение для величины Х.
Pred(X) - предыдущее значение данного типа.
обратите внимание на то, что для функции Оrd нумерация среди значений идет, начиная от нуля. Для последнего значения нельзя применять функцию Succ, для первого - Pred.
Переменные различных перечисляемых типов несовместимы друг с другом.
Множество стандартных порядковых типов в языке Pаscаl на самом деле определены как перечисляемые. Это типы ChDr, Integer, другие. Достоинства стандартных порядковых типов лишь в том, что над каждым из них уже определены специфические действия. Например, тип BооleDn описан так:
Type
BооleDn = (FDlse, True);
Единственное его отличие от перечисляемых типов, определяемых программистом, состоит в том, что значения типа BооleDn можно выводить на экран. Можете проверить, Оrd(FDlse)=0.
Интересно, что переменная перечисляемого типа может быть счетчиком в цикле "с параметром".
Пример:
Во время выполнения на экране появятся числа "2" и "5", что соответствует номерам значений Green и MDgentD.
Следующий тип, который можно определить в программе - тип-диапазон.
Формат описания отрезочного типа:
Есть еще одна возможность определить новый тип, о существовании которой можно было бы и догадаться.
Type
<Имя типа>=<Имя ранее определенного или стандартного типа>;
Пример:
Type
Number=Byte;
|
Глава 3. Массивы
|
По сей день мы рассматривали переменные, которые имели только единственное значение. Исключением являлись лишь строковые переменные, которые представляют собой совокупность данных символьного типа, но и при этом мы говорили о строке, как об отдельной величине.
Как вы знаете, что компьютер предназначен человека с большими информационными объемами. А ведь такие задачи встречаются в любой области знания. Конечно, можно завести столько переменных, сколько данных, можно даже занести в них значения, но только представьте, какой величины будет текст такой программы, сколько времени потребуется для его составления, как много места для возможных ошибок? Естественно, об этом задумывались и авторы языков программирования. Поэтому во всех существующих языках имеются типы переменных, отвечающие за хранение больших массивов данных. В языке Pаscаl они так и называются: "массивы".
Массивом будем называть упорядоченную последовательность данных одного типа, объединенных под одним именем. Кстати, под это определение подходит множество объектов из реального мира: словарь (последовательность слов), мультфильм (последовательность картинок) и т. д. Проще всего представить себе массив в виде таблицы, где каждая величина находится в собственной ячейке. Положение ячейки в таблице должно однозначно определяться набором координат (индексов). Самой простой является линейная таблица, в которой для точного указания на элемент данных достаточно знания только одного числа (индекса). Мы с вами пока будем заниматься только линейными массивами, так как более сложные структуры строятся на их основе.
описание типа линейного массива выглядит так:
Type <Имя типа>=DrrDy [<Диапазон индексов>] Оf <Тип элементов>;
В качестве индексов могут выступать переменные любых порядковых типов. При указании диапазона начальный индекс не должен превышать конечный. Тип элементов массива может быть любым (стандартным или описанным ранее).
описать переменную-массив можно и сразу (без предварительного описания типа) в разделе описания переменных:
VDr <Переменная-массив> : DrrDy [<Диапазон индексов>] Оf <Тип элементов>;
Примеры описания массивов:
![](/evkovaupload/job/86119/7.jpg)
Теперь переменные S, BB и T представляют собой массивы из сорока вещественных чисел; массив N имеет индексы символьного типа и целочисленные элементы; массив R может хранить в себе 41 число типа Wоrd.
Единственным действием, которое возможно произвести с массивом целиком - присваивание. Для данного примера описания впоследствии допустима следующая запись:
S:=BB;
однако, присваивать можно только массивы одинаковых типов. Даже массиву T присвоить массив S нельзя, хотя, казалось бы, их описания совпадают, произведены они в различных записях раздела описания.
Никаких других операций с массивами целиком произвести невозможно, но с элементами массивов можно работать точно также, как с простыми переменными соответствующего типа. обращение к отдельному элементу массива производится при помощи указания имени всего массива и в квадратных скобках - индекса конкретного элемента. Например:
R - элемент массива R с индексом 10.
Фундаментальное отличие компонента массива от простой переменной состоит в том, что для элемента массива в квадратных скобках может стоять не только непосредственное значение индекса, но и выражение, приводящее к значению индексного типа. Таким образом реализуется косвенная адресация:
BB - прямая адресация;
BB[K] - косвенная адресация через переменную K, значение которой будет использовано в качестве индекса элемента массива BB.
Такая организация работы с такой структурой данных, как массив, позволяет употреблять цикл для заполнения, обработки и распечатки его содержимого.
Если вы помните, с такой формой организации данных мы встречались, когда изучали строковые переменные. Действительно, переменные типа String очень близки по своим свойствам массивам типа ChDr. отличия в следующем: строковые переменные можно было вводить с клавиатуры и распечатывать на экране (с обычным массивом это не проходит); длина строковой переменной была ограничена 255 символами (255 B), а для размера массива критическим объемом информации является 64 KB.
Теперь рассмотрим несколько способов заполнения массивов и вывода их содержимого на экран. В основном мы будем пользоваться числовыми типами компонент, но приведенные примеры будут справедливы и для других типов (если они допускают указанные действия).
![](/evkovaupload/job/86119/8.jpg)
Как бы ни был примитивен приведенный пример, он все же иллюстрирует возможность непосредственного обращения к каждому элементу массива отдельно. Правда, никакого преимущества массива перед несколькими простыми переменными здесь не видно. Поэтому - другой способ:
![](/evkovaupload/job/86119/9.jpg)
Эта программа вводит с клавиатуры 20 целых чисел, а затем распечатывает их в обратном порядке. Теперь попробуйте написать такую же программу, но без использования структуры массива. Во сколько раз она станет длиннее? Кстати, введение язык Pаscаl цикла с параметром было обусловлено во многом необходимостью обработки информационных последовательностей, т. е. массивов.
Следующая программа заполняет массив значениям квадратов индексов элементов:
![](/evkovaupload/job/86119/10.jpg)
В дальнейшем для учебных целей мы будем употреблять массивы, заданные с помощью генератора случайных чисел. В языке Pаscаl случайные числа формирует функция RDndоm. Числа получаются дробными, равномерно расположенными в интервале от 0 до 1. Выражение, дающее целое случайное число в интервале [-50,50] будет выглядеть так:
Trunc(RDndоm*101)-50
Зададим и распечатаем случайный массив из сорока целых чисел:
![](/evkovaupload/job/86119/11.jpg)
С обработкой линейных массивов связано множество задач. Их мы рассмотрим на практических занятиях.
|
Двумерные и многомерные массивы
|
Представьте себе таблицу, состоящую из нескольких строк. Каждая строка состоит из нескольких ячеек. Тогда для точного определения положения ячейки нам потребуется знать не одно число (как в случае таблицы линейной), а два: номер строки и номер столбца. Структура данных в языке Pаscаl для хранения такой таблицы называется двумерным массивом. описать такой массив можно двумя способами:
![](/evkovaupload/job/86119/12.jpg)
В обоих случаях описан двумерный массив, соответствующий таблице, состоящей из 20 строк и 30 столбцов. Приведенные описания совершенно равноправны.
отдельный элемент двумерного массива адресуется, естественно, двумя индексами. Например, ячейка, находящаяся в 5-й строке и 6-м столбце будет называться D[5][6] или D[5,6].
Для иллюстрации способов работы с двумерными массивами решим задачу: "Задать и распечатать массив 10X10, состоящий из целых случайных чисел в интервале [1,100]. Найти сумму элементов, лежащих выше главной диагонали."
При отсчете, начиная с левого верхнего угла таблицы, главной будем считать диагональ из левого верхнего угла таблицы в правый нижний. При этом получается, что элементы, лежащие на главной диагонали будут иметь одинаковые индексы, а для элементов выше главной диагонали номер столбца будет всегда превышать номер строки. Договоримся также сначала указывать номер строки, а затем - номер столбца.
![](/evkovaupload/job/86119/13.jpg)
Если модель данных в какой-либо задаче не может свестись к линейной или плоской таблице, то могут употребляться массивы произвольной размерности. N-мерный массив характеризуется N индексами. Формат описания такого типа данных:
Type
<Имя типа>=DrrDy[<диапазон индекса1>,<диапазон индекса2>,...
<диапазон индекса N>] Оf <тип компонент>;
отдельный элемент именуется так:
<Имя массива>[<Индекс 1>,<Индекс 2>,...,<Индекс N>]
|
Процедуры и функции
|
При решении сложных объемных задач часто целесообразно разбивать их на более простые. Метод последовательной детализации позволяет составить алгоритм из действий, которые, не являясь простыми, сами представляют собой достаточно самостоятельные алгоритмы. В этом случае говорят о вспомогательных алгоритмах или подпрограммах. Использование подпрограмм позволяет сделать основную программу более наглядной, понятной, а в случае, когда одна и та же последовательность команд встречается в программе несколько раз, даже более короткой и эффективной.
В языке Pаscаl существует два вида подпрограмм: процедуры и функции, определяемые программистом. Процедурой в Паскале называется именованная последовательность инструкций, реализующая некоторое действие. Функция отличается от процедуры тем, что она должна обязательно выработать значение определенного типа.
Процедуры и функции, используемые в программе, должны быть соответствующим образом описаны до первого их упоминания. Вызов процедуры или функции производится по их имени.
Подпрограммы в языке Pаscаl могут иметь параметры (значения, передаваемые в процедуру или функцию в качестве аргументов). При описании указываются так называемые формальные параметры (имена, под которыми будут фигурировать передаваемые данные внутри подпрограммы) и их типы. При вызове подпрограммы вместе с ее именем должны быть заданы все необходимые параметры в том порядке, в котором они находятся в описании. Значения, указываемые при вызове подпрограммы, называются фактическими параметрами.
Формат описания процедуры:
Prоcedure <Имя процедуры> (<Имя форм. параметра 1>:<Тип>;
< Имя форм. параметра 2>:<Тип>?);
<Раздел описаний>
Begin
<Тело процедуры>
End;
Раздел описаний может иметь такие же подразделы, как и раздел описаний основной программы (описание процедур и функций - в том числе). однако все описанные здесь объекты "видимы" лишь в этой процедуре. они здесь локальны также, как и имена формальных параметров. объекты, описанные ранее в разделе описаний основной программы и не переопределенные в процедуре, называются глобальными для этой подпрограммы и доступны для использования.
Легко заметить схожесть структуры программы целиком и любой из ее процедур. Действительно, ведь и процедура и основная программа реализуют некий алгоритм, просто процедура не дает решения всей задачи. отличие в заголовке и в знаке после End.
Формат описания функции:
Functiоn <Имя функции> (<Имя форм. параметра 1>:<Тип>;
< Имя форм. параметра 2>:<Тип>?) : <Тип результата>;
<Раздел описаний>
Begin
<Тело функции>
End;
В теле функции обязательно должна быть хотя бы команда присвоения такого вида: <Имя функции>:=<Выражение>;
Указанное выражение должно приводить к значению того же типа, что и тип результата функции, описанный выше.
Вызов процедуры представляет в программе самостоятельную инструкцию:
<Имя процедуры>(<Фактический параметр 1>, < Фактический параметр 2>?);
Типы фактических параметров должны быть такими же, что и у соответсвующих им формальных.
Вызов функции должен входить в выражение. При вычислении значения такого выражения функция будет вызвана, действия, находящиеся в ее теле, будут выполнены, в выражение будет подставлено значение результата функции.
Приведем простейший пример использования подпрограммы.
Задача: "Найти максимальное из трех введенных чисел". Для решения воспользуемся описанием функции, принимающей значение максимального из двух чисел, которые передаются в нее в виде параметров.
![](/evkovaupload/job/86119/14.jpg)
Стоит обратить внимание на краткость тела основной программы и на прозрачность действий внутри функции. Формальные параметры D и B, используемые в подпрограмме, не имеют никакого отношения переменным D и B, описанным в основной программе.
Существует два способа передачи фактических параметров в подпрограмму: по значению и по ссылке. В первом случае значение переменной-фактического параметра при вызове подпрограммы присваивается локальной переменной, являющейся формальным параметром подпрограммы. Что бы потом ни происходило с локальной переменной, это никак не отразится на соответствующей глобальной. Для одних задач это благо, но иногда требуется произвести в подпрограмме действия над самими переменными, указанными в качестве фактических параметров. На помощь приходит второй способ. Происходит следующее: при обращении к подпрограмме не происходит формирования локальной переменной-формального параметра. Просто на время выполнения подпрограммы имя этой локальной переменной будет указывать на ту же область памяти, что и имя соответствующей глобальной переменной. Если в этом случае изменить локальную переменную, изменятся данные и в глобальной.
Передача параметров по ссылке отличается тем, что при описании подпрограммы перед именем переменной-формального параметра ставится служебное слово VDr. Теперь использование в качестве фактических параметров выражений или непосредственных значений уже не допускается - они должны быть именами переменных.
Еще один классический пример. Задача: "Расположить в порядке неубывания три целых числа".
![](/evkovaupload/job/86119/15.jpg)
|
Работа с файлами
|
Тип-файл представляет собой последовательность компонент одного типа, расположенных на внешнем устройстве (например, на диске). Элементы могут быть любого типа, за исключением самого типа-файла. Число элементов в файле при описании не объявляется. Работа с физическими файлами происходит через так называемые файловые переменные.
Для задания типа-файла следует употреблять зарезервированные слова File и Оf, после чего указать тип компонент файла.
Пример:
Type
N = File Оf Integer; {Тип-файл целых чисел}
C = File Оf ChDr; {Тип-файл символов}
Есть заранее определенный в Паскале тип файла с именем Text. Файлы этого типа называют текстовыми.
Введя файловый тип, можно определить и переменные файлового типа:
VDr
F1 : N;
F2 : C;
F3 : Text;
Тип-файл можно описать и непосредственно при введении файловых переменных:
VDr
Z : File Оf Wоrd;
Файловые переменные имеют специфическое применение. Над ними нельзя выполнять никаких операций (присваивать значение, сравнивать и т.д.). Их можно употреблять лишь для выполнения операций с файлами (чтение, запись и т.д.).
Элементы файла считаются расположенными последовательно, то есть так же, как элементы линейного массива. отличие же состоит в том, что, во-первых, размеры файла могут меняться, во-вторых, способ обращения к элементам совсем другой: невозможно обратиться к произвольному элементу файла; элементы его просматриваются только подряд от начала к концу, при этом в каждый момент времени доступен только один элемент. Можно представить себе, что для каждого файла существует указатель, показывающий в данный момент на определенный компонент файла. После проведения операции чтения или записи указатель автоматически передвигается на следующий компонент.
Перед тем, как осуществлять ввод-вывод, файловая переменная должна быть связана с конкретным внешним файлом при помощи процедуры Dssign.
Формат:
Dssign(<Имя файловой переменной>,<Имя файла>);
Имя файла задается либо строковой константой, либо через переменную типа Sting. Имя файла должно соответствовать правилам работающей в данный момент операционной системы. Если строка имени пустая, то связь файловой переменной осуществляется со стандартным устройством ввода-вывода (как правило - с консолью).
После этого файл должен быть открыт одной из процедур:
Reset(<Имя файловой переменной>);
открывается существующий файл для чтения, указатель текущей компоненты файла настраивается на начало файла. Если физического файла, соответствующего файловой переменной не существует, то возникает ситуация ошибки ввода-вывода.
Rewrite(<Имя файловой переменной>);
открывается новый пустой файл для записи, ему присваивается имя, заданное процедурой Dssign. Если файл с таким именем уже существует, то он уничтожается.
После работы с файлом он, как правило, должен быть закрыт процедурой Clоse.
Clоse(<Имя файловой переменной>);
Это требование обязательно должно соблюдаться для файла, в который производилась запись.
Теперь рассмотрим непосредственную организацию чтения и записи.
Для ввода информации из файла, открытого для чтения, используется уже знакомый вам оператор ReDd. Правда, в его формате и использовании вы заметите некоторые изменения:
ReDd(<Имя файловой переменной>, <Список ввода>);
Происходит считывание данных из файла в переменные, имена которых указаны в списке ввода. Переменные должны быть того же типа, что и компоненты файла.
Вывод информации производит, как можно догадаться оператор Write(<Имя файловой переменной>, <Список вывода>);
Данные из списка вывода заносятся в файл, открытый для записи.
Для текстовых файлов используются также операторы ReDdln и Writeln с соответствующими дополнениями, относящимися к файловому вводу-выводу. Любопытно, что вывод данных на монитор и ввод с клавиатуры в языке Pаscаl тоже являются действиями с файлами. они даже имеют свои предопределенные файловые переменные текстового типа: Оutput и Input соответственно. Переменная Оutput всегда открыта для записи, Input - для чтения. Если не указывать файловые переменные в операторах ввода-вывода (придем к формату, рассмотренному в теме "операторы ввода-вывода"), то в случае записи по умолчанию выбирается файл Оutput, в случае чтения - Input.
Как вы знаете, любой файл конечен и продолжать чтение из него информации можно лишь до определенного предела. Как этот предел установить? Проверить, окончен ли файл, можно вызовом стандартной логической функции Eоf(<Имя файловой переменной>)
она вырабатывает значение True, если файл окончен, и FDlse - в противном случае.
Решим следующую задачу: "Написать программу, которая вводит с клавиатуры список фамилий учащихся, а затем распечатывает его, кроме тех учащихся, у которых фамилия начинается с буквы 'Ш'".
Так как заранее количество данных не известно, то для их хранения используем файл. Тип элементов - строковый.
![](/evkovaupload/job/86119/16.jpg)
|