рефераты
рефераты рефераты
 логин:   
 пароль:  Регистрация 

МЕНЮ
   Архитектура
География
Геодезия
Геология
Геополитика
Государство и право
Гражданское право и процесс
Делопроизводство
Детали машин
Дистанционное образование
Другое
Жилищное право
Журналистика
Компьютерные сети
Конституционное право зарубежныйх стран
Конституционное право России
Краткое содержание произведений
Криминалистика и криминология
Культурология
Литература языковедение
Маркетинг реклама и торговля
Математика
Медицина
Международные отношения и мировая экономика
Менеджмент и трудовые отношения
Музыка
Налоги
Начертательная геометрия
Оккультизм и уфология
Педагогика
Полиграфия
Политология
Право
Предпринимательство
Программирование и комп-ры
Психология - рефераты
Религия - рефераты
Социология - рефераты
Физика - рефераты
Философия - рефераты
Финансы деньги и налоги
Химия
Экология и охрана природы
Экономика и экономическая теория
Экономико-математическое моделирование
Этика и эстетика
Эргономика
Юриспруденция
Языковедение
Литература
Литература зарубежная
Литература русская
Юридпсихология
Историческая личность
Иностранные языки
Эргономика
Языковедение
Реклама
Цифровые устройства
История
Компьютерные науки
Управленческие науки
Психология педагогика
Промышленность производство
Краеведение и этнография
Религия и мифология
Сексология
Информатика программирование
Биология
Физкультура и спорт
Английский язык
Математика
Безопасность жизнедеятельности
Банковское дело
Биржевое дело
Бухгалтерский учет и аудит
Валютные отношения
Ветеринария
Делопроизводство
Кредитование



Главная > Программирование и комп-ры > Основы программирования на языке Паскаль

Программирование и комп-ры : Основы программирования на языке Паскаль

Основы программирования на языке Паскаль

| |

|Краткий курс лекций |

|"Основы программирования на языке Паскаль" |

| |

| |

|Введение. |

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

|представляет собой знакомство с формальными правилами записи алгоритмов для|

|их последующего выполнения компьютером. Формальность сия проистекает из |

|самих принципов, заложенных в архитектуру вычислительных устройств, и |

|жесткости математической логики. Поэтому, постарайтесь воспринять все |

|довольно строгие правила как неизбежность, настроить себя на серьезную, |

|скрупулезную, порой сложную работу. Однако не стоит бояться, расстраиваться|

|и сетовать на судьбу: немного аккуратности, внимания, знания предыдущего |

|материала - и вы уже программист. |

| |

|Основные понятия. |

| Как и любой алгоритм, являющийся, как вы помните, последовательностью |

|инструкций, программа на языке Паскаль состоит из команд (операторов), |

|записанных в определенном порядке и формате. |

| Команды позволяют получать, сохранять и обрабатывать данные различных |

|типов (например, целые числа, символы, строки символов, т.д.). Однако кроме|

|команд в записи программы участвуют еще так называемые "служебные слова". |

|Это и есть элементы формальности, организующие структуру программы. Их не |

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

|использовать только по своему прямому назначению. Переопределять их не |

|разрешается. |

| Вам уже известно, что основное назначение компьютера - облегчить |

|человеку работу с большими объемами информации, поэтому подавляющее |

|большинство программ построено по одному, довольно простому принципу: |

|получение данных из внешнего мира (ввод), обработка их по соответствующему |

|алгоритму, хранение необходимой информации и вывод во внешний (по отношению|

|к компьютеру) мир полученных результатов. Все эти действия реализуются |

|через имеющиеся в языках программирования команды, алгоритмические |

|структуры и структуры данных. |

| |

|Основная структура программы. |

| Правила языка Паскаль предусматривают единую для всех программ форму |

|основной структуры: |

|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); |

| 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; 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 Do ; |

| Правда, лаконично? По-русски можно прочитать так: "Пока истинно |

|условие, выполнять оператор". Здесь, так же как в формате условного |

|оператора, подразумевается выполнение только одного оператора. Если |

|необходимо выполнить несколько действий, то может быть использован |

|составной оператор. Тогда формат оператора принимает такой вид: |

|While Do |

|Begin |

|; |

|; |

|; |

|. . . |

|End; |

| |

|Цикл "ДО" |

| Этот вид цикла отличается от предыдущего в основном тем, что проверка |

|условия повторения тела цикла находится не перед ним, а после. Поэтому цикл|

|"До" называют циклом "с постусловием", а "Пока" - "с предусловием". |

| Обратите также внимание на то, что новая итерация (повторное |

|выполнение тела цикла) происходит не тогда, когда условие справедливо, а |

|как раз тогда, когда оно ложно. Поэтому цикл и получил свое название |

|(выполнять тело цикла до выполнения соответствующего условия). |

| Интересно, что в случае, когда условие цикла изначально истинно, тело |

|цикла все равно будет выполнено хотя бы один раз. Именно это отличие "до" |

|от "пока" привело к тому, что в программировании они не подменяют друг |

|друга, а используются для решения задач, к которым они более подходят. |

| Формат цикла на языке Pascal: |

|Repeat |

|; |

|; |

|; |

|. . . |

|Until ; |

| Читается так: "Выполнять оператор #1, оператор #2. : до выполнения |

|условия". |

| Здесь не требуется использование составного оператора, потому, что |

|сами слова Repeat и Until являются операторными скобками. |

| |

|Цикл "С параметром". |

| В данном случае параметром будет являться целочисленная переменная, |

|которая будет изменяться на единицу при каждой итерации цикла. Таким |

|образом, задав начальное и конечное значения для такой переменной, можно |

|точно установить количество выполнений тела цикла. Нарисовать блок-схему |

|такой структуры вы сможете сами после некоторых пояснений. |

| Форматов у этого вида цикла предусмотрено два: |

| For := To Do ; |

| For := Downto Do ; |

| Здесь И.П. - имя переменной-параметра, Н.З. - его начальное значение, |

|К.З. - соответственно конечное значение параметра. В качестве начального и |

|конечного значений |

| Читается данная структура так: "Для переменной (далее следует ее имя) |

|от начального значения до конечного выполнять оператор (являющийся телом |

|цикла)". Иногда цикл с параметром даже называют "Для" или "For". В первом |

|случае параметр с каждой итерацией увеличивается на единицу, во втором - |

|уменьшается. |

| Выполняется этот цикл по следующему алгоритму: |

| 1. переменной-параметру присваивается начальное значение; |

| 2. выполняется тело цикла; |

| 3. переменная-параметр автоматически увеличивается на 1 (в первом |

|случае формата); |

| 4. если параметр превышает конечное значение, то происходит выход из |

|цикла, иначе - переход к пункту 2. |

| Примечание: при использовании Downto параметр автоматически |

|уменьшается на 1, а выход из цикла происходит тогда, когда параметр |

|становится меньше конечного значения. |

| Таким образом, в отличие от первых двух видов цикла, этот цикл |

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

|цикла. |

| Вообще говоря, цикл "Пока" является универсальным, то есть любая |

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

|структуры. Циклы "До" и "С параметром" созданы для удобства |

|программирования. |

| Пример. |

| Найти сумму квадратов всех натуральных чисел от 1 до 100. |

| Решим эту задачу с использованием всех трех видов циклов. |

|I. С использованием цикла "Пока". |

|Program Ex1; |

|Var |

| A : Integer; |

| S : Longint; |

|Begin |

|A:=1; S:=0; |

|While A100; |

|Writeln(S) |

|End. |

|III. С использованием цикла "С параметром". |

|Program Ex3; |

|Var |

| A : Integer; |

| S : Longint; |

|Begin |

|S:=0; |

|For A:=1 To 100 Do S:=S+A*A; |

|Writeln(S) |

|End. |

| Теперь вам известны все основные алгоритмические структуры языка |

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

|конечно, если таковое существует. Тем не менее, изучение языка на этом не |

|закачивается, так как для написания хороших программ по утверждению |

|уважаемого Никлауса Вирта (за время моей работы у меня не появилось |

|оснований в этом сомневаться) нужны кроме алгоритмических, еще удобные |

|структуры данных. В рассматриваемом языке таких структур множество, для |

|каждого вида определены свои команды и операции. К их рассмотрению мы и |

|переходим. |

| |

|Строковые операции |

| До сих пор мы с вами рассматривали программы, реализующие алгоритмы |

|обработки числовых данных. Однако хоть ЭВМ изначально и были созданы только|

|для этой цели, по мере развития аппаратной части появилась возможность |

|оцифровывать данные других типов, хранить их в памяти машины, |

|перерабатывать, выводить во внешний по отношению к компьютеру мир. Проще |

|всего можно было так поступить с текстовой информацией. Если не ставить |

|перед машиной задачу "понимания" смысла текста, то задача оцифровки |

|сводится к установлению правил замены символов (литер) при вводе в |

|компьютер на их коды и обратной замены при выводе информации на экран или |

|принтер. Такие правила, конечно же, были составлены. Как водится, сначала |

|их было множество (вспомните разнообразие таблиц кодировки), затем весь мир|

|остановился на ASCII. |

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

|литерными величинами. Паскаль - не исключение. Как вам уже известно, в |

|стандарте языка описаны два типа переменных для литерных величин. Это - |

|String и Char. Напомню - переменная типа Char может содержать в себе только|

|один единственный символ, тип String предназначен для хранения строковых |

|величин до 255 символов длиною. Кстати, вы знаете не все о типе String. При|

|описании переменной этого типа вы можете сами указать максимальное число |

|символов, которое можно занести в нее. Конечно же, это число не должно |

|превышать 255. Делается это так: |

|Var |

|S : String[30]; |

| Для чего это нужно? |

| Дело в том, что при компиляции для каждой переменной отводится свой |

|участок памяти. Если мы будем выделять для всех переменных типа String по |

|256 байт, то это приведет к тому, что при использовании достаточно большого|

|их количества, памяти может и не хватить? Но если в переменной мы |

|собираемся хранить, например, фамилию пользователя, то тридцати символов |

|(тридцати байт) для этого вполне достаточно. Таким образом, экономится |

|память и увеличивается быстродействие программ. |

| Переменным строкового типа можно присваивать строковые величины |

|(внутри программы они заключаются в апострофы), значения выражений, которые|

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

|При этом апострофы не используются. Как вам известно, в числовую переменную|

|нельзя ввести строковую величину. Сделать наоборот - возможно, однако |

|число, находящееся в строковой переменной представляет собой просто |

|последовательность символов (цифр), поэтому в арифметических выражениях |

|участвовать не может. |

| Также, новым для вас явится то, что при использовании строковой |

|переменной, к каждому ее символу можно обратиться отдельно. Необходимо |

|только знать номер нужного символа от начала строки. Его достаточно |

|поставить после имени переменной типа String в квадратных скобках. |

| Пример: S[5] - пятый символ строки S. |

| С отдельным символом строки можно производить все действия, которые |

|можно производить с любой символьной переменной (ввод, присвоение, вывод на|

|экран, участие в выражениях и т.д.). |

| Обратите внимание на то, что нумерация символов в строке начинается с |

|единицы. Внутри квадратных скобок вместо числа может находиться выражение, |

|результатом которого является целое число. Главное чтобы символ с таким |

|номером в строке существовал. Но как же узнать, сколько символов в данный |

|момент находится в строковой переменной? Для этого существует специальная |

|функция, которая возвращает длину строковой переменной в символах. Это |

|функция Length. Ее формат: Length(S) |

| Здесь S - либо строковая величина, либо строковая переменная. |

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

|пользователем строковой величины. |

|Program Str1; |

|Var |

|S : String; |

|Begin |

|Writeln('Введите последовательность символов'); |

|Readln(S); |

|Writeln('Вы ввели строку из ',Length(S), ' символов') |

|End. |

| Другой пример: |

|Решим задачу: "Введенную строку вывести на экран по одному символу в строке|

|экрана". |

|Program Str2; |

|Var |

|S : String; |

|I : Byte; |

|Begin |

|Writeln('Введите строку'); |

|Readln(S); |

|For I:=1 to Length(S) do {организуем цикл, начиная с первого символа} |

|Writeln(S[I]) {строки, до последнего (номер последнего} |

|{совпадает с количеством символов строки S) } |

|End. |

| Какие же еще действия можно выполнять с переменными строкового типа? |

| Две строковые величины можно состыковывать. Эта операция называется |

|конкатенацией и обозначается знаком "+". |

| Например, результатом выполнения следующих команд: |

| R:= 'kadabra'; |

| H:= 'abra'; |

| S:=H+R; |

|в переменной S будет значение 'abrakadabra'. |

| Для конкатенации результат зависит от порядка операндов (в отличие от |

|операции сложения). Следует помнить о том, какой максимальной длины может |

|быть результирующая переменная, так как в случае превышения значением |

|выражения числа, указанного после String в описании переменной, "лишние" |

|символы в переменную не попадут. |

| Строковые величины можно сравнивать между собой. Это относится также и|

|к строковым переменным. Но как же компьютер определяет, какая строка |

|больше: |

|та, которая длиннее? |

|та, которая содержит больше заглавных букв? |

| На самом деле такая проверка проходит довольно сложно: компьютер |

|сравнивает сначала первые символы строк. Большим из двух считается тот, код|

|которого больше (вспомните, что такое код символа). Если равны первые |

|символы, то так же анализируется следующая пара до тех пор, пока не будет |

|найдено различие. Если начало строк совпадает, а одна из них кончается |

|раньше, то вторая автоматически называется большей. |

| Код символа в Паскале можно определить при помощи функции Ord. |

| Ее формат: Ord(C), где С - либо непосредственно указанный символ, либо|

|переменная символьного типа, либо один символ строковой переменной. Вообще,|

|функция Ord имеет более глубокий смысл, но об этом - позже. Есть и обратная|

|функция, которая возвращает символ по известному коду. Это функция Chr(N), |

|где N - выражение, приводящее к целому числу в интервале от 0 до 255 |

|(возможные значения кода символа). Очевидно, что Chr(Ord(C))=C, |

|Ord(Chr(N))=N. |

| Следующая маленькая программа выводит на экран кодовую таблицу: |

|Program Str3; |

|Var |

| I : Byte; |

|Begin |

|For I:=32 to 255 do |

|Write('VV',I:4, '-',Chr(I)) |

|End. |

| Цикл в программе начинается с 32 потому, что символы с кодами от 0 до |

|31 являются управляющими и не имеют соответствующего графического |

|представления. |

| Задача: "Определить, является ли введенная строка "перевертышем". |

|Перевертышем называется такая строка, которая одинаково читается с начала и|

|с конца. Например, "казак" и "потоп" - перевертыши, "канат" - не |

|перевертыш". |

| Поступим следующим образом: из введенной строки сформируем другую |

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

|первую строку со второй; если они окажутся равны, то ответ положительный, |

|иначе - отрицательный. Естественно, предложенный способ решения не является|

|единственно возможным. |

|Program Str4; |

|Var |

| S,B : String; |

| I : Byte; |

|Begin |

|Writeln('Введите строку'); |

|Readln(S); |

|B:=''; {Переменной B присваиваем значение "пустая строка"} |

|For I:=1 to Length(S) do |

|B:=S[I]+B; {Конкатенация. Символы строки S пристыковываются к} |

|{переменной B слева. Самым левым окажется последний.} |

|If B=S Then Writeln('Перевертыш') Else Writeln('Не перевертыш') |

|End. |

| Число, записанное в строковую переменную, естественно числом не |

|является, но очень часто требуется его все же использовать в качестве |

|числа. Для этого нужно произвести преобразование типа. Перевод строкового |

|представления числа в числовое выполняет в Паскале оператор Val. |

|Его формат: |

|Val(S,X,C); |

| Здесь S - строка, содержащая число, X - числовая переменная, в которую|

|будет помещен результат, С - переменная целочисленного типа, в которую |

|помещается первого встреченного в S отличного от цифры символа. Если после |

|выполнения оператора Val переменная С имеет значение 0, то это означает, |

|что преобразование типа прошло совершенно успешно и в строке нецифровых |

|символов не встретилось. |

| Противоположное действие осуществляет оператор Str. Формат оператора: |

| Str(X,S); |

|X - число (либо арифметическое выражение), S - строковая переменная. |

| В переменную S попадает строковое представление числа X. Это нужно, |

|например, при необходимости выводить на экран числа в графическом режиме |

|(будет изучено позже), так как стандартные процедуры вывода на экран там |

|работают только со строковыми величинами. |

| Для иллюстрации рассмотрим такую задачу: "Найти сумму цифр введенного |

|натурального числа". Используя только числовые переменные, решить ее можно,|

|но предлагаемое здесь решение, по-моему, проще. |

|Program Str5; |

|Var |

|S : String; |

|I,X,A,C : Integer; |

|Begin |

|Writeln('Введите натуральное число'); |

|Readln(S); {Число вводится в строковую переменную} |

|A:=0; |

|For I:=1 To Length(S) Do |

|Begin |

|Val(S[I],X,C); {Цифровой символ превращается в число} |

|A:=A+X {Цифры суммируются} |

|End; |

|Writeln('Сумма цифр равна ',A) |

|End. |

| Теперь рассмотрим еще несколько действий над строками: |

|оператор DELETE(S,I,C) из строковой переменной S удаляет C символов, |

|начиная с I-того; |

|оператор INSERT(SN,S,I) вставляет подстроку SN в строковую переменную S |

|перед символом с номером I; |

|функция COPY(S,I,C) возвращает подстроку строки S из C символов, начиная с |

|символа с номером I; |

|функция Pos(SN,S) возвращает номер символа, с которого в строке S |

|начинается подстрока SN (позицию первого вхождения подстроки в строку). |

|Если такой подстроки нет, то возвращается ноль. |

| Пример их использования: |

|"Во введенной строке заменить все вхождения подстроки 'ABC' на подстроки |

|'KLMNO'". |

|Program Str6; |

|Var |

|S : String; |

|A : Byte; |

|Begin |

|Writeln('Введите строку'); |

|Readln(S); |

|While Pos('ABC',S)<>0 Do |

|Begin |

|A:= Pos('ABC',S); |

|Delete(S,A,3); |

|Insert('KLMNO',S,A) |

|End; |

|Writeln(S) |

|End. |

| |

|Определение типов |

| Как было упомянуто ранее, в изучаемом языке возможно определять новые |

|типы переменных. После определения этот тип становится доступным для |

|описания переменных, также как и стандартные типы. |

| Новый тип перед первым его использованием должен быть описан в |

|соответствующем разделе описаний. Его заголовок - служебное слово Type. |

|Type |

| = ; |

| Есть несколько способов описания. Иногда говорят даже о видах типов |

|(как бы это странно ни звучало). |

| Итак, первым рассмотрим так называемый перечисляемый тип. |

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

|позволяя записывать в переменные этого типа названия разнообразных |

|объектов, исследуемых программой. Этот тип представляет собой набор |

|идентификаторов, с которыми могут совпадать значения параметров. |

| Формат описания следующий: = (, ,? ); |

| Далее можно определить любое число переменных уже описанного типа. |

|Обратите внимание на то, что каждый идентификатор может участвовать в |

|описании только одного перечисляемого типа. |

| Этим переменным можно присваивать только значения из списка, |

|определенного при описании типа. Эти значения не являются ни числами, ни |

|строковыми величинами, ни даже величинами логического типа, поэтому они не |

|могут участвовать в арифметических, строковых, логических выражениях, а |

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

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

|определены несколько функций: |

| Ord(X) - порядковый номер значения переменной X в списке |

|идентификаторов. |

| Succ(X) - следующее значение для величины Х. |

| Pred(X) - предыдущее значение данного типа. |

| Обратите внимание на то, что для функции Ord нумерация среди значений |

|идет, начиная от нуля. Для последнего значения нельзя применять функцию |

|Succ, для первого - Pred. |

| Переменные различных перечисляемых типов несовместимы друг с другом. |

| Множество стандартных порядковых типов в языке Паскаль на самом деле |

|определены как перечисляемые. Это типы Char, Integer, другие. Достоинства |

|стандартных порядковых типов лишь в том, что над каждым из них уже |

|определены специфические действия. Например, тип Boolean описан так: |

|Type |

|Boolean = (False, True); |

| Единственное его отличие от перечисляемых типов, определяемых |

|программистом, состоит в том, что значения типа Boolean можно выводить на |

|экран. Можете проверить, Ord(False)=0. |

| Интересно, что переменная перечисляемого типа может быть счетчиком в |

|цикле "с параметром". |

|Пример: |

|Program T1; |

|Type |

| Colors = (Black, Blue, Green, Cyan, Red, Magenta, Brown, Yellow, |

|White); |

|Var |

| C1,C2 : Colors; |

|Begin |

|C1:=Green; |

|C2:=Red; |

|Writeln(Ord(C1), Ord(Succ(C2))) |

|End. |

| Во время выполнения на экране появятся числа "2" и "5", что |

|соответствует номерам значений Green и Magenta. |

| Следующий тип, который можно определить в программе - тип-диапазон. |

| Здесь не нужно перечислять все значения этого типа, потому, что |

|возможными для него являются значения поддиапазона уже определенного до |

|него любого порядкового типа (стандартного или описанного ранее |

|перечисляемого типа). Достаточно лишь указать начальную и конечную величину|

|отрезка порядкового типа. Единственное условие: начальное значение не |

|должно превышать конечное. |

| Формат описания отрезочного типа: |

|Type |

| =..; |

|Примеры: |

|Type |

|Age=0..150; {Целое число в интервале от 0 до 150} |

|Lat='A'.. 'Z'; {Заглавные буквы латинского алфавита} |

|Month=(January, February, March, April, May, June, July, August, September,|

|October, November, December); |

|Spring=March..May; {Весенние месяцы} |

| Есть еще одна возможность определить новый тип, о существовании |

|которой можно было бы и догадаться. |

|Type |

| =; |

|Пример: |

|Type |

| Number=Byte; |

| |

|Массивы |

| До сих пор мы рассматривали переменные, которые имели только одно |

|значение, могли содержать в себе только одну величину определенного типа. |

|Исключением являлись лишь строковые переменные, которые представляют собой |

|совокупность данных символьного типа, но и при этом мы говорили о строке, |

|как об отдельной величине. |

| Вы знаете, что компьютер предназначен в основном для облегчения работы|

|человека с большими информационными объемами. Как же, используя только |

|переменные известных вам типов, сохранить в памяти и обработать данные, |

|содержащие десяток, сотню, тысячу чисел или, к примеру, строк? А ведь такие|

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

|переменных, сколько данных, можно даже занести в них значения, но только |

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

|потребуется для его составления, как много места для возможных ошибок? |

|Естественно, об этом задумывались и авторы языков программирования. Поэтому|

|во всех существующих языках имеются типы переменных, отвечающие за хранение|

|больших массивов данных. В языке Паскаль они так и называются: "массивы". |

| Массивом будем называть упорядоченную последовательность данных одного|

|типа, объединенных под одним именем. Кстати, под это определение подходит |

|множество объектов из реального мира: словарь (последовательность слов), |

|мультфильм (последовательность картинок) и т. д. Проще всего представить |

|себе массив в виде таблицы, где каждая величина находится в собственной |

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

|координат (индексов). Самой простой является линейная таблица, в которой |

|для точного указания на элемент данных достаточно знания только одного |

|числа (индекса). Мы с вами пока будем заниматься только линейными |

|массивами, так как более сложные структуры строятся на их основе. |

| Описание типа линейного массива выглядит так: |

| Type =Array [] Of ; |

| В качестве индексов могут выступать переменные любых порядковых типов.|

|При указании диапазона начальный индекс не должен превышать конечный. Тип |

|элементов массива может быть любым (стандартным или описанным ранее). |

| Описать переменную-массив можно и сразу (без предварительного описания|

|типа) в разделе описания переменных: |

| Var : Array [] Of ; |

| Примеры описания массивов: |

|Var |

|S, BB : Array [1..40] Of Real; |

|N : Array ['A'..'Z'] Of Integer; |

|R : Array [-20..20] Of Word; |

|T : Array [1..40] Of Real; |

| Теперь переменные S, BB и T представляют собой массивы из сорока |

|вещественных чисел; массив N имеет индексы символьного типа и целочисленные|

|элементы; массив R может хранить в себе 41 число типа Word. |

| Единственным действием, которое возможно произвести с массивом целиком|

|- присваивание. Для данного примера описания впоследствии допустима |

|следующая запись: |

| S:=BB; |

| Однако, присваивать можно только массивы одинаковых типов. Даже |

|массиву T присвоить массив S нельзя, хотя, казалось бы, их описания |

|совпадают, произведены они в различных записях раздела описания. |

| Никаких других операций с массивами целиком произвести невозможно, но |

|с элементами массивов можно работать точно также, как с простыми |

|переменными соответствующего типа. Обращение к отдельному элементу массива |

|производится при помощи указания имени всего массива и в квадратных скобках|

|- индекса конкретного элемента. Например: |

|R[10] - элемент массива R с индексом 10. |

| Фундаментальное отличие компонента массива от простой переменной |

|состоит в том, что для элемента массива в квадратных скобках может стоять |

|не только непосредственное значение индекса, но и выражение, приводящее к |

|значению индексного типа. Таким образом реализуется косвенная адресация: |

|BB[15] - прямая адресация; |

|BB[K] - косвенная адресация через переменную K, значение которой будет |

|использовано в качестве индекса элемента массива BB. |

| Такая организация работы с такой структурой данных, как массив, |

|позволяет использовать цикл для заполнения, обработки и распечатки его |

|содержимого. |

| Если вы помните, с такой формой организации данных мы встречались, |

|когда изучали строковые переменные. Действительно, переменные типа String |

|очень близки по своим свойствам массивам типа Char. Отличия в следующем: |

|строковые переменные можно было вводить с клавиатуры и распечатывать на |

|экране (с обычным массивом это не проходит); длина строковой переменной |

|была ограничена 255 символами (255 B), а для размера массива критическим |

|объемом информации является 64 KB. |

| Теперь рассмотрим несколько способов заполнения массивов и вывода их |

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

|компонент, но приведенные примеры будут справедливы и для других типов |

|(если они допускают указанные действия). |

|Program M1; |

|Var |

| A : Array [1..20] Of Integer; |

|Begin |

|A[1]:=7; {Заполняем массив значениями (отдельно каждый компонент)} |

|A[2]:=32; |

|A[3]:=-70; |

|.............. {Трудоемкая задача?} |

|A[20]:=56; |

|Writeln(A[1],A[2],A[3], ?,A[20]) |

|End. |

| Как бы ни был примитивен приведенный пример, он все же иллюстрирует |

|возможность непосредственного обращения к каждому элементу массива |

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

|переменными здесь не видно. Поэтому - другой способ: |

|Program M2; |

|Var |

|A : Array [1..20] Of Integer; |

|I : Integer; |

|Begin |

|For I:=1 To 20 Do {Организуем цикл с параметром I по всем возможным} |

|Readln(A[I]); {значениям индексов и вводим A[I] с клавиатуры } |

|For I:=20 Downto 1 Do {Распечатываем массив в обратном порядке} |

|Write(A[I],'VVV') |

|End. |

| Эта программа вводит с клавиатуры 20 целых чисел, а затем |

|распечатывает их в обратном порядке. Теперь попробуйте написать такую же |

|программу, но без использования структуры массива. Во сколько раз она |

|станет длиннее? Кстати, введение язык Паскаль цикла с параметром было |

|обусловлено во многом необходимостью обработки информационных |

|последовательностей, т. е. массивов. |

| Следующая программа заполняет массив значениям квадратов индексов |

|элементов: |

|Program M3; |

|Const |

|N=50; {Константа N будет содержать количество элементов массива} |

|Var |

|A : Array [1..N] Of Integer; |

|I : Integer; |

|Begin |

|For I:=1 To N Do |

|A[I]:=I*I |

|For I:=1 To N Do |

|Write(A[I],'VVV') |

|End. |

| В дальнейшем для учебных целей мы будем использовать массивы, заданные|

|с помощью генератора случайных чисел. В языке Паскаль случайные числа |

|формирует функция Random. Числа получаются дробными, равномерно |

|расположенными в интервале от 0 до 1. Выражение, дающее целое случайное |

|число в интервале [-50,50] будет выглядеть так: |

|Trunc(Random*101)-50 |

|Зададим и распечатаем случайный массив из сорока целых чисел: |

|Program M4; |

|Const |

|N=40; {Константа N будет содержать количество элементов массива} |

|Var |

|A : Array [1..N] Of Integer; |

|I : Integer; |

|Begin |

|For I:=1 To N Do |

|Begin |

|A[I]:= Trunc(Random*101)-50 |

|Write(A[I],'VVV') |

|End |

|End. |

| С обработкой линейных массивов связано множество задач. Их мы |

|рассмотрим на практических занятиях. |

| |

|Двумерные и многомерные массивы |

|Представьте себе таблицу, состоящую из нескольких строк. Каждая строка |

|состоит из нескольких ячеек. Тогда для точного определения положения ячейки|

|нам потребуется знать не одно число (как в случае таблицы линейной), а два:|

|номер строки и номер столбца. Структура данных в языке Паскаль для хранения|

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

|двумя способами: |

|I. |

|Var |

| A : Array [1..20] Of Array [1..30] Of Integer; |

|II. |

|Var |

| A : Array [1..20,1..30] Of Integer; |

|В обоих случаях описан двумерный массив, соответствующий таблице, состоящей|

|из 20 строк и 30 столбцов. Приведенные описания совершенно равноправны. |

|Отдельный элемент двумерного массива адресуется, естественно, двумя |

|индексами. Например, ячейка, находящаяся в 5-й строке и 6-м столбце будет |

|называться A[5][6] или A[5,6]. |

|Для иллюстрации способов работы с двумерными массивами решим задачу: |

|"Задать и распечатать массив 10X10, состоящий из целых случайных чисел в |

|интервале [1,100]. Найти сумму элементов, лежащих выше главной диагонали." |

|При отсчете, начиная с левого верхнего угла таблицы, главной будем считать |

|диагональ из левого верхнего угла таблицы в правый нижний. При этом |

|получается, что элементы, лежащие на главной диагонали будут иметь |

|одинаковые индексы, а для элементов выше главной диагонали номер столбца |

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

|номер строки, а затем - номер столбца. |

|Program M5; |

|Var |

|A : Array[1..10,1..10] Of Integer; |

|I, K : Byte; |

|S : Integer; |

|Begin |

|S:=0; |

|For I:=1 To 10 Do |

|Begin |

|For K:=1 To 10 Do |

|Begin |

|A[I,K]:=Trunc(Random*100)+1; |

|Write(A[I,K]:6); |

|If K>I Then S:=S+A[I,K] |

|End; |

|Writeln |

|End; |

|Writeln('Сумма элементов выше гл. диагонали равнаV',S) |

|End. |

|Если модель данных в какой-либо задаче не может свестись к линейной или |

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

|N-мерный массив характеризуется N индексами. Формат описания такого типа |

|данных: |

|Type |

|=Array[,,... |

|] Of ; |

|Отдельный элемент именуется так: |

| [,,...,] |

| |

|Процедуры и функции |

|При решении сложных объемных задач часто целесообразно разбивать их на |

|более простые. Метод последовательной детализации позволяет составить |

|алгоритм из действий, которые, не являясь простыми, сами представляют собой|

|достаточно самостоятельные алгоритмы. В этом случае говорят о |

|вспомогательных алгоритмах или подпрограммах. Использование подпрограмм |

|позволяет сделать основную программу более наглядной, понятной, а в случае,|

|когда одна и та же последовательность команд встречается в программе |

|несколько раз, даже более короткой и эффективной. |

|В языке Паскаль существует два вида подпрограмм: процедуры и функции, |

|определяемые программистом. Процедурой в Паскале называется именованная |

|последовательность инструкций, реализующая некоторое действие. Функция |

|отличается от процедуры тем, что она должна обязательно выработать значение|

|определенного типа. |

|Процедуры и функции, используемые в программе, должны быть соответствующим |

|образом описаны до первого их упоминания. Вызов процедуры или функции |

|производится по их имени. |

|Подпрограммы в языке Паскаль могут иметь параметры (значения, передаваемые |

|в процедуру или функцию в качестве аргументов). При описании указываются |

|так называемые формальные параметры (имена, под которыми будут фигурировать|

|передаваемые данные внутри подпрограммы) и их типы. При вызове подпрограммы|

|вместе с ее именем должны быть заданы все необходимые параметры в том |

|порядке, в котором они находятся в описании. Значения, указываемые при |

|вызове подпрограммы, называются фактическими параметрами. |

|Формат описания процедуры: |

|Procedure (:; |

|< Имя форм. параметра 2>:?); |

| |

|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. |




Информационная Библиотека
для Вас!



 

 Поиск по порталу:
 

© ИНФОРМАЦИОННАЯ БИБЛИОТЕКА 2010 г.