Pascal material

166
Введение Язык программирования ПАСКАЛЬ был разработан в 1970 году Никлаусом Виртом, профессором Института Информатики в Цюрихе (Швейцария). Названный в честь французского математика и философа Блеза Паскаля, этот язык получил распространение во всем мире и стал применяться для всех категорий компьютеров. В последующие годы, элементы стандартного языка ПАСКАЛЬ были существенно развиты, в результате чего появились новые версии: TURBO PASCAL 6.0, TURBO PASCAL 7.0, BORLAND PASCAL и даже новые языки: MODULA-2, DELPHI и др. Данный учебник разработан в соответствии с Программой по информатике, принятой Министерством Образования и Науки Республики Молдова, с целью предоставить учащимся необходимые знания для разработки и отладки программ на языке ПАСКАЛЬ. В главе 1 изложены основные элементы теории языков программирования: метаязык БНФ и синтаксические диаграммы. А также представлены алфавит и словарь языка ПАСКАЛЬ: специальные символы и зарезервированные (ключевые) слова, идентификаторы, числа, строки, метки, директивы и разделители. В главе 2 описываются типы данных: целый, вещественный, булевский, символьный, перечисляемый и интервальный. В данной главе также изучаются способы объявления простых типов данных, описание переменных и констант. Глава 3 посвящена концепции действия и содержит описание простых и структурных операторов языка. Особое внимание уделяется изучению синтаксиса и методов вычисления выражений языка ПАСКАЛЬ, способу организации вычислительных процессов с помощью структурных операторов. Здесь также описывается общая структура программы на языке ПАСКАЛЬ. Глава 4 включает обширный теоретический и практический материал по описанию и обработке структурированных типов данных: тип-массив, строковый тип, тип-запись, тип-множество, файловый тип. В данной главе представлены методы создания файлов и работы с ними: связь файлов языка ПАСКАЛЬ с внешними файлами, занесение элементов в файл и считывание их из файла. В главе 5 изучаются процедуры и функции языка ПАСКАЛЬ. Здесь подробно рассматриваются механизмы связи через параметры-значения, параметры- переменные, параметры-функции/процедуры и глобальные переменные. В данной главе также изучаются рекурсивные подпрограммы. В главе 6 изучаются ссылочный тип, динамические переменные и структуры данных, созданные на их основе: списки, стеки, очереди, деревья. Рассматриваются операции, которые осуществляются над динамическими структурами данных, и задачи, связанные с применением итерации и рекурсии. В главе 7 изложены методы разработки программ. Здесь представлены элементы модульного и структурного программирования, методы проверки и отладки программ. 1

description

material util

Transcript of Pascal material

Page 1: Pascal material

ВведениеЯзык программирования ПАСКАЛЬ был разработан в 1970 году Никлаусом Виртом, профессором

Института Информатики в Цюрихе (Швейцария). Названный в честь французского математика и философа Блеза Паскаля, этот язык получил распространение во всем мире и стал применяться для всех категорий компьютеров. В последующие годы, элементы стандартного языка ПАСКАЛЬ были существенно развиты, в результате чего появились новые версии: TURBO PASCAL 6.0, TURBO PASCAL 7.0, BORLAND PASCAL и даже новые языки: MODULA-2, DELPHI и др.

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

В главе 1 изложены основные элементы теории языков программирования: метаязык БНФ и синтаксические диаграммы. А также представлены алфавит и словарь языка ПАСКАЛЬ: специальные символы и зарезервированные (ключевые) слова, идентификаторы, числа, строки, метки, директивы и разделители.

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

Глава 3 посвящена концепции действия и содержит описание простых и структурных операторов языка. Особое внимание уделяется изучению синтаксиса и методов вычисления выражений языка ПАСКАЛЬ, способу организации вычислительных процессов с помощью структурных операторов. Здесь также описывается общая структура программы на языке ПАСКАЛЬ.

Глава 4 включает обширный теоретический и практический материал по описанию и обработке структурированных типов данных: тип-массив, строковый тип, тип-запись, тип-множество, файловый тип. В данной главе представлены методы создания файлов и работы с ними: связь файлов языка ПАСКАЛЬ с внешними файлами, занесение элементов в файл и считывание их из файла.

В главе 5 изучаются процедуры и функции языка ПАСКАЛЬ. Здесь подробно рассматриваются механизмы связи через параметры-значения, параметры-переменные, параметры-функции/процедуры и глобальные переменные. В данной главе также изучаются рекурсивные подпрограммы.

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

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

Материал излагается последовательно: начиная с операторов и простых типов данных и заканчивая динамическими структурами данных, программами, процедурами и функциями таким образом, что синтаксис и семантика языка ПАСКАЛЬ понятны и легко усваиваются. Каждая часть теоретического материала сопровождается рядом примеров, упражнений и контрольных вопросов. Предполагается, что учащийся введет в компьютер и запустит на выполнение предложенные программы, ответит на вопросы и, где необходимо, самостоятельно напишет соответствующие программы.

Все программы, включенные в учебник, были проверены и отлажены в среде программирования Turbo PASCAL 7.0.

1

Page 2: Pascal material

Глава 1Словарь и синтаксис языка

1.1. ЗНАКОМСТВО С ЯЗЫКОМ ПАСКАЛЬ

Рассмотрим следующую программу:

program Р12 {Сумма целых чисел x, y, z:}5 (Введите целые числа:)8 (Сумма введенных чисел:)

Числа 1, 2, 3, …, 10 в левой части страницы не являются частью программы языка ПАСКАЛЬ. Они служат только для объяснения значения каждой строки.

Строка 1. Слово program является зарезервированным словом языка, а Р1 – словом, определяемым пользователем. Зарезервированные слова служат для составления программ, а слова, определяемые пользователем, – для имен переменных, констант, подпрограмм, программ и т.д.

Строка 2. Данная строка является пояснением, комментарием. Комментарий заключается в фигурные скобки: { }. Комментарий ни коим образом не влияет на работу программы и предназначен исключительно для пользователя.

Строка 3. Зарезервированное слово var (variable –переменная) описывает переменные x, у, z и s, используемые в программе. Слово integer (целый) указывает тип соответствующих переменных. Таким образом, переменные x, у, z и s могут принимать только целые значения. Данная строка образует раздел описания.

Строка 4. Зарезервированное слово begin (начало) означает начало выполняемой части программы – раздела операторов.

Строка 5. Вывод сообщения на стандартное устройство вывода, обычно на экран. Слово writeln (write line – запись и переход на новую строку) представляет собой обращение к стандартной процедуре, аргументом которой является текст сообщения:

Введите целые числа x, у, z:

Отметим, что апострофы не будут видны на экране.

Строка 6. Считывание трех чисел со стандартного устройства ввода, как правило, – с клавиатуры. Числа печатаются в одной строке и отделяются друг от друга одним или несколькими пробелами. После введения последнего числа нажимается клавиша <ENTER>. Числа считываются в переменные x, у, z. Слово readln (read line – считывание и переход на новую строку) представляет собой обращение к стандартной процедуре. Аргументами данной процедуры являются имена переменных, в которых запоминаются введенные целые числа.

Строка 7. Оператор присваивания. Переменной s присваивается значение x + y + z.Строка 8. Вывод сообщения Сумма введенных чисел: на стандартное устройство вывода.Строка 9. Вывод значения переменной s на стандартное устройство вывода.Строка 10. Зарезервированное слово end означает конец раздела операторов, а точка – конец

программы.Таким образом, программа на языке ПАСКАЛЬ состоит из следующих частей:

заголовок, в котором указывается имя программы;

2

Page 3: Pascal material

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

раздел операторов, содержащий команды, которые должен выполнить компьютер в определенном порядке.

Вопросы и упражнения1. Введите и запустите на выполнение программу Р1.2. Из каких основных частей состоит программа языка ПАСКАЛЬ?3. Введите и запустите на выполнение следующую программу:

Program Р2{Вывод предописанной константы MaxInt }

4. Укажите заголовок, раздел описаний и раздел операторов программы Р2. Объясните назначение каждой строки данной программы.

5. Напишите программу, которая выводит на экран квадрат и куб целого числа, введенного с клавиатуры.

1.2. МЕТАЯЗЫК БНФ

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

Ясно, что синтаксис любого языка программирования может быть описан с помощью языка общения между людьми, например русского, румынского, английского, французского и т.д. Однако такого рода описание является объемным и может оказаться двусмысленным. Для лаконичного и точного описания синтаксиса языков программирования были разработаны специальные языки, называемые метаязыками. Самым распространенным метаязыком является метаязык БНФ – формы Бэкуса-Наура.

Метаязык БНФ использует следующие символы: терминальные символы – те символы, из которых состоит программа на языке ПАСКАЛЬ;нетерминальные символы – те символы, которые обозначают грамматические единицы

(конструкции) языка.Нетерминальные символы записываются между знаками “<” и “>”.Например, цифры 0, 1, 2 …9, буквы A, B, C, …, Z являются терминальными символами, а

<Цифра>, <Буква> являются нетерминальными символами. Описание синтаксиса языка ПАСКАЛЬ состоит из совокупности металингвистических формул.Под металингвистической формулой будем понимать конструкцию, состоящую из двух частей:

левой и правой, разделенных символами: “::=”, что означает: «равно по определению». В левой части формулы находится нетерминальный символ.

В правой части металингвистической формулы с помощью символа “|”, означающего «или», описываются всевозможные варианты определения нетерминального символа.

Например, формула

<Цифра> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

определяет грамматическую единицу <Цифра> как один из терминальных символов: 0, 1, …, 9.Таким же образом интерпретируется металингвистическая формула: <Буква>:: =

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

В частности, формула

3

Page 4: Pascal material

<Ид> ::= <Буква> | <Буква> <Цифра> определяет грамматическую конструкцию <Ид> как букву или букву, за которой следует цифра.

Например: a, a1, c3, x4, d, e8.В некоторых ситуациях возможные варианты определения нетерминального символа могут

повторяться несколько и даже ноль раз, тогда они заключаются в фигурные скобки: { }.Например, формула

<Целое без знака> ::= <Цифра>{<Цифра>}

определяет нетерминальный символ <Целое без знака> как непустую последовательность цифр. Последовательности 0, 0000, 001, 1900, 35910 соответствуют данному определению, а последовательность 3а5910 – не соответствует.

Формула

<Идентификатор> ::= <Буква>{<Буква> | <Цифра>}

указывает, что идентификатор всегда начинается с буквы, после которой может следовать конечная последовательность из букв и цифр. Например, a, a1, a1b, a23x, a14bxz соответствуют данной формуле, а 2а – не соответствует.

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

Например, формула

<Масштабный множитель> ::= [+ | ] <Целое без знака>

определяет масштабный множитель как целое число без знака, которому может предшествовать + или . Например: 1, +1, 1, 20, +20, 20, + 003 соответствуют данной формуле, а 35 – не соответствуют.

Обратим внимание на то, что символы [, ], {, } принадлежат метаязыку и их не следует путать с соответствующими символами, используемыми в программах на языке ПАСКАЛЬ.

Вопросы и упражнения

1. Дайте объяснение терминам: синтаксис и семантика.2. Для чего предназначен метаязык?3. Как определяется синтаксис произвольного языка с помощью метаязыка БНФ?4. Синтаксис некоторого простого языка описан с помощью следующих металингвистических

формул:<Цифра> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9<Число> ::= <Цифра>{<Цифра>}<Знак> ::= + | <Арифметическое выражение> ::= <Число>{<Знак> <Число>}

Какие из следующих арифметических выражений являются числами?01

Какие из следующих арифметических выражений являются правильными?0+1

5. Синтаксис простого языка общения компьютер-пользователь определяется следующим образом:<Диск> ::= A: | B: | C: | D: | E: <Список параметров> ::= <Диск>{,<Диск>}

4

Page 5: Pascal material

<Название команды> ::= Считывание | Копирование | Форматирование<Команда> ::= <Название команды> <Список параметров>

Укажите синтаксически правильные команды:

а) Считывание е) Копирование А: В:б) Считывание А: ж) Считывание Dв) Копирование F: з) Форматирование D:, Fг) Копирование А:, и) Копирование E:, A:,д) Форматирование D:, E: к) Копирование F:, A:

1.3. СИНТАКСИЧЕСКИЕ ДИАГРАММЫ

Синтаксические диаграммы более наглядно описывают синтаксис языка программирования. Диаграммы представляются в соответствии с формулами БНФ.

Каждому терминальному символу соответствует круг или овал, в который вписывается соответствующий символ. Нетерминальные символы заключаются в прямоугольник. Овалы и прямоугольники объединяются согласно диаграммам на рис.1.1.

Конкатенация (присоединение)АльтернативаНеобязательное присутствиеПовторение

Рис. 1.1. Формулы БНФ, представленные синтаксическими диаграммами

На рис. 1.2 показаны синтаксические диаграммы для грамматических единиц <Целое без знака>, <Идентификатор> и <Масштабный множитель>, определенных в предыдущем параграфе. Отметим, что каждому пути синтаксической диаграммы соответствует синтаксически правильная последовательность терминальных символов.

<Целое без знака>

Цифра

<Идентификатор>

БукваБукваЦифра

<Масштабный множитель>

Целое без знака

Рис. 1.2. Синтаксические диаграммы <Целое без знака>, <Идентификатор> и <Масштабный множитель>

5

Page 6: Pascal material

Вопросы и упражнения 1. Для чего предназначены синтаксические диаграммы?2. Как терминальные и нетерминальные символы представляются в синтаксических диаграммах?3. Как представляются формулы БНФ в синтаксических диаграммах?4. Представьте в виде синтаксических диаграмм:

<Цифра> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9<Число> ::= <Цифра>{<Цифра>}<Знак> ::= + | <Арифметическое выражение> ::= <Число>{<Знак> <Число>}

5. Представьте в виде синтаксических диаграмм:

<Диск> ::= A: | B: | C: | D: | E: <Список параметров> ::= <Диск>{,<Диск>}<Название команды> ::= Считывание | Копирование | Форматирование<Команда> ::= <Название команды> <Список параметров>

6. На рис. 1.3 представлены синтаксические диаграммы, которые определяют грамматическую единицу <Дробное число>. Определите, какие из приведенных ниже примеров соответствуют данным диаграммам:

0.1+0.1

7. Напишите формулы БНФ, соответствующие синтаксическим диаграммам рис.1.3.

<Цифра>

<Последовательность цифр>Цифра

<Дробное число>Последовательность цифр

Последовательность цифр

Рис. 1.3. Синтаксические диаграммы <Цифра>, <Последовательность цифр>, <Дробное число>

1.4. АЛФАВИТ ЯЗЫКА

Алфавит языка ПАСКАЛЬ состоит из следующих символов кода ASCII (American Standard Code for Information Interchange):

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

В некоторых конструкциях языка могут использоваться и буквы национальных алфавитов, например буквы ă, â, î, ş, ţ румынского алфавита, буквы русского алфавита и т. д.

6

Page 7: Pascal material

1.5. СЛОВАРЬ ЯЗЫКА

Самые простые элементы, составленные из символов и имеющие лингвистическое значение, называются лексемами или лексическими единицами. Они и составляют словарь языка ПАСКАЛЬ.

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

1.6. СПЕЦИАЛЬНЫЕ СИМВОЛЫ И КЛЮЧЕВЫЕ СЛОВА

Специальные символы состоят из одного или двух символов:+ плюс < меньше минус > больше* звездочка [ левая квадратная скобка/ наклонная черта ] правая квадратная скобка= равно ( левая круглая скобка, запятая ) правая круглая скобка: двоеточие ; точка с запятой. точка ^ степень@ коммерческое at $ доллар

{ левая фигурная скобка <= меньше либо равно} правая фигурная скобка >= больше либо равно# номер : = присваивание. . многоточие < > не равно(* эквивалент фигурной скобки { (. эквивалент скобки [*) эквивалент фигурной скобки } .) эквивалент скобки ]

Отметим, что специальные символы, составленные из двух символов, например <= или : =, не допускают “вклинивания” в них разделителей.

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

7

Page 8: Pascal material

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

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

следующими формулами БНФ:

<Специальный символ><Ключевое слово> | <Эквивалентный символ>

<Эквивалентный символ><Ключевое слово>

Символы {, }, [ и ], используемые в формулах БНФ, являются, одновременно и элементами языка ПАСКАЛЬ. Чтобы избежать двусмысленности, данные символы, как элементы словаря, могут быть представлены через эквивалентные символы (*, *) и соответственно (., .).

Вопросы и упражнения

1. Выучите ключевые слова языка ПАСКАЛЬ.2. В чем разница между специальными символами и символами?3. Постройте синтаксические диаграммы для лексических единиц: <Специальный символ>,

<Эквивалентный символ>, <Ключевое слово>.

1.7. ИДЕНТИФИКАТОРЫ

Идентификаторы – это лексические единицы, которые выступают в качестве имен переменных, констант, функций, программ и т.д.

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

Напомним формулы БНФ, определяющие лексическую единицу <Идентификатор>:<Цифра><Буква><Идентификатор> ::= <Буква> {<Буква> |<Цифра>} Примеры идентификаторов:x y z

Прописные и строчные буквы в грамматических конструкциях языка ПАСКАЛЬ, за исключением строк, считаются эквивалентными. Таким образом, следующие идентификаторы являются эквивалентными:

x и X, у и У … и.т.д.

Использование прописных и строчных букв позволяет записывать идентификаторы в форме, удобной для чтения, например:

ListaElevilorОтметим, что в основных конструкциях языка ПАСКАЛЬ не используются буквы ă, â, î, ş, ţ

румынского алфавита. Буквы русского алфавита заменяются латинскими буквами SuprafataPloscostiVes

8

Page 9: Pascal material

Вопросы и упражнения

1. Постройте синтаксические диаграммы для грамматических единиц <Цифра>, <Буква> и <Идентификатор>.

2. Какие из приведенных ниже примеров подходят под определение лексической единицы <Идентификатор>:

х1Х1

Для идентификаторов укажите соответствующий путь из синтаксической диаграммы <Идентификатор>.

3. Найдите пары эквивалентных идентификаторов:х101уа15

4. Для чего предназначены идентификаторы в программах языка ПАСКАЛЬ?5. Для нахождения корней х1, х2 квадратного уравнения ах2 + bх + с = 0 сначала находится

дискриминант d. Предложите несколько вариантов представления коэффициентов а, b, с, дискриминанта d и решений х1, х2 посредством идентификаторов.

1.8. ЧИСЛА

Числа могут быть целыми или вещественными. Обычно используется десятичная система счисления. На рис. 1.4 показаны синтаксические диаграммы для лексических единиц <Целое число> и <Вещественное число>.

<Целое без знака>Цифра

<Целое число>Целое без знака

<Масштабный множитель>Целое число

<Вещественное число>Целое число Масштабный множитель

Целое без знака

Рис. 1.4. Синтаксические диаграммы <Целое число> и <Вещественное число>

Примеры целых чисел:23318

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

Примеры вещественных чисел:3.1415283.19

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

Примеры:обычная форма обозначение на языке ПАСКАЛЬОчевидно, что 8.12е-05, 812е-7, 0.812е-4, 81.2е-6 имеют одно и то же значение 8,12 10-5 .

9

Page 10: Pascal material

Вопросы и упражнения

1. Какие из приведенных ниже примеров подходят под определение лексической единицы <Целое число> ?

- 418 Найдите целые числа с одним и тем же значением.

2. С помощью синтаксических диаграмм рис. 1.4 напишите формулы БНФ для определения лексической единицы <Целое число>.

3. Какие из приведенных ниже примеров подходят под определение лексической единицы: <Вещественное число> ?

3.14

Найдите вещественные числа, которые имеют одно и то же значение. Запишите данные числа в обычном виде.

4. С помощью синтаксических диаграмм рис. 1.4 напишите формулы БНФ для определения лексической единицы <Вещественное число>.

5. Укажите на синтаксических диаграммах рис. 1.4 пути, которые соответствуют следующим числам:

-418

1.9. СТРОКИ

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

Например:В отличие от других лексических единиц языка ПАСКАЛЬ в строках могут использоваться и

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

Например:‘Строка’‘Английский язык’‘Поверхность’‘Число попыток’

Лексическая единица <Строка> определяется с помощью следующих формул БНФ:<Строка> :: = ‘<Элемент строки> {<Элемент строки>}’<Элемент строки> ::= ‘ ‘ | <Любой печатный символ>

Синтаксическая диаграмма лексической единицы <Строка> показана на рис. 1.5.

Вопросы и упражнения

1. Укажите на синтаксических диаграммах рис. 1.5. пути, которые соответствуют следующим строкам:‘переменная z’’’’’‘Символы ’’x’’, ’’y’’’‘Лексические единицы’

10

Page 11: Pascal material

2. Какие из приведенных ниже примеров подходят под определение лексической единицы <Строка>:

‘Целое число’ ‘Год 1997’‘Конец программы’ ‘Квадратный корень’‘АПОСТРОФ’ ‘Год ’97’‘‘х’’ ‘Список телефонов’‘функция’ ’’’

<Строка> <Элемент строки>

<Элемент строки> <Любой печатный символ>

Рис. 1.5. Синтаксическая диаграмма <Строка>

1.10. МЕТКИ

Метка представляет собой целое число без знака в диапазоне от 0 до 9999, которое используется для того, чтобы ссылаться на операторы языка ПАСКАЛЬ.

Например:1 100 999 582 1004

Очевидно, что формула БНФ, которая определяет данную лексическую единицу, имеет вид: <Метка> ::= <Целое без знака>

1.11. ДИРЕКТИВЫ

Лексическая единица <Директива> определяется точно так же, как идентификатор:

<Директива> ::= <Буква> {<Буква> | <Цифра>}

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

forward

Данная директива используется при описании некоторых процедур и функций, определенных пользователем.

1.12. РАЗДЕЛИТЕЛИ

Любая программа на языке ПАСКАЛЬ состоит из лексических единиц и разделителей. В языке ПАСКАЛЬ в качестве разделителей используются пробел, конец строки (возврат каретки) и комментарий.

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

Например:

11

Page 12: Pascal material

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

Например:Правильно Неправильно

Комментарием является последовательность символов, заключенная в фигурные скобки: {}.

Например:{ Программа, разработанная Александром Ивановым }{ Введение исходных данных }{ Исходные данные вводятся с клавиатуры. Результаты будут выведены на экран и распечатаны на принтере через 3-4 минуты }

Комментарии никак не влияют на работу программ языка ПАСКАЛЬ и используются для уточнений, пояснений, дополнительной информации и т.д. Очевидно, что комментарии предназначены не для компьютера, а для лиц, читающих соответствующую программу.

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

Глава 2

ПРОСТЫЕ ТИПЫ ДАННЫХ

2.1. КОНЦЕПЦИЯ ДАННЫХ

12

Page 13: Pascal material

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

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

10000001111

В программах на языке ПАСКАЛЬ данные представляются в виде величин: переменных и констант. Для того чтобы избавить пользователя от деталей внутреннего представления данных, в языке ПАСКАЛЬ используются различные типы данных.

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

Например, в версии Turbo PASCAL 7.0 тип integer включает множество целых чисел{-32768, -32767, …, -2, -1, 0, 1, 2, …, 32767}.

К данным числам можно применять следующие операции:+ сложение; вычитание;* умножение;mod остаток от деления;div целочисленное деление и др.

Тип данных real (вещественный) включает подмножество множества вещественных чисел, операции +, , *, / (деление) и др.

Операции mod и div, допустимые в типе данных integer, недопустимы в типе данных real.Концепция данных, реализованная в языке ПАСКАЛЬ, предполагает следующее:1) каждая величина (переменная или константа), используемая в программе должна иметь

определенный тип данных;2) тип переменной определяет множество значений, которые она может принимать, и операции,

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

программе: integer, real, char (символьный), boolean (логичекий), text (текстовый) и др.;4) на основании известных типов данных программист может создавать новые типы,

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

Тип константы объявляется неявно через ее текстовую форму. Например, 10 является числом типа integer, а 10.0 – числом типа real.

Вопросы и упражнения

1. Как представляются данные в машинном коде компьютера? Укажите преимущества и недостатки такого представления.

2. Как представляются данные в программах на языке ПАСКАЛЬ? Укажите разницу между переменной и константой.

3. Объясните значение термина тип данных. Приведите примеры.4. Как указывается тип переменных?5. Определите тип переменных r, s, t, x, y и z из следующего описания:

var

13

Page 14: Pascal material

6. Опишите переменные a, b и c как переменные целого типа, а p и q как переменные текстового типа.

7. Определите тип следующих чисел:

-301

2.2. ТИП ДАННЫХ integer (целый)

Множество значений типа данных integer состоит из элементов подмножества целых чисел, определяемого при реализации. Максимальное значение определяется константой MaxInt, известной любой программе на языке ПАСКАЛЬ. Обычно минимальным значением, в изучаемом типе данных, является –MaxInt или – (MaxInt +1).

Приведенная ниже программа выводит на экран значение предописанной константы MaxInt.

Program P2;{Вывод предописанной константы}

В компьютерах IBM PC работающих с версией Turbo PASCAL 7.0 константа MaxInt принимает значение 32767, а множеством значений типа integer является:

{-32768, -32767, …, -2, -1, 0, 1, 2, …, 32767}.Операции, которые можно применять к целым значениям: +, , mod, div и др. Результаты данных

операций можно увидеть с помощью программы Р3.

Program P3;{Операции с данными типа integer}(‘Введите целые числа’)

Очевидно, что результаты операций: +, , * над целыми числами также должны принадлежать множеству значений типа данных integer. Если программист нарушает данное правило, появляются ошибки переполнения. Эти ошибки будут обнаружены в процессе компиляции или при выполнении соответствующей программы. Для пояснения приведем программы Р4 и Р5:

Program P4;{Ошибка переполнения, обнаруженная в процессе компиляции }{Ошибка, x>MaxInt}

Program P5;{Ошибка переполнения, обнаруженная в процессе выполнения }{Ошибка, у>MaxInt} Вопросы и упражнения

1. Укажите множество значений типа данных integer. Какие операции можно применять к данным значениям?

2. Когда появляются ошибки переполнения? Как могут быть обнаружены данные ошибки?3. Определите значение константы MaxInt версии языка ПАСКАЛЬ, в которой работаете.4. Даны следующие программы:

Program P6;{Ошибка переполнения}

Program P7;{Ошибка переполнения}

14

Page 15: Pascal material

Когда будут обнаружены ошибки переполнения: на этапе компиляции или выполнения?

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

2.3. ТИП ДАННЫХ real (вещественный)

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

Например, в версии Turbo PASCAL 7.0 областью допустимых значений вещественного типа является 2,910-39, …, 1,71038 , числа указаны с точностью до 11-12 десятичных цифр.

В следующей программе переменным х, у и z присваиваются соответственно значения 1,1, 6,14108 и 90,310-29, которые затем выводятся на экран.

Program P8;{Данные вещественного типа}Напомним, что при записи вещественных чисел десятичная запятая заменяется точкой, а степень

числа 10 представляется масштабным множителем (см. параграф 1.8.).Операции, которые можно применять к значениям вещественного типа: +, , * и / (деление) и др.Операции над вещественными числами в общем случае являются приближенными из-за

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

Свойства операций +, , * и / могут быть изучены с помощью следующей программы:

Program P9;{Операции с данными типа real}(‘Введите вещественные числа х, у:’)

В таблице 2.1 представлены данные, которые выводятся на экран программой Р9 (версия Turbo PASCAL 7.0) для некоторых значений переменных х и у. Отметим, что результаты операций х+у и ху в первых двух строках таблицы 2.1 являются точными. Для значений х = 1,0 , у = 1,010-11 (третья строка таблицы) результат сложения – приближенный, а вычитания – точный. Оба результата из строки 4 являются приближенными. Для значений х = у = 1,71038 (строка 5) при выполнении операции сложения имеет место переполнение. Для значений х = 3,110-39, у = 3,010-39 (строка 6) результат сложения – точный, а вычитания – приближенный.

Таблица 2.1. Результаты программы Р9depăşire - переполнение

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

Вопросы и упражнения

1. Как записываются вещественные числа на языке ПАСКАЛЬ?2. Определите множество значений вещественного типа данных в версии языка ПАСКАЛЬ, в

которой работаете. Какова точность соответствующих чисел?3. Какие операции можно применять к данным типа real? Являются ли эти операции точными?4. Запустите на выполнение программу Р9 для следующих значений переменных х, у:

а) х = 2,0

15

Page 16: Pascal material

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

5. Каковы причины ошибок вычисления при работе с данными типа real?

2.4 ТИП ДАННЫХ boolean (булевский)

Значениями типа данных boolean (логический) являются истинностные значения false (ложь) и true (истина). В ниже приведенной программе переменной х последовательно присваиваются значения false и true, выводимые в последствии на экран.

Program P10;{Данные типа boolean}

Логические операции, которые можно применять к данным булевского типа: not отрицание (логическая инверсия, логическая операция НЕ);and конъюнкция (логическое произведение, логическая операция И);or дизъюнкция (логическая сумма, логическая операция ИЛИ);

Таблицы истинности данных операций представлены на рис.2.1.

Рис. 2.1. Таблицы истинности логических операций not, and и or

Свойства логических операций not, and и or могут быть изучены с помощью программы Р11.Program P11;{Операции с данными типа boolean}В отличие от переменных целого или вещественного типа текущие значения переменных

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

Вопросы и упражнения

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

not.4. Напишите программу, которая вычисляет значения логической функции z = x&y для

всевозможных значений аргументов x, y.5. Напишите программу, которая выводит на экран значения логической функции z = xy.

2.5. ТИП ДАННЫХ char (символьный)

Множеством значений данного типа является конечное упорядоченное множество символов. Значения такого типа обозначаются символом, заключенным в одиночные кавычки (апострофы), например: ‘A’, ‘B’, ‘C’ и т.д. Если нужен сам апостроф, то он дублируется: ’’’’.

В следующей программе переменной х типа char последовательно присваиваются значения ‘A’, ‘+’ и ’’’’, выводимые на экран.

Program P12;

16

Page 17: Pascal material

{Данные типа char}

Текущие значения переменной типа char могут считываться с клавиатуры с помощью стандартной процедуры readln. Для пояснения представляем программу Р13, которая считывает с клавиатуры, и выводит на экран значения типа char.

Program P13;{Считывание и вывод на экран символов}

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

Как правило, символы конкретной версии языка ПАСКАЛЬ упорядочены согласно таблице кодов ASCII (см. параграф 1.4).

Порядковый номер символа в множестве значений типа char можно найти с помощью стандартной функции ord, например:

ord(‘A’) = 65,ord(‘B’) = 66,ord(‘C’) = 67и т.д.

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

Program P14;{Изучение функции ord}{символ}{порядковый номер}Стандартная функция chr возвращает символ, который соответствует указанному порядковому

номеру. Таким образом,chr(65) = ‘A’chr(66) = ‘B’chr(67) = ‘C’и т.д.Программа Р15 выводит на экран символы, которые соответствуют порядковым номерам,

считанным с клавиатуры.

Program P15;{Изучение функции chr}{порядковый номер}{символ}

Напомним, что расширенное множество ASCII включает 256 символов, пронумерованных: 0, 1, 2, …, 255.

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

Вопросы и упражнения

1. Укажите множество значений типа данных char.2. Как упорядочено множество значений типа char?3. Определите порядковый номер следующих символов:

- десятичные цифры;- прописные буквы латинского алфавита;

17

Page 18: Pascal material

- знаки препинания;- арифметические и логические операции;- управляющие символы;- буквы русского алфавита (если они установлены на Вашем компьютере).

4. Определите символы, которые соответствуют следующим порядковым номерам:77, 109, 79, 111, 42, 56, 91, 123.

5. Напишите программу, которая выдает на экран множество символов компьютера, на котором работаете.

2.6. ПЕРЕЧИСЛЯЕМЫЕ ТИПЫ ДАННЫХ

Типы integer, real, boolean и char, изучаемые до сих пор, являются предопределенными типами, известными любой программе на языке ПАСКАЛЬ. Кроме предопределенных типов данных существуют типы, создаваемые самим программистом, в частности перечисляемые типы.

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

Например:

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

Например:и т.д.Следующая программа выводит на экран порядковые номера значений типа данных Studii. Program P16;{Тип данных Studii}var {порядковый номер} Переменные перечисляемого типа описываются с помощью ключевого слова var. Они могут

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

значение Nu. Порядковые номера этих значений выводятся на экран.Program P17;{Переменные перечисляемого типа}{Переменная типа Culoare}{Переменная типа Raspuns }{порядковый номер}

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

Например, объявление

является неправильным, так как идентификатор Superioare появляется в обоих списках.

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

Вопросы и упражнения

18

Page 19: Pascal material

1. Как определяется перечисляемый тип данных? Укажите множество значений перечисляемого типа данных.

2. Имеет ли значение порядок идентификаторов в списке элементов перечисляемого типа данных?

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

Continente

4. Назовите тип каждой переменной, описанной в программе Р18.Program P18;

Что выдаст на экран данная программа?

5. Даны объявления:type

Какие из следующих операторов являются правильными?а)

6. В программе Р17 перед ключевым словом end вставьте одну из следующих строк:readln(x);writeln(x);

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

2.7. ИНТЕРВАЛЬНЫЕ ТИПЫ ДАННЫХ

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

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

Например:1)Множество значений типа Indice является подмножеством значений предопределенного типа

integer. Множества значений типов Litera и Cifra являются подмножествами предопределенного типа char.

2)Множества значений типов ZiDeLucru и ZiDeOdihna являются подмножествами перечисляемого

типа Zi, определенного пользователем.3)Множества значений типов Т2 и Т3 являются подмножествами перечисляемого типа Т1.Из данных примеров следует, что базовыми типами интервальных типов данных являются

следующие:

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

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

Пример:Program P19;{Значения переменных интервального типа}

19

Page 20: Pascal material

{возможные значения, …}{ возможные значения, …}{ возможные значения, …}{ возможные значения, …}{Ошибка,…}{ Ошибка,…}}{ Ошибка,…}}writeln(‘Конец’).

Программа Р20 показывает, что тип Pozitiv обладает всеми свойствами типа integer.Program P20;{Тип Pozitiv обладает свойствами типа integer }writeln(‘Введите положительные числа х, у:’);

Отметим, что операции +, , *, mod и div базового типа integer применимы к интервальному типу Pozitiv. Но в отличие от переменных типа integer переменные типа Pozitiv не могут принимать отрицательные значения.

Использование интервальных типов данных улучшает наглядность программ и упрощает их проверку.

Следует подчеркнуть, что в языке ПАСКАЛЬ нельзя определять интервальные типы на базе типа real, так как его значения не имеют порядковых номеров.

Вопросы и упражнения

1. Как определяется интервальный тип данных? Укажите множество значений некоторого интервального типа данных.

2. Назовите базовый тип каждого интервального типа:type

3. Какие значения может принимать каждая переменная из следующих описаний:type

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

4. Какие из следующих определений являются правильными? Аргументируйте Ваш ответ.а)

5. Дана следующая программа:Program P21;writeln (‘Введите индексы i, j:’);Для каких значений переменных i, j появятся ошибки выполнения?

6. Рассмотрим программу Р20. После запуска на выполнение пользователь вводит х=1, у=2. Очевидно, что ху=1. Так как значение 1 не принадлежит типу данных Pozitiv, при выполнении командыz:=xyвозникнет ошибка.Укажите команды, при выполнении которых появятся ошибки, если:а)

2.8. ПОРЯДКОВЫЕ ТИПЫ ДАННЫХ

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

1) порядковым номером некоторого числа типа integer является само это число;

20

Page 21: Pascal material

2) порядковыми номерами истинностных значений false и true типа данных boolean являются соответственно 0 и 1;

3) порядковый номер некоторого символа (тип char) определяется его позицией в таблице кодов, обычно АSCII;

4) порядковый номер некоторого значения перечисляемого типа определяется его позицией в списке перечисляемых элементов. Отметим, что элементы списка нумеруются начиная с нуля: 0, 1, 2, … и т.д.

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

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

Программа Р22 выдает на экран порядковые номера значений: -32, true, ‘A’, A и B.

Program P22;{Порядковые номера значений порядкового типа}

К значениям любого порядкового типа можно применять операции отношения:

< меньше;<= меньше или равно;= равно;>= больше или равно;> больше;< > не равно;Результатом операции отношения является значение типа boolean: true или false. При выполнении

таких операций сравниваются не сами значения, а их порядковые номера. Например, при следующем описании:TypeРезультатом операции Verde < Violetявляется true, так как ord(Verde) = 1, ord(Violet)=3, а 1 меньше чем 3.

Результатом операции Galben > Violetявляется false, так как ord(Galben) = 0, ord(Violet)=3, а 0 не больше чем 3.Следующая программа выводит на экран результаты операций отношения для значений Verde и

Violet типа данных Culoare.

Program P23;{Операции отношения над значениями порядкового типа} Для порядковых типов данных существуют стандартные функции pred (предшествующий) и succ

(последующий).Значению с порядковым номером i предшествует значение с порядковым номером i-1. За

значением с порядковым номером i следует значение с порядковым номером i+1. Например, для значений порядкового типа данных Culoare получим:Pred

Очевидно, что наименьшее значение не имеет предшествующего, а наибольшее – последующего. Программа Р24 выводит на экран предшествующие и следующие за ‘B’, 0 и '0'.

Program P24;{Предшествующие и следующие значения}

21

Page 22: Pascal material

Отметим, что значения, предшествующие (следующие за) порядковым значениям 0 (тип integer) и '0' (тип char) не совпадают, так как типы этих значений различны.

Тип данных real не является порядковым типом. Следовательно, к вещественным значениям нельзя применять функции ord (возвращает порядковый номер), pred (возвращает предыдущее значение) и succ (возвращает последующее значение). Несоблюдение этого правила приводит к ошибкам.

Вопросы и упражнения

1. Назовите порядковые типы данных. Какими общими свойствами они обладают?2. Как определяются порядковые номера значений некоторого порядкового типа данных?3. Что выведет на экран следующая программа?

Program P25;

4. Удалите из следующей программы строку, содержащую ошибку:

Program P26;{Ошибка}Что будет выведено на экран после запуска модифицированной программы на выполнение?5. Прокомментируйте следующую программу:

Program P27;{Ошибка}Удалите строки, содержащие ошибки. Что будет выведено на экран после запуска модифициро-

ванной программы?

2.9. ОБЪЯВЛЕНИЕ ТИПОВ ДАННЫХ

Язык ПАСКАЛЬ предлагает пользователю предопределенные типы данных: integer, real, boolean, char и др. В случае необходимости пользователь может создать собственные типы данных, например: перечисляемые или интервальные.

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

<Раздел объявления типов>::=type <Описание типа>;{<Описание типа>;}<Описание типа>::=<Идентификатор> = <Тип><Тип>::= <Идентификатор> <Перечисляемый тип>

<Интервальный тип> <Тип-массив> <Тип-запись> <Тип-множество> <Файловый тип> <Ссылочный тип>

<Перечисляемый тип>::=(<Идентификатор>{,<Идентификатор>})<Интервальный тип>::=<Константа> . . <Константа>

Соответствующие синтаксические диаграммы приведены на рис. 2.2.Примеры:

Классификация типов данных языка ПАСКАЛЬ представлена на рис. 2.3. Уже изученные к этому моменту типы указаны на сером фоне.

В некоторых конструкциях языка ПАСКАЛЬ необходимо, чтобы переменные и константы были идентичных или совместимых типов.

Два типа являются идентичными, если они описываются одним и тем же именем типа. Например, пусть

22

Page 23: Pascal material

Здесь типы integer, T4, T5 являются идентичными.Два типа могут быть идентичными и тогда, когда они описываются различными именами, при

условии, что эти имена эквивалентны по свойству транзитивности. Например, пусть

<Раздел объявления типов>type Описание типа ;

<Описание типа> Идентификатор = Тип

<Тип>ИдентификаторПеречисляемый типИнтервальный типТип-массивТип-записьТип-множествоФайловый типСсылочный тип

<Перечисляемый тип> ( Идентификатор )

<Интервальный тип> Константа . . Константа

Рис. 2.2. Синтаксические диаграммы описания типов данных

здесь типы real, T6, T7, и T8 являются идентичными.Два типа называются совместимыми тогда, когда верно хотя бы одно из следующих утверждений:- рассматриваемые типы идентичны;- один тип является интервальным типом второго;- оба типа являются интервальными, с одним и тем же базовым типом.

Например, при следующем объявлении:Type

Типы данныхПростые типы Структурированные типы Ссылочный типПорядковые типы real массивInteger записьBoolean множествоChar файлПеречисляемыйИнтервальный

Рис. 2.3. Классификация типов данных

типы Zi, ZiDeLucru, ZiDeOdihna являются совместимыми. Типы Zi и Culoare не совместимы. Отсюда следует, что допустимы следующие операции отношения:

L<DMi< >DVerde< >Violet и т.д.,

а операции типа

23

Page 24: Pascal material

L<VioletVerde = VS< >Albastru

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

Отметим, что интервальный тип 1 . . 20, перечисляемый тип (Alfa, Beta, Gama, Delta) и интервальный тип Alfa . . Gama не имеют собственных имен.Как правило, анонимные типы используются в программах с небольшим количеством переменных.

Вопросы и упражнения

1. Дана следующая программа:Program P28;{… вычисления, в которых используются}{данные переменные …}writeln(‘Конец’)Укажите типы данных, используемые в программе. Какие значения может принимать каждая переменная, описанная в данной программе? Какие из указанных типов совместимы?

2. Укажите на синтаксических диаграммах рис.2.2 пути, соответствующие описаниям типов данных из программы Р28;

3. Укажите анонимные типы данных, используемые в следующей программе: Program P29;{… вычисления, в которых используются}{данные переменные …}writeln(‘Конец’)Какие значения может принимать каждая переменная, описанная в данной программе?

4. Дано следующее объявление:TypeКакие значения может принимать переменная х? Назовите операции соответствующего типа данных.

5. Когда два типа данных являются идентичными? Приведите примеры.6. Когда два типа данных являются совместимыми? Приведите примеры.7. Дано объявление:

TypeНайдите идентичные и совместимые типы.

2.10. ОПИСАНИЕ ПЕРЕМЕННЫХ

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

<Раздел описания переменных> ::=var <Описание переменной>;{<Описание переменной>;}<Описание переменной>::=<Идентификатор>{,<Идентификатор>}:<Тип>Синтаксические диаграммы рассматриваемых грамматических единиц представлены на рис. 2.4.

<Раздел описания переменных> var Описание переменной ;

24

Page 25: Pascal material

<Описание переменной> Идентификатор : Тип

Рис. 2.4. Синтаксические диаграммы <Раздел описания переменных> и <Описание переменной>

В описании переменных могут использоваться предопределенные типы данных (integer, real, char, boolean и др.) и типы, определяемые пользователем (перечисляемые, интервальные и т.д.).

Примеры:Отметим, что в последнем примере тип переменных z1, m и n описывается непосредственно в

разделе описания переменных. Следовательно, эти переменные принадлежат анонимным типам данных.

Вопросы и упражнения

1. Определите типы переменных из следующей программы:Program P30;{… вычисления, в которых используются}{данные переменные …}writeln(‘Конец’)

Какие значения может принимать каждая переменная? Назовите операции соответствующего типа данных.

2. Укажите на синтаксических диаграммах рис. 2.4 пути, которые соответствуют описанию переменных в программе Р30.

3. Какие сообщения будут выведены на экран в процессе компиляции следующей программы?Program P31;

4. Как описываются переменные анонимных типов данных?

2.11. ОПИСАНИЕ КОНСТАНТ

Известно, что значения любого типа данных могут быть выражены через переменные или константы. Для того чтобы сделать программы более удобными для чтения и модификации, язык ПАСКАЛЬ позволяет представлять константы в виде символических имен. Идентификатор, представляющий константу, называется именем константы или просто константой. Везде, где в программе встречается такое имя, оно заменяется на соответствующее значение.

Константы описываются с помощью следующих грамматических конструкций: <Раздел описания констант>:: =const <Описание константы>;{<Описание константы>;}<Описание константы>:: = <Идентификатор> = <Константа><Константа>:: =[+ | ] <Число без знака>|[+ | ]<Имя константы>|<Последовательность символов>Синтаксические диаграммы данных грамматических единиц представлены на рис. 2.5.

Примеры:

В отличие от переменных, типы которых объявляются явно в соответствующих описаниях, типы констант объявляются неявно через их текстовую форму. В приведенных выше примерах типами констант являются:

а,…

25

Page 26: Pascal material

t, S – строка символов.

В программе Р32 описываются константы Nmax, Nmin, Pi, Separator, Indicator и Mesaj. Значения этих констант выводятся на экран.

Program P32;{Описание констант}{Константа типа integer}{Константа типа integer}{ Константа типа real}{ Константа типа char}{ Константа типа boolean} Mesaj = ‘Проверьте принтер’ {Строка символов}{… вычисления, в которых используются }{ данные константы …}

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

В программе Р33 длина L и площадь круга S вычисляются по формулам:L = 2r;S = r2,

где r является радиусом окружности. Число представлено в виде константы Рi = 3.14.

Program P33;{Длина и площадь круга}writeln (‘Введите радиус r:’); writeln (‘Длина L=’, L); writeln (‘Площадь S=’, S);

<Раздел описания констант>const Описание константы

<Описание константы> Идентификатор = Константа

<Константа>Число без знакаИмя константыПоследовательность символов

Рис. 2.5. Синтаксические диаграммы: <Раздел описания констант>, <Описание константы> и <Константа>

Если пользователю необходимы более точные результаты, изменяется только третья строка программы Р33:

const Pi = 3.141592654.Оставшаяся часть программы остается неизменной.

26

Page 27: Pascal material

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

Вопросы и упражнения

1. Определите типы данных следующих констант:а)

2. Напишите программу, которая выводит на экран значения констант из упражнения 1.3. Покажите на синтаксических диаграммах рис. 2.5 пути, которые соответствуют описаниям

констант из программы Р32.4. Между ключевыми словами begin и end программы Р32 вставьте одну из следующих строк:

Nmax:= 10;readln (Nmax);

Объясните сообщения, выдаваемые на экран в процессе компиляции модифицированной программы.

5. Дана программа:Program P34;

Какие сообщения будут выданы на экран в процессе компиляции?6. Что появится на экране после запуска на выполнение следующей программы:

Program P35;

7. Дана программа:Program P36;

Объясните сообщения, выдаваемые на экран.8. Исключите из следующей программы строку, в которой содержится ошибка.

Program P37;writeln (‘Введите i =’);writeln (‘Введите a =’);

Что появится на экране после запуска этой программы на выполнение?

Глава 3Операторы

3.1. КОНЦЕПЦИЯ ДЕЙСТВИЯ

Программа на языке ПАСКАЛЬ состоит из двух основных частей: раздела описаний и раздела операторов. В разделе описаний описываются данные, которыми будет оперировать программа, а в разделе операторов описываются выполняемые над этими данными действия (операции).

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

1) простые операторы; 2) составные операторы.

Простые операторы не содержат других операторов. Такими операторами являются:- оператор присваивания;- оператор процедуры;- оператор перехода;- пустой оператор. Составные операторы составлены из других операторов. Составными операторами являются:

27

Page 28: Pascal material

- составной оператор begin … end;- условные операторы if и case;- операторы цикла for, while, repeat; - оператор with. Каждому оператору может предшествовать метка. Ссылка на метку указывается в операторе

перехода. Напомним, что метка – это целое число без знака (см. параграф 1.10). Синтаксическая диаграмма <Оператор> показана на рис. 3.1. Напомним, что метка отделяется от

оператора с помощью символа «:» (двоеточие). В программах на языке ПАСКАЛЬ количество операторов в строке не ограничено, один оператор

может занимать одну или более строк, а в одной строке может быть несколько операторов. В качестве разделителя операторов используют символ «;» (точка с запятой).

<Оператор>МеткаОператор присваиванияОператор процедурыОператор перехода gotoПустой операторСоставной оператор begin endОператор ifОператор caseОператор forОператор whileОператор repeatОператор with

Рис. 3.1. Синтаксическая диаграмма: <0ператор> 3.2. ВЫРАЖЕНИЯ

Формулы для вычисления значений представляются на языке ПАСКАЛЬ в виде выражений. Выражения состоят из операндов (констант, переменных, ссылок на функции) и операций. Операции классифицируются следующим образом:

<Мультипликативная операция><Аддитивная операция><Операция отношения>Выражения состоят из факторов (множителей), термов (слагаемых) и простых выражений. Фактор состоит из отдельных переменных, констант без знака, обозначений функций и др.

<Фактор> :: = <Переменная> | <Константа без знака> | <0бозначение функции> | not <Фактор> | (<Выражение>) | <Конструктор множества>

Например:

Терм имеет вид: <Терм> :: = <Фактор> {<Мультипликативная операция> <Фактор>}Например:

Под простым выражением понимается:

<Простое выражение> ::=[+|−] <Терм> {<Аддитивная операция> <Терм>}Например:В свою очередь выражение имеет вид: <Выражение> :: = <Простое выражение> {<Операция отношения> <Простое выражение>}

28

Page 29: Pascal material

Например:Синтаксические диаграммы данных грамматических единиц приведены на рис. 3.2 и 3.3. <Мультипликативная операция><Аддитивная операция><Операция отношения>

Рис. 3.2. Синтаксические диаграммы операций. Выражение, взятое в скобки, преобразуется в фактор. Факторы могут образовывать новые термы,

простые выражения, выражения. Язык ПАСКАЛЬ содержит ряд стандартных функций, известных любой программе. Эти функции представлены в таблице 3.1.

ФакторПеременнаяКонстанта без знакаОбозначение функцииNot ФакторВыражениеКонструктор множества

ТермФакторМультипликативная операция

Простое выражениеТермАддитивная операция

ВыражениеПростое выражениеОперация отношения

Рис. 3.3. Синтаксические диаграммы для определения выраженийТаблица 3.1. Стандартные функции языка ПАСКАЛЬ

НАЗВАНИЕ ФУНКЦИИ ОБОЗНАЧЕНИЕ В ЯЗЫКЕ ПАСКАЛЬАбсолютное значениеСинусКосинусАрктангенсКвадрат хКвадратный корень из хЭкспоненциальная функцияНатуральный логарифмОкругление вещественного числаЦелая часть вещественного числаПроверка числа i на нечетность(возвращает значение false, если i – четно и true в противном случае) Порядковый номерОпределение предшествующего элемента

29

Page 30: Pascal material

Определение последующего элементаСимвол с порядковым номером iПризнак конца файлаПризнак конца строки

Вопросы и упражнения

1. Запишите следующие выражения согласно правилам языка ПАСКАЛЬ: а)

2. Укажите на синтаксических диаграммах рис. 3.3 пути, которые соответствуют следующим

выражениям: а)

3. Переведите выражения на языке ПАСКАЛЬ в обычные: а)

4. Какие из следующих выражений на языке ПАСКАЛЬ содержат ошибки? Для ответа воспользуйтесь синтаксическими диаграммами рис. 3.3.

а)

3.3. ВЫЧИСЛЕНИЕ ВЫРАЖЕНИЙ

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

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

Таблица 3.2. Приоритеты операций языка ПАСКАЛЬКАТЕГОРИЯ ОПЕРАЦИЯ ПРИОРИТЕТУнарные операции Первый (наивысший)Мультипликативные операции ВторойАддитивные операции ТретийОперации отношения Четвертый (наименьший)Например:Пусть х=2 и у=6. Тогда:Отметим, что составные части выражения (рис. 3.3) вычисляются в следующем порядке:

1) факторы;2) термы; 3) простые выражения;4) само выражение.

Текущее значение выражения можно вывести на экран с помощью процедуры writeln:Программа Р38 выводит на экран результаты вычисления выражений х*у+z и х+у<z–1.0. Текущие

значения переменных х, у и z считываются с клавиатуры.

30

Page 31: Pascal material

Program P38;{Вычисление выражений}writeln(‘Введите вещественные числа x,y,z’); Вопросы и упражнения

1. Пусть х=1, у=2 и z=3. Вычислите следующие выражения:a)

2. Каковы правила вычисления выражений на языке ПАСКАЛЬ? 3. Назовите приоритеты операций языка ПАСКАЛЬ.4. Укажите порядок вычисления выражений. 5. Напишите программу, которая вычисляет выражения в) и ж) из упражнения 1. Текущие

значения вещественных переменных х, у и z считываются с клавиатуры. 3.4. ТИП ВЫРАЖЕНИЙ

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

Типы результатов операций указаны в таблице 3.3. Таблица 3.4 содержит тип результатов стандартных функций языка ПАСКАЛЬ.

Таблица 3.3. Типы результатов операцийОПЕРАЦИЯ ТИП ОПЕРАНДОВ ТИП РЕЗУЛЬТАТА+, -, *

Один – integer, другой – real /DivModNot, and, or

Идентичные типыСовместимые типыОдин – integer, другой – real

Независимо от типа операндов операция «/» (деление) возвращает результат типа real, а операции отношения возвращают результат типа boolean.

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

Например, рассмотрим выражение: (х>i) or (6*i < sin(х/у)),

в котором i – переменная типа integer, а х и у – переменные типа real. Определим тип составных частей и всего выражения в порядке выполнения вычислений: a)

Таблица 3.4. Типы результатов стандартных функций

31

Page 32: Pascal material

ФУНКЦИЯ ТИП АРГУМЕНТА ТИП РЕЗУЛЬТАТАаbs(х) integer или real Совпадает с типом хsin(х) integer или real realcos(х) integer или real realarctan(х) integer или real realsqr(Х) integer или real Совпадает с типом хsqrt(х) integer или real realехр(х) integer или real realln(х) integer или real realround(х) real integertrunc(х) real integerodd(i) real booleanord(v) Порядковый integerpred(v) Порядковый Совпадает с типом vsucc(v) Порядковый Совпадает с типом vchr(i) integer chareof(f) Файловый booleaneoln(f) Файловый boolean

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

Например, при следующих описаниях:{интервал типа integer}{интервал типа integer}

Имеем:выражение тип выраженияи т.д.В зависимости от типа выражения подразделяются на:- арифметические (integer или real); - порядковые (integer, boolean, char, перечисляемые); - логические (boolean); Как правило, арифметические выражения используются в вычислениях (оператор присваивания),

порядковые выражения – в операторах case и for, а логические – в операторах if, repeat и while.

Вопросы и упражнения

1. Как определяется тип выражения? 2. При наличии описаний: var определите типы следующих выражений:

a)3. Тип выражения можно узнать из текстовой формы результатов, выведенных на экран с

помощью оператора: writeln(<выражение>); Например: результат, выведенный на экран тип выражения

Напишите соответствующие программы и на основании текстовой формы результатов, выведенных на экран, определите типы следующих выражений:

а)

32

Page 33: Pascal material

где переменные х и у являются переменными типа real (вещественнный).

4. Даны описания: var найдите типы следующих выражений: a)

3.5. ОПЕРАТОР ПРИСВАИВАНИЯ

Оператор присваивания имеет вид: <Оператор присваивания>: = <Переменная>: = <Выражение>При выполнении оператора присваивания происходит следующее: а) вычисляется выражение, стоящее в правой части; б) полученное значение присваивается переменной, стоящей в левой части.Например:Отметим, что символ ": =" (читается «присваивание») означает присваивание и не стоит путать его

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

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

справедливо одно из следующих утверждений: 1) типы переменной и результата – идентичны; 2) тип результата является интервалом типа переменной; 3) оба типа являются интервалами одного и того же типа, а тип результата является интервалом

типа переменной; 4) тип переменной – real, а тип результата – integer или его интервал. В качестве примера рассмотрим следующую программу:Program P39;{совместимость с точки зрения присваивания}{интервал типа integer}{интервал типа integer}{верно для 1<= k <=10}{верно для 5<= m <=15}{верно для -4<= n <=5}{верно для 3<= n <=13}Программа будет работать без ошибок только при следующих значениях на входе:1 k 10;5 m 15;3 n 5.Очевидно, что в программе Р39 операторы видаk:= x;i:=x+1;j:=sin(i) и т.д.

являются ошибочными, так как тип выражений х, х + 1, sin(i) – real, а тип переменных k, i, j – integer или его интервал.

Вопросы и упражнения1. Как выполняется оператор присваивания? 2. Объясните термин «совместимость с точки зрения присваивания».3. Даны следующие описания: type Какие из следующих выражений являются правильными? a)

33

Page 34: Pascal material

4. При каких значениях переменной j программа Р40 будет работать без ошибок?Program P40;

3.6. ОПЕРАТОР ПРОЦЕДУРЫ

Процедура это подпрограмма, к которой, в процессе выполнения программы, можно обращаться произвольное количество раз. Каждая процедура имеет свое имя, например: readln, writeln, CitireDate, A15 и т. д. Язык ПАСКАЛЬ включает ряд стандартных процедур, известных любой программе: read, readln, write, writeln, get, put, new и т. д. В дополнение к ним программист может создавать собственные процедуры.

Оператор процедуры вызывает процедуру с соответствующим именем. Оператор имеет вид:<Оператор процедуры>:: =<Имя процедуры> [<Список формальных параметров>]; <Имя процедуры> :: = <Идентификатор> <Список формальных параметров> :: = (<Формальный параметр> {, <Формальный параметр>})Синтаксические диаграммы данных металингвистических формул представлены на рис. 3.4.Как правило, <Формальный параметр> является выражением.Например:Тип каждого формального параметра и порядок его появления в списке указываются в разделе

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

Оператор процедурыИмя процедуры

Список фактических параметров

Список фактических параметровФактический параметр

Имя процедуры Идентификатор

Рис. 3.4. Синтаксические диаграммы оператора процедуры

Вопросы и упражнения

1. Для чего необходим оператор процедуры?2. Даны следующие операторы:

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

3. Укажите на синтаксических диаграммах рис. 3.4 пути, которые соответствуют операторам из упражнения 2.

3.7. ВЫВОД АЛФАВИТНО-ЦИФРОВОЙ ИНФОРМАЦИИ НА ЭКРАН В обычных версиях языка ПАСКАЛЬ экран монитора является стандартным устройством вывода.

Как правило, экран разделяется на условные зоны, называемые символьными. Обычно указанные зоны образуют 25 строк по 85 символов в каждой. Зона, в которой будет выведен текущий символ, обозначается курсором.

Данные выводятся на экран с помощью процедуры write(x) или writeln(x).

34

Page 35: Pascal material

Процедура write(х1, x2, ...,хn) эквивалентна последовательности write(х1); write(х2); ...; write(xn). Фактические

параметры процедур write или writeln называются параметрами вывода. Они могут иметь следующий вид:

ее: wе: w : f

где е – выражение типа integer, boolean, char или строкового типа, значение которого нужно вывести на экран; w и f являются выражениями типа integer, и называются параметрами размера поля. Значение выражения w указывает минимальное число символов, используемых для вывода значения е; если для представления значения е требуется меньше чем w символов, то ему предшествует такое число пробелов, чтобы было записано точно w символов (рис. 3.5).

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

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

Например('Сумма введенных чисел');('Сумма =', s);

Рис. 3.5. Значение параметра размер поля wРис. 3.6. Значение параметра размер поля f

Вопросы и упражнения1. Для чего нужен параметр размера поля? 2. Как называются фактические параметры процедуры write или writeln? 3. Определите форматы данных, выводимых на экран следующими программами:

Program P41;{Вывод данных типа integer}

Program P42;{Вывод данных типа real}

Program P43;{Вывод данных типа boolean}

Program P44;{Вывод строк символов}

4. Напишите программу, которая выводит на экран значения 1234567890, 123, 123.0 и true следующим образом:

1234567890

3.8. ВВОД ДАННЫХ С КЛАВИАТУРЫ

35

Page 36: Pascal material

Как правило, стандартным устройством ввода является клавиатура. Ввод данных с клавиатуры выполняется с помощью стандартных процедур read или readln. Список фактических параметров процедуры read или readln может включать переменные типа integer, real, char и строкового типа.

Процедураread(х)

выполняет следующие действия: если переменная х является переменной типа integer или real, тогда считывается вся строка символов, представляющая целое или вещественное значение; если переменная х является переменной типа char, то процедура считывает только один символ.

Процедураread(х1, x2, ...,хn)

эквивалентна последовательности read(х1); read(х2); ...; read(xn).

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

Например, рассмотрим программу:Program P45;{Считывание чисел с клавиатуры}writeln ('Были введены: ');

в которой считываются с клавиатуры значения переменных i, j, х, у. После запуска программы на выполнение пользователь набирает:

1 На экран будет выведено:Были введены:Если данные вводить одной строкой, то результат не изменится: 1 2 3.0 4.0<ENTER> В случае необходимости целые числа, введенные пользователем, переводятся в вещественные

значения. Например, в программе Р45 пользователь может набрать на клавиатуре 1 2 3 4<ENTER> Процедура readln считывает данные точно так же, как и процедура read. Однако после считывания

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

Program P46;{Использование процедуры readln}(Использование процедуры read) (Были введены:)(Использование процедуры readln)(Были введены:)При выполнении командread(i, j)read(х, у)

числовые значения из строки 1 2 3 4<ENTER>

введенной пользователем, будут присвоены соответственно переменным i, j, x, у. При выполнении команды

readln(i, j) числовые значения 1 и 2 из строки

1 2 3 4<ENTER>

36

Page 37: Pascal material

будут присвоены переменным i и j. Числа 3 и 4 игнорируются. Затем компьютер выполняет команду:

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

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

Например:(Введите два числа) (Введите целое число) (Ответьте да/D или нет/N:);

Вопросы и упражнения 1. Как разделяются числовые данные, вводимые с клавиатуры?2. Каковы различия между процедурами read и readln? 3. Дана следующая программа: Program P47;Определите результаты, которые будут выведены на экран этой программой после ввода

следующих данных: а.) 3.9. ПУСТОЙ ОПЕРАТОР

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

<Пустой оператор>:: = Таким образом, в тексте программы пустой оператор ни чем не представляется. Так как операторы

программы разделяются с помощью «;», присутствие пустого оператора отмечается появлением этого символа.

Например, в тексте: х := 4;;;; у := х+1

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

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

3.10. УСЛОВНЫЙ ОПЕРАТОР IF

Простой оператор выбора if выполняет одно из двух возможных действий в зависимости от условия – логического выражения. Синтаксис данного оператора:

<Оператор if>::=if <Выражение булевского типа> then <Оператор>[else <Оператор>] Синтаксическая диаграмма данного оператора представлена на рис. 3.7. Логическое выражение,

входящее в состав оператора if, называется условием. <Оператор if>if Выражение булевского типа then

Оператор else Оператор

37

Page 38: Pascal material

Рис. 3.7. Синтаксическая диаграмма <Оператор if>

Выполнение оператора if начинается с проверки условия. Если результатом проверки является true, то выполняется оператор, стоящий после ключевого слова then. Если условие принимает значение false, то выполняется оператор, стоящий после ключевого слова else (если оно есть), или управление передается оператору, следующему непосредственно за оператором if.

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

Program P48;{определение максимального из двух чисел}writeln('Введите два числа: ');

Следующая программа переводит римские цифры: I (один), V (пять), Х (десять), L (пятьдесят), C (сто), D (пятьсот), M (тысяча), считываемые с клавиатуры, в соответствующие им числа в десятичной системе счисления.

Program P49;{Перевод римских цифр}writeln('Введите одну из римских цифр');writeln('I, V, X, L, C, D, M');

writeln(c, '– не является римской цифрой');

Отметим, что в языке ПАСКАЛЬ символ ";" не является частью оператора, а используется в качестве разделителя. Следовательно, если в операторе:

if B then S

перед S поставить пустой оператор:if B then ; S

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

Если в оператореIf B then I else J

после I поставить символ ";", то получим программу, составленную синтаксически неправильно:If B then I; else JВ данном операторе else J интерпретируется как оператор, стоящий после условного оператора.

Вопросы и упражнения

1. Для чего необходим оператор if? 2. Какие значения будет принимать переменная х после выполнения каждого из следующих

операторов: а = 18, b = 15, p = true?a)

3. Напишите программу, которая вычисляет значение одной из следующих функций:а)Например, для у =получаем:

Program P50;

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

38

Page 39: Pascal material

Program P51;

5. Прокомментируйте сообщения, выводимые на экран в процессе компиляции программы Р52:Program P52;{Ошибка}

6. Напишите программу, которая переводит десятичные числа 1, 5, 10, 50, 100, 500 и 1000, считываемые с клавиатуры, в римские.

3.11. ОПЕРАТОР ВЫБОРА CASE

Оператор выбора case состоит из выражения, называемого переключателем (селектором), списка констант и соответствующего ему списка операторов. Каждому оператору соответствует одна или несколько констант выбора. Синтаксис данного оператора:

<Оператор case>:: =case <выражение> of [<Вариант>{;< Вариант >}][;] end< Вариант > :: = <Константа> {, <Константа>} : <Оператор>

Соответствующие синтаксические диаграммы представлены на рис. 3.8.

<Оператор case>case выражение of Вариант end

< Вариант > <Константа> : <Оператор>

Рис. 3.8. Синтаксические диаграммы оператора case

Селектор должен относиться к порядковому типу. Константы выбора не должны повторяться и должны быть совместимыми с типом селектора.

Например:writeln ('четная цифра')writeln ('нечетная цифра') Выполнение оператора case начинается с проверки селектора. Если селектор принимает одно из

значений констант выбора, то выполняется оператор, соответствующий этой константе.В следующей программе оператор case используется для перевода римских цифр в десятичные. Program P53;{Перевод римских цифр в десятичные}writeln('Введите одну из римских цифр');writeln('I, V, X, L, C, D, M');

writeln(c, '– не является римской цифрой');

Отметим, что в некоторых версиях языка синтаксис и семантика оператора case были изменены. Список вариантов может включать оператор, которому предшествует ключевое слово else (в некоторых версиях otherwise). Константы выбора можно заменить интервалами вида

<Константа> . . <Константа>

Например (Turbo Pascal 7.0.):Program P54;{Модель карманного калькулятора}write ('Код операции');write ('Неизвестный код операции');

39

Page 40: Pascal material

Вопросы и упражнения

1. Укажите на синтаксических диаграммах рис. 3.8 пути, которые соответствуют операторам case в программах Р53 и Р54.

2. Как выполняется оператор case? Какого типа должен быть селектор?3. Какие константы можно использовать в качестве констант выбора?4. Замените оператор case программы Р54 последовательностью эквивалентных операторов if.5. Используя оператор case, напишите программу, которая переводит десятичные числа 1, 5, 10,

50, 100, 500, 1000, считываемые с клавиатуры, в римские.6. Что появится на экране в процессе выполнения программы Р55?

Program P55;(СТОП)(ВНИМАНИЕ)(СТАРТ)

7. Прокомментируйте следующие программы:Program P56;{Ошибка}writeln('Четная цифра');writeln('Нечетная цифра');

Program P57;{Ошибка}writeln('Один');writeln('Два');writeln('Три');writeln('Четыре');writeln('Пять');

Program P58;{Ошибка}writeln(СТОП');writeln('ВНИМАНИЕ');writeln(СТАРТ');writeln('ПАУЗА');

3.12. ОПЕРАТОР FOR

Оператор for означает повторное выполнение некоторого оператора в зависимости от значения управляющей переменной. Синтаксис данного оператора:

<Оператор for> :: =for <Переменная> :: = <Выражение> <Шаг> <Выражение>do <Оператор>

<Шаг>:: = to downtoСоответствующие синтаксические диаграммы представлены на рис. 3.9.Переменная, находящаяся после ключевого слова for называется управляющей переменной или

параметром цикла. Эта переменная должна относиться к порядковому типу.

<Оператор for> :: =

for Переменная :: = Выражение

40

Page 41: Pascal material

to Выражение do Операторdownto

Рис. 3.9. Синтаксическая диаграмма оператора for

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

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

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

Например:Program P59;{Оператор for}

Результаты, выводимые на экран:0 1 2Значения параметра цикла не могут быть изменены внутри цикла, т. е.1) параметру цикла не присваиваются никакие значения;2) параметр цикла не может быть параметром цикла другого вложенного оператора for;3) нельзя применять процедуры типа read, readln, в которых присутствует параметр цикла.После выхода из оператора for значение параметра цикла не определено, за исключением случая,

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

повторений неизвестно. В качестве примера рассмотрим программы Р60, Р61 и Р62, которые вычисляют соответственно n!, xn и сумму

Program P60;{Вычисление факториала}

Program 61;{Вычисление х в степени n}

Program P62;{Вычисление суммы }

Вопросы и упражнения

1. Укажите на синтаксической диаграмме рис. 3.9 пути, которые соответствуют операторам for из программы Р59.

2. Как выполняется оператор for?3. Что будет выведено на экран программой Р63?

Program P63;

4. Даны описания:var

41

Page 42: Pascal material

Какие из следующих операторов являются правильными?а)

5. Даны описанияvar i, m, n : integer;

Сколько раз будут выполнены процедуры writeln(i) и writeln(2*i), входящие в состав операторов:

если:а)

6. Напишите программу, которая выводит на экран коды символов 'A', 'B', ... , 'Z'.7. Вычислите для первых n элементов:

а)

8. Вычислите сумму первых n элементов:

Указание: Используйте в цикле оператор if odd(...) then... else...

3.13. СОСТАВНОЙ ОПЕРАТОР

Синтаксис составного оператора:<Составной оператор>::=begin <Оператор> {; <Оператор>} endСоответствующая синтаксическая диаграмма представлена на рис. 3.10.

<Составной оператор>::=

begin Оператор end

Рис. 3.10. Синтаксическая диаграмма <Составной оператор>

Например:Ключевые слова begin и end выступают в роли "скобок". Множество операторов, заключенных в

данные скобки, является, с точки зрения языка, одним оператором. Таким образом, составной оператор используется для того, чтобы несколько операторов поместить в те места программы, где позволяется наличие только одного оператора (см. операторы if, case, for и др.).

Например:1)2) ('СЛОЖЕНИЕ');

('ВЫЧИТАНИЕ');('УМНОЖЕНИЕ');('ДЕЛЕНИЕ');

3)

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

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

42

Page 43: Pascal material

символа";" означает вставку пустого оператора. Для того чтобы программы были удобными для чтения, слова begin и end пишутся строго одно

под другим, а операторы внутри "скобок" – смещаются на несколько позиций вправо. Если составной оператор begin … end включается в состав других операторов (if, case, for и др.), то ключевые слова begin и end смещаются вправо.

В качестве примера рассмотрим программу Р64, в которой вычисляется среднее арифметическое n чисел, считываемых с клавиатуры.

Program P64;{Среднее арифметическое n чисел}writeln('Введите', n,'чисел: ');

Вопросы и упражнения

1. Для чего необходим составной оператор?2. Укажите на синтаксической диаграмме рис. 3.10 пути, которые соответствуют составному

оператору в программе Р64.3. Напишите программу, которая считывает с клавиатуры n чисел и затем выводит на экран:

а) сумму и среднее арифметическое считанных чисел;б) сумму и среднее арифметическое положительных чисел;в) сумму и среднее арифметическое отрицательных чисел;

4. Напишите программу, которая считывает с клавиатуры n символов и затем выводит на экран:а) количество считанных десятичных цифр;б) количество четных цифр;в) количество нечетных цифр;г) количество считанных букв;д) количество гласных;е) количество согласных.

Вводимые символы разделяются с помощью нажатия клавиши <ENTER>. Предполагается, что вводятся десятичные цифры 0, 1, 2, ... 9 и прописные буквы латинского алфавита A, B, C, ... Z.

3.14. ОПЕРАТОР WHILE

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

<Оператор while>::=while <Логическое выражение> do <Оператор>Синтаксическая диаграмма представлена на рис. 3.11.

<Оператор while>while Логическое выражение do Оператор

Рис. 3.11. Синтаксическая диаграмма оператора while

Например:

Оператор, расположенный после ключевого слова do, многократно выполняется до тех пор, пока логическое выражение принимает значение true. Как только логическое значение принимает значение false, оператор, стоящий после ключевого слова do, перестает выполняться. Логическое выражение должно иметь как можно более простой вид, так как оно проверяется при каждой итерации.

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

43

Page 44: Pascal material

управляющей является переменная типа real. В следующей программе оператор while используется для вывода значений функции у=2х.

Аргумент х принимает значения от х1 до х2 с шагом х. Program P65;{Таблица функции у=2х}

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

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

Program P66;{Среднее арифметическое положительных чисел,

считываемых с клавиатуры}writeln('Введите положительные числа: ');writeln('Было введено', n, 'положительных чисел');writeln('среднее= ', suma / n);writeln('среднее=*****');

Отметим, что число повторений составного оператора begin ... end, входящего в состав оператора while, заранее неизвестно. Оператор while завершает свое действие, когда пользователь вводит число x 0.

Вопросы и упражнения

1. Как выполняется оператор while?2. Укажите на синтаксических диаграммах рис. 3.11 пути, которые соответствуют операторам

while в программах Р65 и Р66.3. Используя оператор while, напишите программу, которая выводит на экран значения функции

y=f(x) для аргумента, принимающего значения от х1 до х2 с шагом х:а)

4. Пользователь вводит с клавиатуры целые положительные числа, разделяемые нажатием клавиши <ENTER>. Признаком конца последовательности является число 0. Напишите программу, которая выводит на экран:а) сумму и среднее арифметическое четных чисел;б) сумму и среднее арифметическое нечетных чисел.

5. Напишите программу, которая выводит на экран значения функции z=f(x, y). Аргумент х принимает значения от х1 до х2 с шагом х, а аргумент у принимает значения от у1 до у2 с шагом у:

а)

Program P67;{Таблица функции z=x+y}

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

эквивалентен последовательности операторов:

Напишите эквивалентную последовательность операторов для оператора цикла:

7. Даны описания:varКакие из следующих последовательностей операторов эквивалентны?а)

44

Page 45: Pascal material

Аргументируйте Ваш ответ.

3.15. ОПЕРАТОР REPEAT

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

Синтаксис рассматриваемого оператора:<Оператор repeat> ::= repeat <Оператор>{;<Оператор>} until <Логическое выражение>

Синтаксическая диаграмма представлена на рис. 3.12.

<Оператор repeat> repeat Оператор until Логическое выражение

Рис. 3.12. Синтаксическая диаграмма оператора repeat

Например:1)Операторы, расположенные между ключевыми словами repeat и until, многократно выполняются

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

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

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

Program P68;{Четность чисел, считываемых с клавиатуры}writeln('Введите целые числа');writeln(i : 6, ' - нечетное число');writeln( i : 6, ' - четное число');Выполнение оператора repeat завершается, когда пользователь вводит i = 0.Следующая программа вычисляет значение:

используя рекуррентное соотношение:Выполнение оператора repeat завершается, когда последовательные приближения yi-1 и yi

начинают удовлетворять условию:

Program P69;{Вычисление квадратного корня }

Параметр показывает точность, с которой вычисляется х. Например, для х = 2 и = 0.01 программа Р69 выведет на экран:

а для х = 2 и = 0.0000000001:Из данных примеров видно, что оператор repeat используется тогда, когда число повторений

некоторой последовательности операторов сложно предугадать.

Вопросы и упражнения

45

Page 46: Pascal material

1. Как выполняется оператор repeat?2. Укажите на синтаксических диаграммах рис. 3.12 пути, которые соответствуют операторам

repeat в программах Р68 и Р69.3. Даны следующие операторы:

a) Оператор 1Оператор 2...Оператор n

б) Оператор 1Оператор 2...Оператор n

Эквивалентны ли эти операторы? Аргументируйте Ваш ответ.

4. Напишите программу, которая считывает с клавиатуры последовательность символов и выводит на экран:а) количество считанных десятичных чисел;б) количество четных чисел;в) количество нечетных чисел.

Вводимые символы разделяются с помощью клавиши <ENTER>. Предполагается, что вводятся десятичные цифры 0, 1, 2, ... 9. Конец последовательности указывается вводом символа *.

5. Напишите программу для вычисления значения у= с помощью рекуррентного соотношения:

6. Эквивалентен ли оператор:

последовательности операторов:

Аргументируйте Ваш ответ.

7. Напишите программу, которая выводит на экран значения функции у=f(x). Аргумент х принимает значения от х1 до х2 с шагом х, а цикл организуется с помощью оператора repeat.а)

8. Напишите программу, которая считывает с клавиатуры последовательность символов и выводит на экран:а) количество считанных букв;б) количество прописных букв;в) количество строчных букв.Вводимые символы разделяются с помощью клавиши <ENTER>. Предполагается, что можно вводить строчные и прописные буквы латинского алфавита и символ *, который указывает конец ввода последовательности.

3.16. ОПЕРАТОР GOTO

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

46

Page 47: Pascal material

<Оператор goto>::= <Метка>

Напомним, что метка - это целое число без знака, которое указывает на некоторый оператор программы (рис. 3.1). Метки перечисляются в разделе описаний программы после ключевого слова label. Синтаксис данного описания:

<Метки>::= label <Метка> {, <Метка>};Синтаксические диаграммы соответствующих грамматических единиц представлены на рис. 3.13.

Отметим, что перечисление меток в разделе описаний label обязательно.

<Оператор goto>goto Метка

<Метки>label Метка

Рис. 3.13. Синтаксические диаграммы <Оператор goto> и <Метки>

При выполнении оператора goto управление передается оператору, отмеченному соответствующей меткой.

В качестве примера представим программу Р70, которая вычисляет значение функцииу=

Значения аргумента х считываются с клавиатуры.

Program P70;{Выполнение оператора goto}

Если пользователь набирает значение x0, то выполняется команда goto 1 и управление передается оператору присваивания:

1: у:=х

После этого выполняются операторы:Если пользователь набирает значение x < 0, то выполняются операторы:

Последний оператор передает управление оператору:2: readlnДля меток и операторов любой программы должны выполняться следующие правила:1) каждая метка должна быть описана с помощью ключевого слова label;2) каждая метка должна стоять перед одним и только одним оператором;3) переход извне внутрь сложного оператора (if, for, while, ... и др.) запрещается.Например:

goto 1; {Ошибка}goto 10; {Ошибка} При отсутствии операторов goto, все операторы программы выполняются в том порядке, в

котором они появляются в тексте программы. Следовательно, операторы goto нарушают соответствие между текстом программы и порядком выполнения операторов, что усложняет разработку, проверку и отладку программ. Таким образом, использовать оператор goto не рекомендуется.

Например, программу Р70 можно переписать в следующем виде:Program P71;{Исключение оператора goto из программы Р70}

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

47

Page 48: Pascal material

размеров программы.

Вопросы и упражнения

1. Для чего необходим оператор goto?2. Укажите на синтаксических диаграммах рис. 3.13 пути, которые соответствуют меткам и

операторам goto из программы Р70.3. Перепишите следующие программы без использования оператора goto:

Program P72;{Вывод на экран форм приветствия}write ('Который час?');writeln ('Доброе утро!');writeln('Добрый день!');writeln('Добрый вечер!');

4. Прокомментируйте следующую программу:Program P73;{Ошибка}

5. Что выведет на экран следующая программа?Program P74;{Ошибка}

Напомним, что работу программы можно прервать нажатием клавиш <CTRL+C> или <CTRL+BREAK>.

6. Прокомментируйте следующую программу:Program P75;{Ошибка}

3.17. СТРУКТУРА ПРОГРАММ НА ЯЗЫКЕ ПАСКАЛЬ

Программа на языке ПАСКАЛЬ имеет следующую структуру:<Программа>::=

<Заголовок программы><Блок>.

Заголовок программы содержит имя программы и иногда список формальных параметров:<Заголовок программы>::=Program <Идентификатор>

[(<Идентификатор> {, <Идентификатор>})];Например:Обычно формальные параметры используются для связи программы со средой ввода/вывода.

Более подробно ввод/вывод изучается следующих главах.Блок программы состоит из раздела описаний и раздела операторов:<Блок> ::= <Раздел описаний>

<Раздел операторов>Синтаксис раздела описаний:<Раздел описаний>::= [<Раздел описания меток>]

[<Раздел описания констант>][<Раздел описания типов>][<Раздел описания переменных>][<Раздел описания подпрограмм>]

Подпрограммы будут изучаться в последующих главах.Раздел операторов – составной оператор begin ... end.Синтаксические диаграммы соответствующих грамматических единиц представлены на рис. 3.14.

48

Page 49: Pascal material

Отметим, что конец программы обозначается символом "." (точка).В заключение в качестве примера представляем программу Р76, которая вычисляет длину дуги

окружности, опирающуюся на угол в градусов, и площадь соответствующего сектора.Program P76;{Длина дуги окружности и площадь соответствующего сектора}writeln('Ошибка: raza<0');

<Программа>Заголовок программы Блок .

<Заголовок программы>Program Идентификатор

Идентификатор

<Блок> Раздел описаний Раздел операторов

<Раздел описаний> Раздел описания метокРаздел описания константРаздел описания типовРаздел описания переменныхРаздел описания подпрограмм

Рис. 3.14. Структура программы на языке ПАСКАЛЬ

Вопросы и упражнения

1. Для чего необходим заголовок программы? Как обозначается конец программы?2. Укажите на синтаксических диаграммах рис. 3.14 пути, которые соответствуют

грамматическим единицам программы Р76.3. Перепишите программу Р76 без использования оператора goto. Укажите раздел описаний и

раздел операторов созданной программы.4. Для чего нужны параметры, указываемые в заголовке программы?

49

Page 50: Pascal material

Глава 4СОСТАВНЫЕ ТИПЫ ДАННЫХ

4.1. ТИП ДАННЫХ МАССИВ (ARRAY)

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

Тип данных массив определяется конструкцией вида:type <Имя типа> = array [T1] of T2;

где Т1 – тип индекса, который должен быть порядковым, а Т2 – тип компонент (базовый), который может быть любым.

Например:

Структура данных, используемых в этих примерах, представлена на рис. 4.1. Доступ к компонентам переменной типа массив осуществляется явно через имя переменной, за

которой следует соответствующий индекс, заключенный в квадратные скобки. Например:

Рис. 4.1. Структура данных типа Vector, Venit и Temperatura

К компонентам данных типа массив можно применять все операции, допустимые для соответствующего базового типа. Следующая программа выводит на экран сумму компонент переменной х типа Vector. Значения переменных x[1], x[2], …, x[5] вводятся с клавиатуры.

50

Page 51: Pascal material

Program P77;{Сумма компонент переменной х типа Vector}writeln(‘Введите 5 чисел:’);writeln(‘Были введены:’);writeln(‘Сумма = ’, s);

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

Например, программу Р77 можно изменить таким образом, чтобы она считала сумму n действительных чисел, n ≤100:

Program P78;{Расширение области применения программы Р77}writeln(‘Введите ’,n ,’чисел: ’);writeln(‘Были введены:’);writeln(‘Сумма = ’, s);

Двумерные массивы определяются с помощью конструкции:type <Имя типа> = array [T1, Т2] of T3;

где Т1 и Т2 указывают тип индексов, а Т3 – тип компонент.

В качестве примера на рис. 4.2 представлена структура данных этого типа:

Компоненты типа real

Рис. 4.2. Структура данных типа Matrice

Matrice = array [1. .3, 1. . 4] of real.

Доступ к компонентам переменной типа двумерный массив осуществляется явно через имя переменной, за которой следуют соответствующие индексы, разделенные запятой и заключенные в квадратные скобки.

Например, при описанииvar m : Matrice;

обозначение m[1, 1] означает ссылку на компоненту, расположенную в первой строке и в первом столбце (см. рис. 4.2); обозначение m[1, 2] означает ссылку на компоненту, расположенную в первой строке и втором столбце; обозначение m[i, j] означает ссылку на компоненту, расположенную в строке i и столбце j.

Следующая программа выводит на экран сумму компонент переменной m типа Matrice. Значения компонент m[1, 1], m[1, 2], … m[3, 4] вводятся с клавиатуры.

Program P79;{ Сумма компонент переменной m типа Matrice }writeln(‘Введите компоненты m[i, j]:’);writeln(‘Были введены:’);writeln(‘Сумма = ’, s);

В общем виде тип n-мерный массив (n = 1, 2, 3 и т.д.) определяется с помощью синтаксических диаграмм, приведенных на рис. 4.3. Слово packed (упакованный) указывает компилятору, что область памяти для элементов типа array должна быть выделена с применением оптимизации. Отметим, что в большинстве компьютеров использование этого префикса ничего не дает, так как оптимизация осуществляется автоматически.

51

Page 52: Pascal material

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

Например, при описании

var a, b: Matrice;оператор:

a:=b

является корректным.

<Тип массив>

[ Тип ] of Тип

Рис. 4.3. Синтаксическая диаграмма <Тип массив>

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

Type Переменная Т состоит из 3-х компонент: T[1], T[2] и T[3] типа Linie. Переменная L состоит из 4-х компонент: L[1], L[2], L[3] и L[4] типа real.

Следовательно, операции присваивания:L[1]:=x, x:=L[3]; T[2]:=L; L:=T[1]

являются корректными.Доступ к элементам переменной Т может осуществляться через T [i] [j] или T[i, j]. Здесь индекс i

означает номер компоненты типа Linie переменной T, а j – номер компоненты типа real компоненты T[i] типа Linie.

Отметим, что объявления вида

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

Первое объявление определяет двумерные массивы с компонентами типа Т3. Второе – определяет одномерные массивы с компонентами типа array [T2] of T3.

В программах на языке ПАСКАЛЬ массивы используются для группировки под одним именем нескольких переменных, обладающих одинаковыми характеристиками.

Вопросы и упражнения

1. Установите тип индексов и тип компонент в следующих объявлениях:

Нарисуйте структуру данных типа P, R, S и T (рис. 4.1 и 4.2).

2. Укажите на синтаксической диаграмме рис. 4.3 пути, которые соответствуют объявлениям из упражнения 1.

3. Напишите металингвистические формулы, которые соответствуют синтаксической диаграмме <Тип массив> рис. 4.3.

52

Page 53: Pascal material

4. Даны описания:

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

5. Даны описания:

Компоненты переменной v представляют собой ежедневный доход предприятия. Напишите программу, которая:

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

6. Даны описания:Компоненты переменной t представляют собой значения температуры, измеряемой каждый час в течение 24 часов. Напишите программу, которая:а) подсчитывает среднюю температуру;б) указывает минимальное и максимальное значения температуры; в) указывает час (часы), в который была зарегистрирована максимальная температура;г) указывает час (часы), в который была зарегистрирована минимальная температура.

7. Даны описания

Компонента C[or, z] переменной C представляет собой потребление электроэнергии города or в день z. Напишите программу, которая:

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

8. Даны описания:

Какие из следующих операций присваивания корректны?

9. Используя тип данных массив, напишите программу, которая реализует алгоритм Эратосфена для вычисления простых чисел, меньших заданного n (n≤200).

4.2. ТИП ДАННЫХ СТРОКА СИМВОЛОВ

В стандартном языке тип данных строка символов является частным случаем типа array и определяется конструкцией вида

<Имя типа>:=Множеством значений данного типа являются все строки, содержащие ровно n символов.

Например:

53

Page 54: Pascal material

Program P80;{Строки символов с фиксированной длиной }

Результат, выводимый на экран:MunteanuMihai

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

N:=’Olaru’;P:=’Ion’.

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

N:=’ Olaru ’;P:=’Ion ’.

Значения любой переменной v типа packed array [1..n] of char можно ввести с клавиатуры только путем поочередного считывания соответствующих компонент:

readОднако вывести всю строку на экран можно с помощью одной процедуры write(v) или writeln(v). Особо выделим тот факт, что строки символов типа packed array [1..n] of char содержат ровно n

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

Чтобы устранить этот недостаток, нынешние версии языка разрешают использование строк символов произвольной длины.

В версии Turbo PASCAL тип данных строка символов, множеством значений которого являются строки произвольной длины, определяется с помощью конструкции вида:

где nmax – максимальная длина, которую могут иметь соответствующие строки. При отсутствии параметра nmax максимальная длина устанавливается неявно, как обычно – 255 символов.

К строкам типа string можно применять операцию конкатенации (склеивания), обозначаемую знаком «+». Текущую длину любой переменной v типа string можно узнать с помощью стандартной функции length(v), которая возвращает значение типа integer. Независимо от длины все строки символов типа string являются совместимыми.

Например: Program 81;{Строки символов произвольной длины}

Результаты, выводимые на экран: Отметим, что в процессе выполнения данной программы длина строк символов N, P и NP

изменяется. К строкам символов можно применять операции отношения <, <=, =, >=, >, < >. Строки

сравниваются посимвольно, слева направо, в соответствии с порядковыми номерами символов типа данных char (см. параграф 2.5). Оба операнда должны относится к типу packed array [1..n] of char с одинаковым числом компонент либо к типу string. Естественно операнды типа string могут быть различной длины.

Например, результатом операции: ‘AC’<’BA’ является true, а результатом операции: ‘AAAAC’<’AAAAB’ – false.

54

Page 55: Pascal material

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

Например, в строке P=’Mihai’ имеем: P[1]=’M’, P[2]=’i’, P[3]=’h’ и т. д. После выполнения последовательности операторовпеременная Р примет значение ‘Petru’.

Следующая программа вводит с клавиатуры произвольные строки символов и выводит на экран количество пробелов в соответствующей строке. Работа программы завершается после введения строки: ‘Sfîrşit’.

Program Р82;{Количество пробелов в строке символов}writeln('Введите строки символов: ');writeln('Количество пробелов = ', i); Вопросы и упражнения

1. Как определяется тип данных строка символов?2. Какие операции можно применять к строкам символов?3. Прокомментируйте следующую программу:

Program P83;{Ошибка}

4. Напишите программу, которая:а) определяет, сколько раз символ ‘A’ встречается в строке;б) заменяет символ 'A' символом '*';в) удаляет из строки символ ‘B’;г) определяет, сколько раз слог ‘MA’ встречается в строке;д) заменяет слог ‘MA’ слогом ‘TA’;е) удаляет из строки слог ‘TO’.

5. Определите результат операций отношения:а)

6. Даны строки символов, состоящие из прописных букв латинского алфавита и пробелов. Напишите программу, которая выводит на экран данные строки согласно следующим правилам:

- все буквы от ‘A’ до ‘Y’ заменяются на последующие буквы алфавита; - каждая буква ‘Z’ заменяется на букву ‘A’;- все пробелы заменяются знаком ‘-‘.

7. Напишите программу, которая расшифровывает строки символов, зашифрованные согласно правилам из упражнения 6.

8. Дано m, m100 строк, состоящих из строчных букв латинского алфавита. Напишите программу, которая выводит на экран данные строки в алфавитном порядке.

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

4.3. ТИП ДАННЫХ ЗАПИСЬ (RECORD)

Множество значений типа данных record состоит из записей. Записи состоят из компонентов, называемых полями. В отличие от элементов массива поля могут относиться к разным типам. Каждое поле имеет свое имя (идентификатор поля).

Тип данных запись определяется структурой вида

type <имя типа> = record<Имя поля 1> : T1;

55

Page 56: Pascal material

<Имя поля 2> : T2;…<Имя поля n> : Tn;end;

где T1, T2, … Tn указывают тип соответствующих полей. Тип некоторого поля может быть произвольным, значит поле, в свою очередь, может относиться к типу запись. Таким образом можно определять вложенные типы.

Например:1) 2) {координата x}

{координата y}3) {вершина A}

{вершина B}{вершина C}

Структура данных из приведенных выше примеров представлена на рис. 4.4. Если две переменные относятся к единому типу запись, то между ними разрешена операция

присваивания. При таком присваивании все поля переменной, стоящей в правой части, копируются в переменную, стоящую в левой части. Например, для типов данных и переменных, определенных выше, корректны следующие операторы:

Е1:= Е2;Т2:= Т3;Р2:= Р1;

Рис. 4.4. Структура данных типа Elev, Punct и Triunghi

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

Например:

Очевидно, что элемент E1.Nume относится к типу string; элемент P1.x – к типу real; элемент T1.A – к типу Punct; элемент T1.A.x – к типу real и т. д.

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

Program P84;{Данные типа Elev} writeln(‘Введите данные о первом ученике:');write ('Фамилия: ');write ('Имя: ');write ('Средний балл: ');

writeln(‘Введите данные о втором ученике:');write ('Фамилия: ');write ('Имя: ');write ('Средний балл: ');

writeln (‘Ученик с наиболее высоким средним баллом: ');

Любой тип данных record может служить базовым типом для формирования других составных типов.

56

Page 57: Pascal material

Например:

Очевидно обозначение LE[i] указывает на i-го ученика из списка; обозначение LE[i].Nume указывает на имя данного ученика и т.д. Следующая программа вводит с клавиатуры данные об n учениках и выводит на экран имя, фамилию и средний балл лучшего ученика. Считается, что средние баллы учеников различны.

Program P85;{Массив с элементами типа Elev}

writeln(‘Введите данные об ученике', i);write ('Фамилия: ');write ('Имя: ');write ('Средний балл: ');

writeln (‘Лучший ученик: ');

В обобщенном виде тип данных запись определяется с помощью синтаксических диаграмм на рис. 4.5. В дополнение к фиксированным записям (записям с фиксированным количеством полей), язык ПАСКАЛЬ позволяет использование вариантных записей. Такие записи изучаются в более углубленных курсах информатики.

Тип записьpacked recordИдентификатор Тип end

Рис. 4.5. Синтаксическая диаграмма <Тип запись>

Вопросы и упражнения

1. Укажите множество значений типа данных «запись».2. Укажите на синтаксической диаграмме рис. 4.5. пути, которые соответствуют определениям

типов данных запись из программ Р84 и Р85.3. Напишите металингвистические формулы для синтаксической диаграммы на рис. 4.5.4. Даны следующие типы данных:

Напишите программу, которая вводит с клавиатуры данные о n лицах (n50) и выводит на экран:а) фамилии и имена тех, кто родился в день месяца z;б) фамилии и имена тех, кто родился в месяц года l;в) фамилии и имена тех, кто родился в год a;г) фамилии и имена тех, чья дата рождения z.l.a;д) фамилию и имя самого старшего человека;е) фамилию и имя самого младшего человека;ж) возраст каждого человека в годах, месяцах и днях;з) список лиц старше v лет;и) список лиц в алфавитном порядке;к) список лиц, упорядоченный согласно дате рождения; л) список лиц одного возраста (рожденных в одном и том же году).

5. Дано n (n30) точек на евклидовой плоскости. Каждая точка i определяется координатами x i, yi. Расстояние между точками i, j вычисляется по формуле

57

Page 58: Pascal material

Напишите программу, которая выводит на экран точки, расстояние между которыми максимально.

6. Площадь треугольника вычисляется по формуле Герона

где р – полупериметр, a, b и с – длины соответствующих сторон. Используя типы данных Punct и Triunghi из данного параграфа, напишите программу, которая считывает с клавиатуры информацию о n треугольниках (n10) и выводит на экран:

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

4.4. ОПЕРАТОР WITH

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

Например, при следующем описании

к элементам переменной А можно обращаться через A.NumePrenume, A.ZileLucrate, A.PlataPeZi и A.PlataPeLuna.

Так как имя А переменной типа “запись” постоянно повторяется, то такой способ обращения к элементам является очень громоздким. Этих повторений можно избежать при использовании оператора with (с).

Синтаксис данного оператора:

<Оператор with>::= with <Переменная> {,< Переменная>}do <Оператор>

Синтаксическая диаграмма представлена на рис. 4.6.

<Оператор with> with Переменная do Оператор

Рис. 4.6. Синтаксическая диаграмма оператора with

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

Например:

Этот оператор эквивалентен следующему:

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

Например:

В нашем случае идентификатор x может представлять собой переменную x типа integer или поле P.x записи Р.

58

Page 59: Pascal material

В оператореx:=1

идентификатор x указывает на переменную x типа integer.

В оператореwith P do x:=1

идентификатор х указывает на поле Р.х переменной Р типа запись.

Так как переменная S типа запись не содержит поля с именем S.x, то в оператореwith S do x:=1

идентификатор х будет интерпретирован как переменная х типа integer. Оператор видаwith v1, v2, … vn do <Оператор>,

где v1, v2, … vn – переменные типа запись, эквивалентен оператору:

with v1 dowith v2 do{…}with vn do <Оператор>

Очевидно, что поля записей v1, v2, … vn должны быть однозначно определены. Например, для переменных Р и S, описанных выше, можно записать:

{ссылка на Р.х}

{ссылка на S.A.x}

{ссылка на S.B.x}

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

Вопросы и упражнения

1. Укажите на синтаксической диаграмме рис. 4.6 пути, которые соответствуют операторам with из примеров, приведенных в данном параграфе.

2. Каково назначение оператора with?3. Используя оператор with, исключите из программ Р84 и Р85, рассмотренных в предыдущем

параграфе, повторения типа4. Даны следующие типы данных

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

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

дней.

59

Page 60: Pascal material

5. Окружность может быть определена через координаты х, у и радиус r. Напишите программу, которая считывает с клавиатуры данные об n окружностях (n50) и выводит на экран:

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

соответствующих центров;в) координаты центра и радиус окружности, которая описывает круг минимальной площади; г) количество окружностей, в которые входит круг с минимальным радиусом, и координаты

соответствующих центров.

4.5. ТИП ДАННЫХ МНОЖЕСТВО (SET)

Тип данных множество (set) определяется по отношению к базовому типу, который должен быть порядковым:

<Тип «множество»> ::= [packed] set of <Тип>

Значениями типа данных множество являются множества, состоящие из значений базового типа. Если базовый тип имеет n значений, то тип множество будет иметь 2n значений. Значение n ограничено: n 256.

В языке ПАСКАЛЬ элементы множества могут перечисляться в квадратных скобках:[ ]; которые являются аналогом фигурных скобок в математике.

Обозначение [ ] означает пустое множество.

Например:

Порядковый тип Indice имеет n=10 значений: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. Тип MultimeIndicii имеет 210=1024 значений, а именно:

[ ]

Таким образом, переменная МI может принимать любое из этих значений, например:МI : = [1, 3] .

Порядковый тип Zi имеет n=7 значений: L, Ma, Mi, J, V, S, D. Тип ZileDePrezenta имеет 2 7=128 значений, а именно:

[ ]

Переменная ZP может принимать любое из этих значений, например:ZP : = [L, Ma, Mi, V].

Значение типа множество может определяться через конструктор множества. Синтаксическая диаграмма грамматической единицы <Конструктор множества> представлена на рис. 4.7. Конструктор содержит конкретные значения элементов множества, разделенных запятыми и заключенных в квадратные скобки. Элемент может являться конкретным значением базового типа или интервалом вида:

<Выражение> . . <Выражение>

<Конструктор множества>Выражение Выражение

Рис. 4.7. Синтаксическая диаграмма <Конструктор множества>

Значения данных выражений представляют собой верхний и нижний пределы интервала.

60

Page 61: Pascal material

Например:

К значениям типа данных множество можно применять обычные операции:+ объединение;* пересечение;- разность,

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

= равенство;< > неравенство;<=, >= включение;in принадлежность,

результат которых относится к типу boolean.

Следующая программа выводит на экран результаты операций +, * и -, применяемых к переменным типа MultimeIndicii.Program P86;{Данные типа Multime Indicii}

{A содержит 1, 2, 3, 4, 5, 8}{B содержит 1, 2, 3, 9, 10}{C является пустым множеством}{C содержит 1, 2, 3, 4, 5, 8, 9, 10}

writeln('Объединение');{C содержит 1, 2, 3}

writeln('Пересечение');{C содержит 4, 5, 8}

writeln('Разность'); В отличие от массивов и записей, к элементам которых существует прямой доступ

соответственно через индексы и названия полей, к элементам множества прямого доступа нет. Допускается только проверка на принадлежность элемента множеству (операция отношения in). Благодаря этому при использовании типов данных множество увеличивается скорость работы программы и улучшается читабельность программ PASCAL.

Например, оператор:

Можно заменить более простым оператором:

Другим примером является использование типов данных множество при вычислении простых чисел, меньших заданного n, n - натуральное число. Для этого используется алгоритм Решето Эратосфена:1) в решете находятся числа 2, 3, 4, ... n;2) из решета удаляется самое малое число i;3) данное число включается в множество простых чисел;4) из решета удаляются все множители m числа i;5) процесс завершается, когда решето становится пустым.

Program P87;{Решето Эратосфена}

61

Page 62: Pascal material

Цифры 1, 2, 3, 4, 5, стоящие в фигурных скобках в левой части программы соответствуют пунктам алгоритма Эратосфена.

Вопросы и упражнения

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

Program P88;{Ошибка}

3. Даны следующие описания:

Какие значения может принимать переменная NT?

4. Напишите металингвистическую формулу, которая соответствует синтаксической диаграмме <Конструктор множества> рис. 4.7.

5. Рассмотрите тип данных MultimeIndicii, описанный в этом параграфе. Перечислите элементы множеств, определяемых следующими конструкторами:

а)

6. Напишите программу, которая выводит на экран все подмножества множества: {1, 2, 3, 4}.7. Напишите программу, которая выводит на экран все подмножества множества: {'A', 'B', 'C', 'D'}.8. Дана строка символов, в которой слова разделяются пробелом или символами: точка, запятая,

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

9. Дана строка символов. Напишите программу, которая выводит на экран количество гласных в данной строке.

10.Напишите программу, которая считывает с клавиатуры две строки символов и выводит на экран:

а) символы, которые встречаются, по крайней мере, в одной из строк;б) символы, которые встречаются в обеих строках;в) символы, которые принадлежат первой строке и не принадлежат второй.

11.Напишите программу, которая проверяет правильность введения в компьютер имени человека (под именем понимается последовательность символов, не содержащая цифр).

12.В современных версиях языка количество значений базового типа любого типа множество ограничено, обычно n 256. Отсюда следует, что программа Р87 не сможет найти простые числа больше n. Напишите программу, которая вычисляет простые числа из интервала 8, ..., 10000.

Указание: Решето из алгоритма Эратосфена можно представить в виде массива, элементами которого являются множества.

4.6. ФАЙЛЫ

Под файлом понимают структуру данных, которая состоит из последовательности компонентов. Все компоненты файла относятся к одному и тому же типу, который называется базовым. Число компонентов файла является произвольным, однако, конец файла обозначается специальным символом: EOF (End of File - конец файла). Файл, который не содержит ни одного элемента, называется пустым файлом.

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

62

Page 63: Pascal material

<Файловый тип> ::= [packed] file of <Тип>где <Тип> - является базовым типом. Базовый тип может быть любым, кроме самого файлового типа (не существует “файл файлов”).

Например:

Структура данных файлового типа представлена на рис. 4.8. Отметим, что символ EOF, который означает конец файла, не является компонентом файла.

FisierNume

Рис. 4.8. Структура данных типа FisierNume, FisierCaractere и FisierElevi

Переменные FN, FC, FE файлового типа называются файлами языка ПАСКАЛЬ или просто файлами. В отличие от остальных типов данных, значения которых хранятся во внутренней памяти компьютера, данные файлов хранятся на периферийных устройствах - носителях информации (на дисках, магнитных лентах, оптических дисках, бумаге принтера или на устройстве считывания документов и др.). Информация на таких носителях хранится в виде внешних файлов в соответствии с требованиями операционной системы. Таким образом, перед использованием переменную файлового типа необходимо связать с некоторым внешним файлом. Методы связи зависят от версии языка и операционной системы, установленной на компьютере.

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

В Turbo PASCAL связь файловой переменной f с внешним файлом осуществляется с помощью процедуры

assign (f, s),где s - это выражение типа string, которое является именем внешнего файла.

Например:аssign (FN, 'A:\ REZULTAT \ R.DAT')

файл FN связывается с внешним файлом R.DAT, находящимся в каталоге REZULTAT на диске A:;

аssign (FC, 'C:\ A.CHR')файл FC связывается с файлом A.CHR, находящимся в корневом каталоге диска С:;

write('Введите имя файла:');readln(str);assign(FE, str)

файл FE связывается с внешним файлом, имя которого считывается с клавиатуры и представлено переменной str типа string.

После выполнения оператора assign (f, s) все операции, осуществляемые над файлом f, будут выполняться над внешним файлом s.

Самыми распространенными операциями, выполняемыми над файлами, являются считывание компонентов из файла и запись их в файл.

Считывание некоторого компонента из файла осуществляется с помощью процедуры вида read(f, v),

где v - переменная, которая относится к базовому типу файла f.

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

63

Page 64: Pascal material

write(f, e),

где е - выражение, относящееся к базовому типу файла f. Например:

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

По методу доступа к компонентам файлы подразделяются на:- файлы последовательного доступа или последовательные (доступ к компоненте i возможен

только после считывания или записи компоненты i-1);- файлы прямого доступа (к любой компоненте есть прямой доступ через ее порядковый

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

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

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

reset(f) - открывает существующий файл для чтения;rewrite(f) - создает пустой файл для записи.После завершения обработки компонент файла файл нужно закрыть. При закрытии файла

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

В стандартном языке по окончании работы программы все файлы закрываются автоматически. В Turbo PASCAL закрытие файла f осуществляется явно с помощью процедуры close(f).

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

1) assign(f, s) - связь файловой переменной f с внешним файлом s;2) reset(f)/rewrite(f) - открытие файла f для чтения / записи;3) read(f, v)/write (f, e) - чтение/запись некоторой компоненты файла f; 4) close (f) - закрытие файла f.

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

языке ПАСКАЛЬ операция присваивания файлов запрещена.

Вопросы и упражнения

1. Объясните термины файл языка ПАСКАЛЬ, внешний файл.2. Где хранятся данные файла? Для чего нужна процедура assign?3. Нарисуйте структуру следующих типов данных:

а)

4. Для чего нужны процедуры открытия и закрытия файлов? Как выполняются эти процедуры?5. Для чего нужны процедуры read и write? Какого типа должна быть переменная v в процедуре

вида read (f, v)? Какого типа должно быть выражение e в процедуре вида write(f, e)?6. Как классифицируются файлы в зависимости от допустимых операций и от метода доступа?7. Переменные А и В введены посредством описания

Корректна ли следующая запись А : = ВОбоснуйте ваш ответ.

64

Page 65: Pascal material

4.7. ФАЙЛЫ С ПОСЛЕДОВАТЕЛЬНЫМ ДОСТУПОМ

Рассмотрим следующие описания:

посредством которых определяются файловый тип FT с базовым типом T, файловая переменная f и переменная v типа Т.

Для открытия выходного файла последовательного доступа используется процедура rewrite (f). Затем в файл записываются соответствующие компоненты. Запись отдельных компонент производится с помощью процедуры:

Write (f, e);где е - выражение типа Т. Оператор вида

write(f, e1, e2, ... en) - эквивалентен последовательности операторовwrite(f, e1); write(f, e2); ... write(f, en).

После записи последней компоненты файл необходимо закрыть.

Например:

Program P89; {Создание файла с компонентами типа Elev}write('Введите имя файла: ');{связывает FE с именем str}{открывает FE для записи}write('Введите количество учеников: ');write('Введите данные об ученике ', i);{Считывает поля переменной Е с клавиатуры}{Записывает Е в FE}{Закрывает FE}

Для открытия входного файла последовательного доступа используется процедура reset(f). Чтение текущего элемента из файла выполняется с помощью процедуры вида:

read(f, v).

Оператор видаread (f, v1, v2, ... vn)

эквивалентен последовательности операторов:read (f, v1); read (f, v2); ... ,read (f, vn).Конец файла можно обнаружить с помощью булевой функции eof(f), которая возвращает значение

true после чтения последнего элемента.

Например:Program P90;{Считывание файла с элементами типа Elev}write('Введите имя файла: ');{связывает FE с именем str}{считывает E из FE}{выводит E на экран}{закрывает FE}

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

65

Page 66: Pascal material

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

Вопросы и упражнения

1. Из скольких элементов может состоять файл? В каком порядке записываются и считываются элементы файла с последовательным доступом?

2. Даны следующие типы данных:

Напишите программу, которая считывает с клавиатуры данные об n лицах и записывает их в файл.Создайте файлы: FILE1.PRS, FILE2.PRS, FILE3.PRS, в которых должны содержаться данные соответственно о 2, 7 и 10 лицах.

3. Напишите программу, которая читает файлы, созданные программой из предыдущего упражнения, и выводит на экран:

а) данные о всех лицах, занесенных в файл;б) данные о тех, кто родился в год а;в) данные о тех, чья дата рождения z.l.a;г) данные о самом старшем человеке;д) данные о самом младшем человеке.

4. Напишите программу, которая выводит на экран среднее арифметическое чисел, записанных в файл типа file of real;

5. В файл типа file of char записаны произвольные символы. Напишите программу, которая выводит на экран количество согласных, находящихся в файле.

6. Прокомментируйте следующую программу:Program P91;{Ошибка}writeln ('Введите имя файла: ');

4.8. ФАЙЛЫ ПРЯМОГО ДОСТУПА

Данный параграф полностью относится к версии Turbo PASCAL. В Turbo PASCAL c переменными типа file of T можно проводить как операции чтения, так и

записи, независимо от того, были ли они открыты с помощью процедуры rewrite или reset. Для этого каждый элемент файла имеет свой номер, называемый номером элемента. Первому элементу соответствует номер ноль, второму - один и т.д. Количество элементов файла f можно определить с помощью стандартной функции: FileSize(f).

Обычно доступ к элементам файла является последовательным. Это означает, что после считывания/записи некоторого элемента указатель текущей позиции в файле перемещается на элемент со следующим порядковым номером. Прямой доступ основывается на процедуре поиска Seek (f, i), которая перемещает указатель текущей позиции в файле на элемент с номером i. После чего элемент, выбранный таким образом, можно считать/записать. Стандартная функция FilePos (f, i) возвращает номер текущей позиции в файле.

Например:

Program P92;{Прямой доступ к файлам типа FisierElev}write ('Введите имя файла: ');writeln ('Файл ', str, 'имеет ', n, 'элементов ');writeln ('Нумерация элементов: 0, ..', n-1);write ('Введите номер элемента: ');

66

Page 67: Pascal material

writeln ('Ошибка: несуществующий элемент'){установление указателя на элемент i}{считывание выбранного элемента}write(Будет ли изменяться элемент? [d/n]'); {установление указателя на элемент i}{запись измененного элемента}

Напомним, что файлы типа FisierElevi можно создать с помощью программы Р89 из предыдущего параграфа.

Вопросы и упражнения

1. Чем отличается прямой доступ от последовательного?2. Для чего нужны процедуры и функции: FileSize, FilePos, Seek?3. Создайте с помощью программы Р89 файлы CLASA0.ELV, CLASA1.ELV и CLASA5.ELV.

Файлы должны содержать соответственно 0, 1 и 5 элементов. Проверьте работу программы Р92 для каждого из созданных файлов.

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

5. Даны следующие типы данных:

Напишите программу, которая:

а) считывает с клавиатуры данные о каждом работнике и создает файлы типа FisierAngajati;б) изменяет, по необходимости, поля ZileLucrate, PlataPeZi, PlataPeLuna для указанных

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

зарплаты;ж) добавляет фамилии новых работников в существующий файл;з) удаляет из файла фамилии уволенных работников.

4.9. ТЕКСТОВЫЕ ФАЙЛЫ

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

Для того чтобы упростить общение пользователя и компьютера, в языке ПАСКАЛЬ информация, предназначенная для пользователя, представляется в виде текстовых файлов. Текстовый файл состоит из последовательности символов, разделенных на строки (рис. 4.9). Длина строк – произвольна. Конец каждой строки обозначается специальным символом EOL (End of Line - конец строки). Так как длина строк произвольна, то позицию некоторой строки в файле нельзя знать заранее. Следовательно, доступ к элементам текстового файла может быть только последовательным.

Текстовый файл задается описанием вида:

var f: text;

67

Page 68: Pascal material

linie - строкаcaractere - символы Рис. 4.9. Структура текстового файла

где предопределенный тип text известен любой программе на языке ПАСКАЛЬ. Отметим, что типы text и file of char различны, так как файл file of char не содержит символов EOL (рис.4.8.).

Обработка текстовых файлов может осуществляться с помощью известных процедур, применимых к любым типам файлов: assign, reset, rewrite, read, write, close. В дополнение к ним, в языке есть специальные процедуры для обработки элементов EOL:

writeln(f) - записывает в файл элемент EOL (конец строки);readln(f) - переход на следующую строку.Конец строки определяется с помощью булевой функции eoln(f), которая принимает значение true

после считывания последнего символа строки.Оператор вида write(f, e1, e2, ... en)

эквивалентен последовательности операторов:write(f, e1); write(f, e2); ... write(f, en).

Оператор видаread (f, v1, v2, ... vn)

эквивалентен последовательности операторов:read (f, v1); read (f, v2); ... ,read (f, vn).

Для ввода и вывода данных используются, как правило, предопределенные текстовые файлы Input и Output. Файл Input предназначен только для чтения и связан со стандартным устройством ввода операционной системы (как правило, с клавиатурой). Файл Output предназначен только для записи и связан со стандартным устройством вывода (как правило, экраном). Эти файлы открываются и закрываются автоматически в начале и, соответственно, в конце выполнения программы. Если при вызове подпрограмм имя файла не указано в списке параметров, то предполагается, что текстовым файлом является файл Input или файл Output в зависимости от сущности подпрограммы. Например, read(c) эквивалентен read(Input, c), а write(c) эквивалентен write(Output, c).

В качестве примера приведем программу Р93, которая создает на текущем диске текстовый файл FILE.TXT. Строки файла вводятся с клавиатуры (файл Input). Признаком конца строки является нажатие клавиши <ENTER>, а признаком конца файла является нажатие клавиш <CTRL+Z>, <ENTER>.

Program P93;{создание текстового файла FILE.TXT}

{связывание файла F с FILE.TXT }{открытие F для записи}

{считывает с из Input}{записывает с в F}

{записывает EOL в F}{переходит на следующую строку из Input}

{закрывает F}Следующая программа выводит на экран содержимое файла FILE.TXT.

68

Page 69: Pascal material

Program P94;{Чтение текстового файла FILE.TXT}{связывает F с FILE.TXT}{открывает F для чтения}{считывает с из F}{записывает с в Output}{переходит на следующую строку F}{записывает EOL в Output}{закрывает f} Посимвольное чтение и запись текстовых файлов является достаточно сложным в случае, когда

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

Для текстовых файлов переменная v из процедуры read(f, v) может относиться к типу: integer, real, char или строка символов. При чтении последовательность символов, которую представляет переменная v, будет переведена во внутреннее представление.

За выражением е в процедуре write(f, e) может следовать указатель формата. Значение выражения может относиться к типу: integer, real, char или строка символов. При записи, соответствующее значение переводится из внутреннего представления в последовательность символов.

Последовательности символов, считываемые/записываемые с помощью процедур read/write соответствуют синтаксису констант типа переменной/выражения v/e.

Использование процедур write, writeln, read и readln для обработки файлов Output и Input было подробно изучено в параграфах 3.7 и 3.8. Аналогично обрабатывается и любой текстовый файл, определенный пользователем.

В качестве примера приведем программу Р95, которая считывает с клавиатуры по три вещественных числа a, b, c и записывает их в файл IN.TXT. После чтения указанных чисел, которые представляют собой длины сторон треугольника, программа записывает в файл OUT.TXT числа a, b и c, полупериметр р и площадь s треугольника. В завершение, содержимое файла OUT.TXT выводится на экран.

Program P95;{Обработка файлов IN.TXT и OUT.TXT}

{связывает F с IN.TXT}{открывает F для записи}

writeln('Введите вещественные числа: a, b, c:');

{считывает a, b, c с клавиатуры}{записывает a, b, c в F}

{закрывает F}{открывает F для чтения}{связывает G с OUT.TXT}{открывает G для записи}

{считывает a, b, c из F}{записывает a, b, c в G}

{записывает p, s в G}{закрывает F}{закрывает G}{открывает G для чтения}

69

Page 70: Pascal material

{считывает str из G}{выводит str на экран}

{закрывает G}

Для входных данныхПрограмма Р95 выводит на экран:

Вопросы и упражнения

1. Какова разница между текстовым файлом и файлом file of char?2. Что означают элементы EOL и EOF?3. Какова разница между процедурами read и readln? А процедурами write и writeln?4. Запустите следующую программу на выполнение:

Program P96;{связывание файла FN с устройством ввода }

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

текстовом файле.7. Входные данные некоторой программы записаны в текстовый файл. В каждой строке файла

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

8. Входные данные некоторой программы записаны в текстовый файл. В каждой строке файла содержатся по три вещественных числа, разделенных пробелами, и по одному из слов ADMIS, RESPINS. Напишите программу, которая:а) выводит содержимое данного файла на экран;б) создает резервную копию файла;в) создает текстовый файл, строки которого содержат среднее арифметическое трех

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

строкой пишется ее порядковый номер 1, 2, 3 и т. д. 9. Каждая строка текстового файла содержит следующие данные, разделенные запятыми:

порядковый номер (integer);имя (последовательность символов, не содержащая пробелов);оценка по 1-му предмету (real);оценка по 2-му предмету (real);оценка по 3-му предмету (real).

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

порядковый номер (integer);имя (string);средний балл (real);

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

70

Page 71: Pascal material

71

Page 72: Pascal material

Глава 5ФУНКЦИИ И ПРОЦЕДУРЫ

5.1 ПОДПРОГРАММЫ

Любая сложная задача может быть решена путем ее разбиения на ряд подзадач. Для решения каждой подзадачи записывается соответствующая последовательность операторов, называемая подпрограммой. Таким образом, задача решается с помощью основной программы, в которой для решения подзадач вызываются подпрограммы. Когда в основной программе встречается обращение к подпрограмме, управление передается первому оператору вызванной подпрограммы (рис. 5.1). После завершения выполнения операторов подпрограммы управление передается оператору основной программы, следующему за оператором вызова подпрограммы.

В языке ПАСКАЛЬ существуют два вида подпрограмм: функции и процедуры.<Подпрограммы> :: = {< Функция >; < Процедура >;}

Функция – это подпрограмма, которая вычисляет и возвращает некоторое значение. Язык ПАСКАЛЬ содержит ряд стандартных функций, известных любой программе: sin, cos, eof и т.д. (см. таблицу 3.1). Помимо этого, программист может создавать собственные функции, к которым можно обращаться так же, как и к стандартным функциям. Таким образом, концепция функции расширяет понятие выражения в языке ПАСКАЛЬ.

Процедура – это подпрограмма, которая осуществляет обработку данных, переданных в момент обращения. В языке ПАСКАЛЬ существуют стандартные процедуры: read, readln, write, writeln и т. д. Помимо этого, программист может создавать собственные процедуры, к которым можно обращаться так же, как и к стандартным процедурам. Таким образом, концепция процедуры расширяет понятие оператора в языке ПАСКАЛЬ.

Подпрограммы объявляются в разделе описаний программы (рис. 3.14). Обращение к функциям и процедурам производится в разделе операторов.

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

Рис. 5.1. Взаимодействие между программой и подпрограммой

Вопросы и упражнения

1. Объясните термины основная программа и подпрограмма.2. Как взаимодействуют программа и подпрограмма?3. Какова разница между процедурами и функциями?4. Как происходит обращение к функции? В каких операторах языка может появиться обращение

к функции?5. Как происходит обращение к процедуре?6. Назовите типы аргументов и типы результатов стандартных функций 7. Назовите тип фактических параметров процедур read и write.8. Как обрабатываются данные с помощью процедур read и write?

5.2. ФУНКЦИИ

На языке ПАСКАЛЬ функция описывается следующим образом:Первая строка – это заголовок функции, состоящий из:f – имя функции;(x1, x2, …; xn) – произвольный список формальных параметров, являющихся аргументами

функции;tr - тип результата; может быть простым или ссылочным.

72

Page 73: Pascal material

За заголовком следует тело функции, состоящее из произвольных локальных описаний D и составного оператора begin … end.

Локальные описания состоят из следующих разделов (некоторые из которых могут отсутствовать):

Имя f функции, которое появляется хотя бы один раз в левой части некоторого оператора присваивания: f:=e. Последнее значение, присвоенное функции f, возвращается в основную программу.

Как правило, формальный параметр из списка (x1, x2, …; xn) имеет вид:(v1, v2, …; vk) : tp,

где (v1, v2, …; vk) – идентификаторы, а tp – имя типа.

Обращение к функции f осуществляется следующим образом:f(a1, a2, …; an),

где (a1, a2, …; an) - список фактических параметров. Обычно фактическими параметрами являются выражения, значения которых передаются функции. Связь между фактическим и формальным параметрами определяется их позицией в рассматриваемых списках. Фактический параметр должен быть совместимым с точки зрения присваивания с типом формального параметра.

Например:Program P97;{Описание и использование функции Putere}

{вычисление x в степени n}

Функция Putere имеет два формальных параметра: x типа real и n типа Natural. Функция возвращает значение типа real. В теле функции описаны локальные переменные p и i.

При обращении к функции Putere (a, b) значения 3.0 и 2 фактических параметров a, b передаются формальным параметрам, соответственно x и n. Отметим, что тип параметра а совпадает с типом параметра х, а тип b – c типом n.

В случае обращения к функции Putere(s, t) тип фактических параметров s, t не совпадает с типом формальных параметров соответственно x и n. Однако такое обращение корректно, так как соответствующие типы совместимы с точки зрения присваивания.

Вопросы и упражнения

1. Даны следующие описания:

Назовите тип формального параметра и тип результата, возвращаемого функцией. Укажите переменные, описанные в теле функции. Напишите программу, которая выводит на экран значения n! для n = 2, 3 и 7.

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

Program P98;{Ошибка}

4. Дан заголовокКакие из следующих процедур корректны:а)

5. Напишите функцию, которая находит:a) сумму действительных чисел a, b, c, d;b) среднее арифметическое целых чисел i, j, k, m;

73

Page 74: Pascal material

c) минимальное из чисел a, b, c, d;d) количество гласных в строке символов;e) количество согласных в строке символов;f) корень уравнения ax + b = 0;g) наименьший делитель целого числа n>0, отличный от 1;h) наибольший общий делитель натуральных чисел a и b;i) наименьший общий множитель натуральных чисел a и b;j) последнюю цифру в десятичном представлении целого числа n > 0;k) сумму цифр в десятичном представлении целого числа n > 0;l) наибольшую цифру в десятичном представлении целого числа n > 0;m) количество появлений заданного символа в строке символов.

6. Даны следующие описания:Создайте функцию, которая вычисляет:a) сумму элементов некоторого массива типа Vector;b) среднее арифметическое элементов данного массива;c) максимальный элемент;d) минимальный элемент.

7. Даны следующие типы данных:Создайте функцию, которая вычисляет:a) длину отрезка;b) длину окружности;c) площадь круга;d) площадь треугольника;e) площадь прямоугольника.

8. Переменная А вводится с помощью описания:

Напишите функцию, которая возвращает количество символов в множестве А.9. Напишите функцию, которая вычисляет в секундах разность между двумя моментами

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

треугольников проверяют:a) одинаковы ли площади данных треугольников;b) являются ли треугольники подобными;c) находится ли первый треугольник внутри второго.

5.3. ПРОЦЕДУРЫПроцедура описывается следующим образом:

p – имя процедуры;(x1, x2, …; xn) – произвольный список формальных параметров. В тело процедуры включены:D – произвольные локальные описания, сгруппированные таким же образом, как и в случае

функций; begin … end – составной оператор, в котором имя процедуры не появляется в операциях

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

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

74

Page 75: Pascal material

Параметры из списка, вводимые через описания видаv1, v2, …; vk : tp

называются параметрами-значениями. Они служат для передачи значений из основной программы в процедуру.

Формальные параметры, введенные в список через описания видаvar v1, v2, …; vk : tp

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

Запуск процедуры выполняется путем её вызова:р(a1, a2, …; an),

где (a1, a2, …; an) - список фактических параметров. В отличие от функции, обращение к процедуре является оператором. Операторы вызова процедур вставляются в основную программу там, где требуется выполнить соответствующую обработку данных.

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

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

Например:Program P99;{Описание и использование процедуры Lac}{Длина окружности и площадь круга}{r - радиус; l - длина; s - площадь}

Процедура Lac имеет три формальных параметра: r, l, s. Параметр r является параметром-значением, а l и s – параметрами-переменными.

При выполнении процедуры Lac (a, b, c) значение 1.0 передается формальному параметру r, а адреса переменных b и с передаются формальным параметрам l и s. Таким образом, последовательность операторов

а : = 1.0;Lac(a, b, c)

эквивалентна последовательностиb : = 2 * Pi * 1.0;c : = Pi * sqr(1.0).

Аналогично оператор:Lac (3.0, t, q)

эквивалентен последовательности

t : = 2* Pi * 3.0;q : = Pi * sqr(3.0).

Вопросы и упражнения

1. Какова разница между параметром-значением и параметром-переменной?2. Даны описания:

Какие из следующих процедур корректны?а)Аргументируйте Ваш ответ.

75

Page 76: Pascal material

3. Прокомментируйте следующую программу:Program P100;{Ошибка}

4. Что будет выведено на экран следующей программой?Program P101;{Параметр-значение и параметр-переменная}

Аргументируйте Ваш ответ.

5. Напишите процедуру, которая:a) находит корни уравнения b) удаляет из строки символ, указанный при вызове процедуры;c) обрамляет строку символами “#”;d) упорядочивает элементы массива array [1..100] of real в порядке возрастания;e) упорядочивает элементы файла file of integer в порядке убывания;f) находит и заносит в массив простые числа, меньшие заданного натурального числа n.

6. В упражнении 4 из параграфа 4.3 определен тип данных ListaPersoane. Напишите процедуры, необходимые для вычисления данных, указанных в пунктах а), б), в), …, л) указанного упражнения.

7. Напишите процедуру, которая:a) создает резервную копию любого текстового файла;b) удаляет из текстового файла пустые строки;c) находит количество строк в текстовом файле;d) выполняет слияние двух текстовых файлов в один;e) выполняет слияние n (n > 2) текстовых файлов в один.

8. В упражнении 5 из параграфа 4.9 определен тип данных FisierAngajati. Напишите процедуры, необходимые для обработки данных согласно пунктам а), б), в), …, з) указанного упражнения.

9. Введите тип данных для обработки больших натуральных чисел и напишите процедуры для их сложения и вычитания.

5.4. ФОРМАЛЬНЫЕ ПАРАМЕТРЫ-ФУНКЦИИ / ПРОЦЕДУРЫ

Помимо параметров-значений и параметров-переменных, в языке ПАСКАЛЬ используются параметры-функции и параметры-процедуры.

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

заголовок function F(x:real):real выступает в качестве параметра-функции.

Вызов процедуры Q имеет вид:Q(F1, j),

где F1 – имя функции, которое должно быть известно на момент вызова.

В Turbo PASCAL параметры-функции/процедуры объявляются явно и относятся к процедурному типу.

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

76

Page 77: Pascal material

Например:

Множество значений типа TF состоит из имен всех функций от одной переменной вещественного типа, значения которых также относятся к вещественному типу. Множество значений типа TР состоит из имен всех процедур с двумя переменными целого типа.

Отметим, что при объявлении процедурных типов имя функции/процедуры не указывается.

К переменным процедурного типа можно применять операции присваивания. Например, при описаниях:

корректны следующие операции присваивания:v :=F1;p :=P1.

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

Program P102;{Формальный параметр-функция}{Табуляция функции F(x)}writeln ('Таблица функции F1');writeln ('Таблица функции F2);writeln ('Таблица функции F3);

В данной программе даны описания:- процедурного типа TF;- переменной v типа TF;- функций F1, F2 и F3 типа TF;- процедуры Tabel с параметром-функцией F и параметрами-значениями: x1, x2 и dx.

Процедура Tabel выводит на экран таблицу любой функции типа TF. В данной программе процедура вызывается для табуляции функций F1, F2 и F3. При последнем вызове процедуры имя функции F3 передается процедуре Tabel через переменную v.

Отметим, что стандартные процедуры и функции не могут передаваться в качестве фактических параметров. Например, нельзя осуществить вызов процедуры Tabel (sin, … ), так как sin - стандартная функция. Однако эту проблему можно решить путем введения функции fsin

которую можно использовать в обращении Tabel (fsin, …) для получения желаемого результата.

Вопросы и упражнения

1. Как описывается формальный параметр-функция / процедура в языке PASCAL? В Turbo PASCAL?

2. Как объявляется процедурный тип? Каково множество значений процедурного типа? 3. Исправьте программу:

Program P103;{Ошибка}

4. Используя процедуру Tabel из программы Р102, напишите программу, которая табулирует функции:

77

Page 78: Pascal material

5. Что выведет на экран следующая программа:

Program P104;{Формальный параметр-процедура}

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

7. Функция y = f(x) в точках 1, 2, …, n не обращается в нуль. Напишите процедуру, которая определяет, сколько раз в последовательности чисел f(1), f(2), …, f(n) встречается смена знака.

8. Дано множество функций от целой переменной f(i), значения которых относятся к вещественному типу. Напишите функцию, которая вычисляет: f(1) + f(2) + … + f(n).

9. Дана функция от целой переменной f(i), значения которой относятся к целому типу. Напишите функцию, которая определяет сколько раз подпоследовательность 1, 0, 1 встречается в последовательности чисел f(1), f(2), …, f(n).

10. На интервале (a, b) уравнение f(x) = 0 имеет один корень. Напишите процедуру для определения корней данного уравнения по методу деления отрезка пополам (метод дихотомии).

Указание: Вычислите c = (a + b)/2. Проанализировав знаки значений f(a), f(c) и f(b), выберите один из интервалов (a, c), (c, b), в котором содержится корень уравнения. Опять разделите выбранный интервал на два интервала и т. д. до тех пор, пока не будет достигнут желаемый уровень точности.

5.5. ОБЛАСТИ ВИДИМОСТИ

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

Program P105;{Блочная структура программы} Рис. 5.2. Блочная структура программы на языке ПАСКАЛЬ

В таких структурах каждому блоку i соответствует некоторый уровень вложенности. Основной программе соответствует уровень вложенности 0, блоку, определенному в основной программе - уровень вложенности 1. Блоку, определенному на уровне n соответствует уровень вложенности n+1.

В качестве примера, на рис. 5.2. представлена модульная структура программы Р105.Как правило, любой блок на языке ПАСКАЛЬ содержит описания меток, переменных, функций,

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

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

78

Page 79: Pascal material

Например, в программе Р105 областью видимости описания var a: integer является текст, заключенный между пунктами {1}-{7}. Область видимости описания var c: real состоит из двух фрагментов текста, заключенных между {2}, {3} и {5}, {6}. Областью видимости описания var c: char является текст, заключенный между {4} и {5}.

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

Например, в программе Р105 идентификатор с из оператора:c : = chr(d)

обозначает переменную типа char.

Тот же самый идентификатор из оператора:c : = b + 1;

обозначает переменную типа real.

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

Например, областью видимости описания procedure Q является текст, находящийся между пунктами {3} и {6}. Областью видимости описания d: integer является текст, находящийся между пунктами {3} и {5}.

Вопросы и упражнения

1. Как определяется область видимости некоторого описания?2. Определите области видимости описаний b: real и x: real из программы Р105 (рис. 5.2).3. Какова модульная структура программы, представленной ниже? Для каждого описания

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

Program P106;{Переопределение констант}

Что выведет на экран данная программа?

4. Определите области видимости идентификаторов P и F из программы Р105 (рис. 5.2).5. Прокомментируйте следующую программу:

Program P107;{Ошибка}

6. Как определяется объект, обозначаемый некоторым именем, из программы на языке ПАСКАЛЬ?

5.6. СВЯЗЬ ЧЕРЕЗ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ

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

79

Page 80: Pascal material

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

В дополнение к передаче данных через параметры, язык ПАСКАЛЬ допускает связь между программой и вызываемыми подпрограммами через глобальные переменные.

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

Например:Program P108;{Связь через глобальные переменные}{глобальная переменная в P}{глобальная переменная в P, F}{локальная переменная в P}{локальная переменная в F}{выводится на экран 2.0000000000Е+00}{выводится на экран 5.0000000000Е+00}

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

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

Вопросы и упражнения

1. Объясните термины переменная глобальная по отношению к некоторой подпрограмме и переменная локальная в некоторой подпрограмме.

2. Назовите глобальные и локальные переменные, описанные в программе Р105 (рис. 5.2).3. Может ли локальная переменная в то же время являться и глобальной по отношению к какой-

либо подпрограмме?4. Назовите локальные и глобальные переменные, описанные в следующей программе. Что

выведет на экран данная программа?

Program P109;{Связь через глобальные переменные}

5. Даны описания:

Компоненты некоторой переменной типа Temperatura представляют собой значения температуры, измеряемой каждый час в течение 24 часов. Напишите процедуру, которая:

a) находит максимальную и минимальную температуры;b) находит час (часы), когда была зарегистрирована максимальная температура;c) записывает в текстовый файл час, когда была зарегистрирована минимальная

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

80

Page 81: Pascal material

6. Даны произвольные текстовые файлы. Напишите функцию, которая:a) возвращает количество строк в файле;b) считает количество гласных в тексте;c) считает количество слов в тексте (слова представляют собой последовательности

символов, разделенных пробелами или символами конца строки);d) возвращает среднюю длину строк текста;e) возвращает среднюю длину слов текста;f) возвращает число знаков пунктуации в тексте.

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

5.7. Побочные эффекты

Любая функция возвращает единственный результат – значение функции. Как правило, значения аргументов передаются функции через параметры-значения, а полученный результат возвращается на место вызова через имя функции. Помимо этого, язык ПАСКАЛЬ допускает передачу аргументов через глобальные переменные и параметры-переменные.

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

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

Program P110;{Побочный эффект - присваивание глобальной переменной}{глобальная переменная}{присваивание, влекущее за собой побочный эффект}{на экран выводится 1}{ на экран выводится 2}{ на экран выводится 3}

В программе Р110 функция F возвращает значение выражения а*х. Наряду с этим, операция присваивания а : = а+1 изменяет значение глобальной переменной а. Таким образом, для одного и того же значения 1 аргумента х функция возвращает различные результаты, что противоречит обычному определению функции.

Program P111;{Побочный эффект - присваивание формальному параметру}{присваивание, влекущее за собой побочный эффект}{на экран выводится 4}{ на экран выводится 6}{ на экран выводится 8}

В программе Р111 функция F возвращает значение выражения 2*х. Так как х - формальный параметр-переменная, то операция присваивания х : = х + 1 изменяет значение фактического параметра, указываемого при вызове, и значение переменной а из основной программы. Тот факт, что при обращении к процедурам, идентичным по тексту F(a), F(a) и F(a), возвращаются различные результаты, может привести к осложнениям в процессе отладки.

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

81

Page 82: Pascal material

переменные, операции присваивания над некоторыми такими параметрами не считаются побочными эффектами.

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

формальные параметры-значения, а возврат единственного результата – через ее имя. Связь процедур со средой вызова осуществлять посредством передачи данных в процедуру через

формальные параметры-значения или параметры-переменные, а возврат результатов – через формальные параметры-переменные.

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

Вопросы и упражнения

1. Какова причина побочных эффектов? К каким последствиям могут привести указанные эффекты?

2. Что выведут на экран следующие программы:

Program P112;{Побочные эффекты}

Program P113;{Побочные эффекты}

Program P114;{Побочные эффекты}{Обмен значениями между переменными х и у}

3. Как можно избежать побочных эффектов?

5.8. РЕКУРСИЯ

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

Предположим, что объявлен следующий тип

type Natural = 0 . . MaxInt;

Функция факториал

может быть представлена на языке ПАСКАЛЬ, исходя из ее определения, в следующем виде:

Вызов F(7) влечет за собой ряд обращений к функции F с фактическими параметрами 6, 5, …, 2, 1, 0:

При вызове F(0) вычисляется непосредственное значение функции, что останавливает процесс повторений; после этого следует процесс возврата и вычисление значений функции F для аргументов 1, 2, …, 6, 7, последнее вычисленное значение F(7) возвращается на место первого вызова функции.

82

Page 83: Pascal material

Значениями функции

являются числа Фибоначчи. Следуя определению, получаем:

Каждый вызов функции Fib для n 1 влечет за собой два вызова Fib(n-1), Fib(n-2) и т. д., например:

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

Очевидно, любая рекурсивная подпрограмма должна содержать условие остановки процесса повторения. Например, в случае факториала процесс повторений останавливается, когда n принимает значение 0; в случае функции Fib процесс останавливается, когда n принимает значения 0 или 1.

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

- текущие значения параметров, передаваемых через значение;- местонахождение (адреса) параметров-переменных;- адрес возврата, т. е. адрес оператора, который следует за оператором вызова.

Таким образом, при рекурсивном вызове занимаемая область памяти увеличивается очень быстро, что ведет к риску переполнения памяти компьютера. Этого можно избежать путем замены рекурсии на итерацию (операторы for, while, repeat). В качестве примера представим нерекурсивную форму функции для вычисления факториала:

Рекурсию необходимо использовать в случаях, когда написание нерекурсивных алгоритмов является очень сложным: перевод программ на языке ПАСКАЛЬ на язык компьютера, машинная графика, распознавание образов и т. д.

Вопросы и упражнения

1. Как выполняется рекурсивная подпрограмма? Какая информация заносится в память компьютера при выполнении рекурсивного вызова?

2. Какова разница между рекурсией и итерацией?3. Напишите не рекурсивную функцию Фибоначчи.4. Напишите рекурсивную подпрограмму, которая:

a) вычисляет суммуb) вычисляет произведениеc) переставляет символы строки в обратном порядке;d) вычисляет произведение.

5. Напишите программу, которая вводит с клавиатуры натуральные числа m, n и выводит на экран значения функции Акерманна:

Вычислите а(0, 0), а(1, 2), а(2, 1) и а(2, 2). Попробуйте вычислить а(4, 4) и а(10, 10). Объясните сообщения, выдаваемые на экран.

6. Дано описание

Напишите рекурсивную подпрограмму, которая:

a) выводит на экран компоненты вектора;b) вычисляет сумму соответствующих компонент;c) переставляет компоненты вектора в обратном порядке;

83

Page 84: Pascal material

d) вычисляет сумму положительных компонент вектора;e) проверяет, есть ли среди компонент вектора хотя бы один отрицательный;f) вычисляет произведение отрицательных компонент;g) проверяет, есть ли среди компонент вектора хотя бы один равный заданному числу.

7. Перепишите следующую функцию в нерекурсивном виде:8. Напишите рекурсивную функцию, которая возвращает значение true, если строка символов s

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

9. Даны следующие металингвистические формулы:

Напишите рекурсивную функцию, которая возвращает значение true, если строка символов s соответствует определению лексической единицы “Выражения”.

5. 9. ОПЕРЕЖАЮЩИЕ ОПИСАНИЯ

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

Например:

Ясно, что на языке ПАСКАЛЬ в тексте функции f(x) будет использоваться вызов g(x-1), а в тексте g(x) – вызов f(x-1).

Согласно основным правилам языка ПАСКАЛЬ, описание некоторого имени в тексте программы должно предшествовать его использованию. В случае функций f(x) и g(x), независимо от текстовой формы программы, имя одной из функций используется до ее описания. Для решения такого рода проблем используются опережающие описания.

Опережающее описание состоит из заголовка подпрограммы и директивы forward (вперед). Тело подпрограммы появится позже и ему предшествует краткий заголовок, в котором указывается только имя подпрограммы, без указания параметров и типов.

Например:Program P115;{Опережающее описание}{Опережающее описание функции F}{Тело функции F}

Опережающие описания могут использоваться для объявления любых процедур или функций, не обязательно рекурсивных. Отметим, что необоснованное использование опережающих описаний усложняет модульную структуру программ на языке ПАСКАЛЬ.

Вопросы и упражнения

1. Какова разница между прямой и косвенной рекурсией?2. Существует ли необходимость использования директивы forward при косвенной рекурсии?

Аргументируйте Ваш ответ.3. Напишите программу, которая считывает с клавиатуры натуральное число n и выводит на

экран значение функции f(n):

Вычислите значения: f(0), f(5), f(10) и f(15). Попробуйте вычислить f(100) и f(200). Объясните

84

Page 85: Pascal material

сообщения, выдаваемые на экран.

4. Определите, что выведет на экран следующая программа:

Program P116;

5.10.СИНТАКСИС ОПИСАНИЙ И ВЫЗОВОВ ПОДПРОГРАММ

В обобщенном виде описание некоторой функции осуществляется с помощью следующих металингвистических формул:

<Функция> : = <Заголовок функции> ; <Тело><Заголовок функции>;<Директива> function <Идентификатор> ; <Тело>

<Заголовок функции> : = function <Идентификатор>[<Список формальных параметров>] : <Идентификатор>

Синтаксические диаграммы представлены на рис. 5.3.Процедуры описываются с помощью следующих формул: <Процедура> : = <Заголовок процедуры> ; <Тело><Заголовок процедуры>;

<Директива> procedure <Идентификатор> ; <Тело>

<Заголовок процедуры> : = procedure <Идентификатор>[<Список формальных параметров>]

Синтаксические диаграммы представлены на рис. 5.4.

ФункцияЗаголовок функции Тело

Директиваfunction Идентификатор Тело

<Заголовок функции> function ИдентификаторСписок формальных параметров Идентификатор

Рис. 5.3. Синтаксис описания функции

ПроцедураЗаголовок процедуры Тело

Директиваprocedure Идентификатор Тело

<Заголовок процедуры> function ИдентификаторСписок формальных параметров

Рис. 5.4. Синтаксис описания процедуры

Список формальных параметров имеет синтаксис:<Список формальных параметров> ::=

( <Формальный параметр> {;<Формальный параметр>})<Формальный параметр> ::= [var] <Идентификатор> {, <Идентификатор>}

: <Идентификатор> <Заголовок функции>

85

Page 86: Pascal material

<Заголовок процедуры>

Синтаксическая диаграмма представлена на рис. 5.5.

<Список формальных параметров>

var Идентификатор

ИдентификаторЗаголовок функцииЗаголовок процедуры

Рис. 5.5. Синтаксическая диаграмма <Список формальных параметров>

Отметим, что при отсутствии ключевого слова var идентификаторы из списка указывают параметры-значения. Слово var указывает параметры-переменные. Заголовок некоторой функции (процедуры) указывает на параметр-функцию (процедуру). В Turbo PASCAL такие параметры описываются явно, относятся к процедурному типу и имеют вид параметров-значений. Язык ПАСКАЛЬ расширяет обычный смысл понятия функции, допуская возврат значений не только через имя функции, но и через параметры-переменные.

Оператор вызова функции имеет вид:<Вызов функции> :: = <Имя функции> [<Список фактических параметров>]

а оператор вызова процедуры:<Вызов процедуры> :: = <Имя процедуры> [<Список фактических параметров>]

Фактические параметры описываются с помощью формул: <Список фактических параметров> ::=

( <Фактический параметр> {;<Фактический параметр>})<Фактический параметр> ::= <Выражение> <Переменная>

<Имя функции> <Имя процедуры>

Синтаксическая диаграмма представлена на рис. 5.6.

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

<Вызов функции> Имя функции Список фактических параметров

<Вызов процедуры> Имя процедуры Список фактических параметров

86

Page 87: Pascal material

<Список фактических параметров> ВыражениеПеременнаяИмя функцииИмя процедуры

Рис. 5.6. Синтаксис вызова функций и процедур

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

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

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

Вопросы и упражнения

1. Когда используется описание вида2. Укажите на синтаксических диаграммах рис. 5.3 и 5.5 пути, которые соответствуют описаниям

функций из программы Р115, параграф 5.9.3. Какова разница между параметром-значением и параметром-переменной?4. Укажите на синтаксических диаграммах рис. 5.4 и 5.5 пути, которые соответствуют описаниям

процедур из программы Р116, параграф 5.9.5. Как описываются формальные параметры-функции (процедуры) в языке ПАСКАЛЬ? В Turbo

PASCAL?6. Укажите на синтаксических диаграммах рис. 5.3-5.6 пути, которые соответствуют описанию и

вызову подпрограмм из программы Р102, параграф 5.4.

ГЛАВА 6ДИНАМИЧЕСКИЕ СТРУКТУРЫ ДАННЫХ

6.1. ДИНАМИЧЕСКИЕ ПЕРЕМЕННЫЕ. ССЫЛОЧНЫЙ ТИП

87

Page 88: Pascal material

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

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

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

Доступ к динамическим переменным осуществляется через переменные ссылочного типа. Как правило, ссылочный тип определяется описанием вида:

Type Tr = ^ Tb,

где Tr - имя ссылочного типа, а Tb – базовый тип. Знак “^” читается как «адрес». Очевидно, могут использоваться и анонимные ссылочные типы. Синтаксическая диаграмма <Ссылочный тип > представлена на рис. 6.1.

Множество значений ссылочного типа состоит из адресов.

<Ссылочный тип > Тип

Рис. 6.1. Синтаксическая диаграмма <Ссылочный тип>

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

Например:

Текущее значение переменной i будет указывать на динамическую переменную типа integer. Аналогично переменные ссылочного типа r и с указывают на переменные типа real и соответственно char. Отметим, что типы данных AdresaInteger, AdresaChar и анонимный тип ^real являются различными ссылочными типами.

К значениям ссылочного типа можно применять операции = и < >. Значения ссылочного типа не могут быть считаны с клавиатуры и выведены на экран.

Динамическая переменная создается с помощью стандартной функции new (новый). Вызов данной процедуры имеет вид

new(p),где р – переменная ссылочного типа.

Процедура выделяет область памяти для создаваемой переменной и возвращает адрес

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

Например:new (i) ; i ^ := 1 - создание динамической переменной типа integer; созданной переменной i

присваивается значение 1;new (r) ; r ^ := 2.0 - создание динамической переменной типа real; созданной переменной r

присваивается значение 2.0;

88

Page 89: Pascal material

new (c) ; c ^ := ‘*’ - создание динамической переменной типа char; созданной переменной c присваивается значение ‘*’.

Отметим, что динамическая переменная p^ , созданная при вызове new(p) отличается от всех переменных, созданных ранее. Следовательно, выполнение операторов

new(p); new(p); … new(p)приведет к созданию последовательности динамических переменных v1, v2, …, vn. При этом переменная p указывает на последнюю из созданных динамических переменных – на vn. Так как значения переменных ссылочного типа являются адресами конкретных областей внутренней памяти компьютера, данные переменные называются указателями адреса или просто указателями.

Уничтожение некоторой динамической переменной и освобождение соответствующей области памяти осуществляются с помощью стандартной процедуры dispose (освобождение). Вызов данной процедуры имеет вид:

dispose(p),где р – переменная ссылочного типа.

Например:

После выполнения процедуры dispose(p) значение переменной р ссылочного типа становится неопределенным.

К динамическим переменным можно применять все операции, допустимые в базовом типе.Например:

Program P117;{Операции над динамическими переменными}{создание динамических переменных типа integer}{операции над созданными переменными}{создание динамических переменных типа real}{операции над созданными переменными}{уничтожение динамических переменных}

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

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

Например:Program P118;{Ошибка: переполнение памяти}

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

Вопросы и упражнения

1. Какова разница между статическими и динамическими переменными?2. Как идентифицируются динамические переменные?

89

Page 90: Pascal material

3. Укажите на синтаксической диаграмме рис. 6.1 пути, которые соответствуют описаниям ссылочных типов из программы Р117.

4. Даны описания:

Укажите множество значений типа данных AdresaReal и множество значений, которые может принимать динамическая переменная r^.

5. Какие операции можно применять к ссылочным типам данных? А к динамическим переменным?

6. Даны описания:

Укажите множество значений типа данных AdresaTablou и множество значений, которые может принимать динамическая переменная t^.

7. Прокомментируйте программу:

Program P119;{Ошибка}

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

9. Что выведет на экран следующая программа?

Program P120;

10. Прокомментируйте программу:

Program P121;{Ошибка}

11. Объясните выражение динамическое распределение памяти.

6.2. СТРУКТУРЫ ДАННЫХ

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

Массивы, строки символов, записи, файлы и множества, изученные в предыдущих главах, относятся к неявным структурам данных. Связи между компонентами данных структур являются предопределенными и неизменяемыми. Например, все компоненты строки символов имеют общее имя, а символ s[i+1], с точки зрения занимаемой позиции, следует за символом s[i] Так как структура массивов, строк символов, записей, файлов и множеств не изменяется в процессе выполнения любой программы или подпрограммы, соответствующие структуры являются статическими.

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

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

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

90

Page 91: Pascal material

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

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

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

Вопросы и упражнения

1. Объясните термин структура данных. Приведите примеры.2. Какова разница между явными и неявными структурами данных?3. Структура данных является однородной, если все ее компоненты относятся к одному и тому

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

4. Какова разница между статическими и динамическими структурами данных?5. Объясните термин рекурсивная структура данных.

6.3. ОДНОСВЯЗНЫЕ СПИСКИ

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

В качестве примера на рис. 6.2 представлен односвязный список, составленный из четырех ячеек. Ячейки содержат элементы A, B, C и D.

поле указатель данных адреса

ячейка поле связей nil

Рис. 6.2. Односвязный список

Данные, необходимые для создания и обработки односвязного списка определяются описаниями вида:

Полезная информация, относящаяся к конкретной ячейке, запоминается в поле Info, а адрес следующей ячейки – в поле Urm. Для простоты считается, что тип Info является строковым. В поле Urm последней ячейки списка содержится значение nil. Адрес первой ячейки (базовый адрес) запоминается в переменную ссылочного типа р (рис.6.2).

Отметим, что при описании ссылочного типа AdresaCelula базовый тип Celula еще не известен. Согласно правилам языка ПАСКАЛЬ, это возможно только в случае динамических переменных при условии, что базовый тип определяется ниже в этом же описании.

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

Пример:Program P122;{Создание односвязного списка A - > B - > C - > D;}

91

Page 92: Pascal material

{базовый адрес}{1 – сперва список является пустым}

{2 – добавление ячейки А}{создание ячейки}{инициализация базового адреса}{ввод полезной информации}{запись индикатора «конец списка»}{запоминание адреса вершины списка}

{3 – добавление ячейки B}{создание ячейки}{инициализация базового адреса}{ввод полезной информации}{запись индикатора «конец списка»}{создание связи A - > B}{обновление адреса вершины списка}

{4 – добавление ячейки С}{создание ячейки}{инициализация базового адреса}{ввод полезной информации}{запись индикатора «конец списка»}{создание связи В - > С }{обновление адреса вершины списка}

{5 – добавление ячейки D}{создание ячейки}{инициализация базового адреса}{ввод полезной информации}{запись индикатора «конец списка»}{создание связи C - > D}{обновление адреса вершины списка}{вывод созданного списка на экран} Процесс составления данного списка представлен на рис. 6.3. Для того, чтобы установить

индикатор адреса V^.Urm, адрес последней созданной ячейки запоминается в переменной V (адрес вершины).

1 - сперва список является пустым2 - добавление ячейки А3 - добавление ячейки B4 - добавление ячейки C5 - добавление ячейки D

Рис. 6.3. Создание односвязного списка

Это необходимо потому, что на момент заполнения полей R^.Info и R.^Urm текущей ячейки адрес последующей ячейки еще не известен.

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

Program P123;{Создание линейных списков}

92

Page 93: Pascal material

{Создание}

{Вывод на экран}

Любой односвязный список можно определить рекурсивно следующим образом: a) отдельная ячейка является односвязным списком;b) ячейка, которая содержит указатель на другой линейный список, также является односвязным

списком.

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

Частично, свойства линейных списков можно воспроизвести путем запоминания соответст-вующих элементов в одномерный массив. Например, данные из рис. 6.2 можно представить в виде:

Однако такое представление является неприемлемым в случае списков с заранее неизвестным числом элементов.

Вопросы и упражнения

1. Как определяются данные, необходимые для создания списка?2. Для чего нужно поле данных, входящее в состав ячейки? Для чего нужно поле связей? Какая

информация записывается в данное поле?3. Напишите программу, которая создает односвязный список рис. 6.2, прибавляя к базе списка

по одному элементу.4. Напишите процедуру, которая меняет местами два элемента списка.5. С клавиатуры считываются числа, отличные от нуля. Создайте два списка, один из которых

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

данных?

6.4. ОБРАБОТКА ОДНОСВЯЗНЫХ СПИСКОВ

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

Предположим, что существует непустой список (рис. 6.2), определенный описанием:Переменная Р является базовым адресом списка.

Прохождение списка осуществляется согласно следующей последовательности операторов:

{установление указателя на базовую ячейку}{обработка информации из поля R^.Info}{установление указателя на следующую ячейку}

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

Адрес данной ячейки заносится в переменную R.

93

Page 94: Pascal material

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

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

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

Вставка ячейки, заданной указателем Q, за ячейкой, заданной указателем R (рис. 6.4) выполняется с помощью последовательности операторов:

Q^.Urm : = R^.Urm;R^.Urm := Q;

а бРис. 6.4. Вставка элемента в список:а – список до операции вставки; б – список после операции вставки

Для удаления элемента из списка необходимо найти адрес Q предыдущей ячейки и изменить указатель адреса Q^.Urm (рис. 6.5)

а б

Рис. 6.5. Удаление элемента из спискаа – список до операции удаления; б – список после операции удаления

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

Например:Program P124;{Создание и обработка односвязного списка}{базовый адрес}writeln(‘Список уже существует’);writeln(‘Введите список’);{Создание}

Procedure Afis;Writeln(‘Список пустой’);Writeln(‘Текущий список’);

Procedure Includ;Writeln(‘Введите элемент, который’);Writeln(‘будет вставлен:’);Writeln(‘Укажите элемент, после которого ’);Writeln(‘будет осуществляться вставка’);

Writeln (‘Несуществующий элемент’);{Вставлен}

Procedure Exclud;Writeln(‘Введите элемент, который’);

94

Page 95: Pascal material

Writeln(‘будет удален:’);Writeln (‘Несуществующий элемент’);

{Удален}

{сперва список пустой};writeln(‘Меню’);writeln(‘C – Создание списка’);writeln(‘I – Вставка элемента’);writeln(‘E – Удаление элемента’);writeln(‘A – Вывод списка на экран’);writeln(‘O – Остановка программы’);writeln(‘Выбор = ’);

writeln(‘Такой операции не существует’);

Процедура Creare создает односвязный список с произвольным количеством ячеек Полезная информация, связанная с каждой ячейкой, считывается с клавиатуры. Процедура Afis выводит элементы списка на экран. Процедура Includ считывает с клавиатуры элемент, который должен быть вставлен, и элемент, после которого должна выполняться вставка. Затем реализуется поиск ячейки, содержащей указанный элемент. Если такой элемент существует, вставляется новая ячейка. Процедура Exclud осуществляет поиск ячейки, содержащей элемент, считанный с клавиатуры, и удаляет ее, если таковая существует.

Вопросы и упражнения

1. Напишите нерекурсивную функцию, которая возвращает адрес вершины односвязного списка.2. Перепишите процедуры Includ и Exclud из программы Р124 без использования оператора goto.3. Даны следующие типы данных:

Напишите программу, которая:a) создает односвязный список с компонентами типа Candidat;b) выводит список на экран;c) удаляет из списка кандидата, который забирает документы;d) включает в список кандидата, который подает документы;e) выводит на экран кандидатов, средний балл которых больше 7,5;f) создает дополнительный список, составленный из кандидатов, средняя оценка которых

больше 9,0;g) удаляет из списка всех кандидатов, средний балл которых меньше 6,0.

4. Напишите процедуру, которая:

a) упорядочивает элементы односвязного списка согласно указанному критерию;b) склеивает два односвязных списка;c) разделяет заданный список на два отдельных списка;d) выбирает из списка элементы, которые удовлетворяют указанному критерию.

5. Элементы односвязного списка записаны в одномерный массив. Создайте процедуры, необходимые для:

a) прохождения списка;b) поиска определенного элемента;c) вставки заданного элемента;d) удаления заданного элемента.

95

Page 96: Pascal material

Каковы преимущества и недостатки такого представления? Считается, что список содержит максимум 100 элементов.

6. Напишите рекурсивную функцию, которая возвращает количество ячеек в односвязном списке.

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

Напишите программу, которая формирует список слов, встречающихся в текстовом файле, и считает, сколько раз появляется каждое слово. Рассмотрите случаи:

a) слова вставляются в список в порядке их первого появления в тексте;b) слова вставляются в список в алфавитном порядке.

Прописные и строчные буквы считаются идентичными.

6.5. ДВУСВЯЗНЫЕ СПИСКИ

Каждая ячейка двусвязного списка содержит в поле связей два указателя адреса. Первый указывает на следующую ячейку, а второй – на предыдущую. В качестве примера на рис. 6.6 представлен двусвязный список, составленный из четырех ячеек, которые содержат элементы A, B, C и D.

Рис. 6.6. Двусвязный список.

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

Переменные ссылочного типа P и V запоминают соответственно адрес первой ячейки (базовый адрес) и адрес последней ячейки (адрес вершины).

Двусвязный список можно создать путем добавления в вершину списка по одному элементу. Сперва, двусвязный список является пустым.

Например:Program P125;{ Создание двусвязного списка: A<->B<->C<->D} {базовый адрес}{адрес вершины}{1 – сперва список является пустым}

{2 – добавление ячейки А}{инициализация базового адреса}{инициализация адреса вершины}{3 – добавление ячейки B}{создание связи B - >A}{создание связи A - >B}{обновление адреса вершины}

{4 – добавление ячейки С}{создание связи C - > B }{создание связи В - > С }{обновление адреса вершины списка}

96

Page 97: Pascal material

{5 – добавление ячейки D}{создание связи D - > C}{создание связи C - > D}{обновление адреса вершины списка}

{вывод созданного списка на экран}

Процесс создания данного списка представлен на рис. 6.7.К двусвязным спискам можно применять следующие операции:

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

1 - сперва список является пустым2 - добавление ячейки А3 - добавление ячейки B4 - добавление ячейки C5 - добавление ячейки D

Рис. 6.7. Создание двусвязного списка

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

Пример: Program P126;{ Создание и прохождение двусвязного списка} {базовый адрес}{адрес вершины}writeln (‘Введите список:’);{Создание}writeln(‘Прохождение списка от базового элемента к вершине: ’);writeln(‘Прохождение списка от вершины к базовому элементу: ’);{Прохождение}

Вопросы и упражнения

1. Как описываются данные, необходимые для создания двусвязного списка? Каково предназначение полей Prec и Urm некоторой ячейки?

2. Напишите программу, которая создает двусвязный список, представленный на рис. 6.6, путем добавления по одному элементу к базовому.

3. Дополните программу Р126 процедурами, необходимыми для вставки и удаления элементов из созданного двусвязного списка.

97

Page 98: Pascal material

4. Напишите процедуру, которая:

a) переводит односвязный список в двусвязный;b) переводит двусвязный список в односвязный.

Можно ли выполнить такие переводы без использования дополнительного объема памяти? 5. Напишите процедуру, которая проходит односвязный список от вершины к базовому

элементу. Сравните сложность этой процедуры со сложностью соответствующей последовательности операторов из программы Р126.

6. Каковы недостатки и преимущества двусвязных списков по сравнению с односвязными списками? А по сравнению с одномерными массивами?

7. Вокруг судьи стоят N игроков. Начиная с игрока m, каждый k-й игрок выбывает. Напишите программу, которая выдает на экран порядок выбывания игроков из круга.

Указание: Игроки, расставленные по кругу, могут быть представлены в виде двусвязного списка, в котором установлена дополнительная связь между вершиной и базовым элементом (кольцевой список).

6.6. СТЕКИ

Под стеком (по-английски: stack) понимается односвязный список, вставка и удаление элементов в который можно производить только с одного конца списка. Ячейка, которую занимает последний введенный элемент, называется вершиной списка. Список, не содержащий ни одного элемента, называется пустым.

В качестве примера на рис. 6.8 представлен стек, который содержит элементы A, B, C. Данные, необходимые для создания и обработки стека, можно определить с помощью описаний

вида:

а б

Рис. 6.8. Стек:а- детальное представление; б - обобщенное представление

а б в

Рис. 6.9. Вставка и удаление элементов из стека:a - исходный стек; б - вставка элемента D; в - удаление элементов D, C.

Адрес вершины стека запоминается в переменной ссылочного типа S. Адрес предыдущей ячейки стека запоминается в поле Prec.

Операция вставки элемента в стек (рис. 6.9) выполняется с помощью следующей последовательности операторов:

new (R); {создание ячейки}{введение полезной информации

в поле R^Info}R^.Prec : = S; {создание связи

с предыдущей ячейкой стека}S : = R: {обновление адреса вершины}

где R является переменной типа AdresaCelula.

98

Page 99: Pascal material

Удаление элемента из стека (рис. 6.9.) выполняется с помощью следующей последовательности операторов:

R : = S; {запоминание адреса удаляемого элемента}{обработка информации из поля R^.Info}S : = S^.Prec; {удаление ячейки из стека}dispose(R); {уничтожение удаленной ячейки}

Например:

Program P127;{Создание и обработка стека}{адрес вершины}

procedure Introduc; write('Введите элемент, который нужно добавить');writeln(' который нужно вставить:');{ Introduc }

procedure Extrag;writeln('Стек пустой');write('Удален');writeln('элемент: ');{ Extrag }procedure Afis;writeln('Стек пустой');writeln('Стек включает элементы: ');{ Afis }

{Сперва стек пустой}writeln('Меню: ');writeln('I - Вставка элемента');writeln('E - Удаление элемента');writeln('A - Вывод стека на экран');writeln('O - Остановка программы');

writeln(' Ваш выбор: ');writeln(' Недопустимая операция ');

Стеки называют еще списками LIFO (last in, first out – последний элемент, введенный в стек, будет первым на выходе) и часто используют для динамического выделения памяти в случае рекурсивных процедур и функций. Очевидно, стеки можно имитировать, используя одномерные массивы: array [1..n] of …, однако такое представление ограничено только n ячейками.

Вопросы и упражнения

1. Каков порядок вставки и удаления элементов из списка?2. С клавиатуры считывается последовательность вещественных чисел. Выведите данные числа

на экран в порядке, обратного чтения.3. На рис. 6.10 представлена схема движения железнодорожных вагонов в депо.

Напишите программу, которая считывает с клавиатуры и выводит на экран данные о каждом вагоне, который зашел или вышел из депо. Эти данные должны включать:- регистрационный номер (integer);

99

Page 100: Pascal material

- станцию регистрации (string);- год выпуска (1960 - 2000);- тип вагона (string);- владельца вагона (string);- грузоподъемность (real).

Въезд Выезд

Тупик

Рис. 6.10. Схема движения железнодорожных вагонов в депо.

4. Можно ли использовать двусвязные списки для создания стеков?5. Временные рабочие группы создаются и упраздняются в следующем порядке: "Последний

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

- фамилию (string);- имя (string);- год рождения (1930 - 1985);- дату приема на работу (день, месяц, год).

6. Даны конечные строки символов, составленные из скобок: (, ), [, ], {, }. Строка является правильной, если она составлена по следующим правилам:a) пустая строка является правильной;b) если А является правильной строкой, то (А), [A], {A} – правильные строки;c) если A и B – правильные строки, то AB – правильная строка.

Например, строки: ( ), [ ], { }, [( )], ((({[ ]}))([ ])) – правильные, а строки: ([, ( )[ ]{{, ([)] – неправильные. Напишите программу, которая проверяет, является ли строка символов, считанная с клавиатуры правильной. Указание. Задачу можно решить, осуществляя проверку с помощью единственного просмотра строки. Если текущий символ (, [, или {, то он заносится в стек. Если вершина списка и текущий символ образуют пару ( ), [ ] или { }, то соответствующая скобка удаляется из стека. Если после проверки последнего символа строки стек остается пустым, то строка символов –правильная.

7. Элементы стека запоминаются в одномерном массиве. Напишите процедуры, необходимые для вставки и удаления элементов из стека. Каковы недостатки и преимущества такого представления? Считается, что стек состоит максимум из 100 элементов.

6.7. ОЧЕРЕДИ

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

В качестве примера на рис. 6.11 представлена очередь, которая содержит элементы A, B, C.

а б

100

Page 101: Pascal material

Рис. 6.11. Очередь:а – детальное представление; б – обобщенное представление

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

Адрес первого элемента очереди запоминается в переменную ссылочного типа Р, а адрес последнего элемента – в переменной U. Адрес последующего элемента очереди запоминается в поле Urm.

Операция вставки элемента (рис. 6.12) реализуется с помощью последовательности операторов:

new (R); {создание ячейки}{введение полезной информации

из поля R^Info}R^.Urm : = nil; {вставка индикатора

"последний элемент"}U^.Urm : = R: {добавление ячейки в очередь}

U : = R {обновление адреса последней ячейки}

а б в

Рис. 6.12. Вставка и удаление элементов из очереди:a – исходная очередь; б – вставка элемента D; в – удаление элементов A, B.

Удаление элемента из стека (рис. 6.12) выполняется с помощью последовательности операторов:

R : = P; {запоминание адреса первой ячейки}{обработка информации из поля R^.Info}P : = P^.Urm; {удаление первой ячейки}dispose(R); {уничтожение удаленной ячейки}

Например:

Program P128;{Создание и обработка очереди}{адрес первого элемента}{адрес последнего элемента}

procedure Introduc; write('Введите элемент');writeln(' который нужно вставить:');{ Introduc }

procedure Extrag;writeln('Очередь пустая');write('Удален');writeln('элемент: ');{ Extrag }

procedure Afis;writeln('Очередь пустая');writeln('Очередь содержит');

101

Page 102: Pascal material

writeln('элементы:');{ Afis }

{Сперва очередь пустая}writeln('Меню: ');writeln('I - Вставка элемента');writeln('E - Удаление элемента');writeln('A - Вывод очереди на экран');writeln('O - Остановка программы');

writeln(' Ваш выбор: ');writeln(' Операция неизвестна ');

Очереди называют ещё списками FIFO (first in, first out - первый элемент, который был введен в очередь, будет первым, который выйдет из нее). Отметим, что имитация очередей с помощью одномерных массивов является неэффективной по причине выбывания элементов очереди, начиная с последнего элемента массива.

Вопросы и упражнения

1. Можно ли использовать двусвязные списки для создания очереди? Какие преимущества были бы у такой структуры данных?

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

которая считывает с клавиатуры и выводит на экран данные о каждом самолете, запросившем разрешение на посадку и о приземляющемся самолете. Эти данные должны включать:

- регистрационный номер (integer);- тип самолета (string);- номер рейса (integer);

4. Очередью с приоритетами является очередь, в которой элемент вставляется ни после последнего элемента, а перед всеми элементами с наименьшим приоритетом. Приоритеты элементов задаются целыми числами. Напишите программу, которая:

a) создает очередь с приоритетами;b) вставляет в очередь элементы, указанные пользователем;c) удаляет элементы из очереди;d) выводит очередь с приоритетами на экран.

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

a) создание списка;b) добавление элемента в правый конец;c) добавление элемента в левый конец;d) удаление элемента из правого конца списка;e) удаление элемента из левого конца списка;f) прохождение списка слева направо;g) прохождение списка справа налево.

6.8. ДВОИЧНЫЕ ДЕРЕВЬЯ

102

Page 103: Pascal material

Под узлом понимается динамическая переменная типа record, которая содержит поле, предназначенное для запоминания полезной информации и поле для двух указателей адреса.

Двоичное дерево определяется рекурсивно следующим образом:a) отдельный узел является двоичным деревом;b) узел, содержащий связи с другими двумя двоичными деревьями, тоже является двоичным

деревом.

Считается, что пустое дерево не содержит ни одного узла. В качестве примера, на рис. 6.13 представлено двоичное дерево, в узлах которого содержится полезная информация A, B, C, D, E, F, G, H, I, J. Данные, необходимые для создания и обработки двоичного дерева, можно определить с помощью описаний вида:

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

Узел, к которому нет ни одной ссылки от других узлов, называется корнем. Адрес корня запоминается в переменной ссылочного типа Т. В случае пустого дерева Т = nil.

Два дерева, связанные с корнем, называются левым и правым поддеревом. Адрес левого поддерева запоминается в поле Stg, адрес правого – в поле Dr.

Считается, что корневой узел находится на нулевом уровне, уровень узла, связанного с узлом i-го уровня, является: (i+1)-ым. Обычно в графическом представлении двоичного дерева, узлы располагаются каждый на своем уровне: корень – на уровне 0, вершины, связанные с корнем, – на уровне 1 и т. д. (рис. 6.13). Узлы (i+1)-го уровня, связанные с узлами i-го уровня, называются его ветвями. На рис. 6.13 узел В является левой ветвью, а узел С – правой ветвью узла А; узел D является левой ветвью, а узел E – правой ветвью узла B и т. д.;

уровень 0уровень 1уровень 2уровень 3

Рис. 6.13. Двоичное дерево:a – детальное представление; б – обобщенное представление

Если узел х является ветвью узла у, то узел у называется родителем узла х. На рис. 6.13 узел А является родителем узлов В и С; узел В является родителем узлов D и E и т.д.;

Узел, к которому не подсоединяется ни одно поддерево, называется терминальным узлом. В противном случае узел является нетерминальным. Под высотой двоичного дерева понимается максимальный из уровней, к которым относятся терминальные узлы. Высота деревьев на рис. 6.13 равняется 3; узлы D, H, F, I и J являются терминальными узлами, а узлы A, B, C, E и G – нетерминальными.

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

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

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

Узлы дерева на рис. 6.13 будут созданы с помощью итеративного алгоритма в следующем порядке: A, B, C, D, E, F, G, H, I, J.

103

Page 104: Pascal material

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

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

Например: Program P129;{Создание двоичного дерева - итерация}{корень}{первый элемент очереди}{последний элемент очереди}

procedure ExtrageDinCoada; writeln('Очередь пустая');

procedure CreareArboreBinar;{Сперва дерево пустое}{Сперва очередь пустая}writeln('Введите корень:');{Создание корня}{Инициализация адреса корня}{Пока очередь не станет пустой}writeln('Введите ветви узла', R^.Info);writeln('левая:');writeln('правая:');

procedure AfisareArboreBinar;writeln('Дерево пустое');writeln('Дерево состоит из: ');writeln('Корень ', R^.Info);writeln(' Ветви: ');

Полезная информация, связанная с каждым узлом, считывается с клавиатуры. Признаком отсутствия ветви является нажатие клавиши <ENTER> (программа считывает с клавиатуры пустую строку символов). Отметим, что очередь, созданная в программе Р129, содержит не узлы, а только их адреса.

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

- создается корневой узел;- строится левая ветвь;- строится правая ветвь.

Согласно рекурсивному алгоритму узлы двоичного дерева на рис. 6.13 будут созданы в следующем порядке: A, B, D, E, H, C, F, G, I, J.

Пример:

Program P130;{Создание двоичного дерева - рекурсия}{корень}

function Arb : Arbore;

104

Page 105: Pascal material

{создание двоичного дерева}writeln('Введите левую ветвь');writeln('корня', s, ':');

procedure AfisArb;{Вывод двоичного дерева на экран}

writeln('Введите корень:');

Функция Arb считывает с клавиатуры полезную информацию узла, находящегося в процессе создания. Если считывается пустая строка, то узел не создается и функция возвращает значение nil. В противном случае, функция создает новый узел, записывает строку символов в поле Info и возвращает адрес созданного узла. В момент, когда необходимо заполнить поля Stg (адрес левого поддерева) и Dr (адрес правого поддерева), функция вызывает саму себя, таким образом переходя к построению соответствующего поддерева.

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

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

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

Вопросы и упражнения

1. Как определяется двоичное дерево? Объясните термины: корень, левое поддерево, правое поддерево, ветвь, уровень, терминальный узел, нетерминальный узел, высота двоичного дерева.

2. Сформулируйте итеративные алгоритмы, предназначенные для создания двоичных деревьев и их вывода на экран.

3. Как строится двоичное дерево с помощью рекурсивного алгоритма?4. Напишите программу, которая строит ваше генеалогическое дерево, рассчитанное на три-

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

5. Как можно изменить процедуру AfisArb из программы Р130 для того, чтобы двоичное дерево было выведено на экран в следующем порядке: правое поддерево, корневой узел, левое поддерево?

6. Напишите рекурсивную функцию, которая возвращает количество узлов двоичного дерева. Перепишите данную функцию в нерекурсивной форме.

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

- фамилия (string);- имя (string);- дата рождения (день, месяц, год);- гражданство (string).

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

105

Page 106: Pascal material

Напишите программу, которая создает в памяти компьютера и выводит на экран дерево турнира "на выбывание". Указание. Вначале составляется список игроков. Победители матчей первого тура заносятся во второй список. Далее создается список победителей второго тура и т. д.

8. Как нужно изменить функцию Arb из программы Р130 для того, чтобы двоичное дерево строилось в следующем порядке: A, C, G, J, I, F, B, E, H, D?

9. Функция Arb из программы Р130 строит двоичные деревья в следующем порядке: корневой узел, левое поддерево, правое поддерево. Напишите нерекурсивную процедуру, которая строит двоичные деревья в таком же порядке. Указание. Используется стек, элементы которого являются узлами. Вначале стек содержит только корневой узел. Для каждого узла из вершины стека строится левое поддерево, а затем - правое. Созданные узлы заносятся в стек. После построения правого дерева соответствующий узел удаляется из стека.

6.9. ОБХОД ДВОИЧНЫХ ДЕРЕВЬЕВ

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

- операции, которые изменяют структуру дерева (вставка или удаление узла);- операции, которые не затрагивают структуру дерева (поиск информации, печать информации,

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

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

Обход КЛП:

1) исследуется корень;2) обходится левое поддерево;3) обходится правое поддерево.

КЛП ЛКП ЛПК

Рис. 6.14. Методы обхода двоичных деревьев

Обход ЛКП:

1) обходится левое поддерево;2) исследуется корень;3) обходится правое поддерево.

Обход ЛПК:

1) обходится левое поддерево;2) обходится правое поддерево;3) исследуется корень.

Обозначения КЛП, ЛКП и ЛПК указывают порядок обхода: К – корень, Л – левое поддерево, П – правое поддерево. Методы обхода двоичных деревьев показаны на рис. 6.14.

При обходе деревьев на рис. 6.13 методом КЛП получаем следующий порядок посещения узлов:

106

Page 107: Pascal material

при обходе методом ЛКП получаем следующий порядок посещения узлов:

обход методом ЛПК приводит к следующему порядку посещения узлов:

Ниже представлена программа обхода двоичного дерева по всем трем методам.

Program P131;{Обход двоичного дерева}{корень}

function Arb{создание двоичного дерева}write ('Введите левую ветвь'); write (' узла ', s, ' : '); write ('Введите правую ветвь'); write (' узла ', s, ' : ');

procedure AfisArb{вывод на экран двоичного дерева}

procedure Preordine;{обход КЛП}

procedure Inordine;{обход ЛКП}

procedure Postordine;{обход ЛПК}

writeln('Введите корень: ');writeln(' обход КЛП ');writeln(' обход ЛКП ');writeln(' обход ЛПК ');

Отметим, что функция Arb создает узлы, совершая в процессе построения обход двоичного дерева методом КЛП. Процедура AfisArb выводит на экран узлы, совершая обход двоичного дерева методом ЛКП.

Вопросы и упражнения1. Какие операции можно применять к двоичным деревьям?2. Объясните методы обхода двоичных деревьев. Приведите примеры.3. Напишите списки узлов, полученные в каждом методе обхода двоичного дерева на рис. 6.15. 4. Перепишите в не рекурсивной форме процедуры Preordine, Inordine и Postordine из программы

Р131.5. Напишите подпрограмму, которая вычисляет высоту двоичного дерева.6. Напишите программу, которая выводит на экран все узлы, находящиеся на заданном уровне

двоичного дерева.7. Напишите рекурсивную процедуру, которая обходит двоичное дерево в порядке:

a) КПЛ (корень - правое поддерево - левое поддерево);b) ПКЛ (правое поддерево - корень - левое поддерево);c) ПЛК (правое поддерево - левое поддерево - корень):

107

Page 108: Pascal material

Перепишите созданную процедуру в нерекурсивном виде.

Рис. 6.15. Двоичное дерево

8. Напишите программу, которая выводит на экран уровень каждого узла двоичного дерева.9. Дано двоичное дерево, в котором терминальные узлы представляют целые числа, а

нетерминальные – бинарные операции: +, -, *, mod, div. Данное дерево можно рассматривать как представление арифметического выражения. Значение этого выражения вычисляется начиная с корня, путем выполнения операций над значениями подвыражений, представленных левым и правым поддеревом. Напишите функцию, которая возвращает значение арифметических выражений, представленных двоичными деревьями.

10. Даны арифметические выражения, составленные из операндов и двоичных операций: +, -, *, /. Операндами являются переменные, имена которых состоят из одной буквы, и константы, состоящие из одной цифры. Каждому арифметическому выражению i можно поставить в соответствие двоичное дерево:a) арифметическому выражению, составленному из одного операнда i, ставится в

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

b) арифметическому выражению вида Е1Е2, где Е1 и Е2 являются арифметическими выражениями, ставится в соответствие двоичное дерево, в корне которого содержится оператор “”, левым поддеревом является выражение Е1, а правым - выражение Е2.

Значение выражения вычисляется, начиная с корня, путем выполнения операций над значениями подвыражений, представленных левым и правым поддеревом. Напишите программу, которая:a) строит двоичные деревья для арифметических выражений, считываемых с клавиатуры;b) вычисляет арифметические выражения, представленные двоичными деревьями.

Указание. Алгоритм должен следовать рекурсивному определению рассматриваемого дерева. В качестве текущего оператора "" может выступать любой оператор: +, -, из выражения, подлежащего обработке. Операторы * и / могут выступать в роли текущих операторов, только когда выражение, подлежащее обработке, не содержит операторов +, -.

6.10. ДВОИЧНЫЕ ДЕРЕВЬЯ ПОИСКА

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

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

Из определения следует, что при обходе ЛКП (левое поддерево - корень - правое поддерево) двоичного дерева поиска узлы располагаются в порядке возрастания ключей, поэтому такие деревья называются двоичными деревьями поиска-сортировки.

На рис. 6.16 представлено двоичное дерево поиска. Для простоты указаны только ключи, связанные с соответствующими узлами. Обход ЛКП выдаст узлы в следующем порядке: 1, 2, 3, 4, 5, 6, 8, 9.

Рис. 6.16. Двоичное дерево поиска

108

Page 109: Pascal material

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

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

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

продолжается в левом или правом поддереве. Если соответствующее поддерево является пустым, то поиск завершается неудачей.

Например, для деревьев на рис. 6.16 и ключа 5 порядок обхода узлов будет следующим: 4, 8, 6, 5.Вставка узла, содержащего данный ключ, осуществляется аналогично:

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

вставка будет осуществляться либо в левое либо в правое поддерево.

Например, при вставке узла с ключом 7 в дерево на рис. 6.16 порядок обхода узлов будет следующим: 4, 8, 6. Вставленный узел будет левым поддеревом узла 6.

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

Program P132;{Двоичные деревья поиска}{корень}procedure Inserarewriteln('Корень уже существует');procedure AfisArb{Вывод двоичного дерева на экран}procedure Inordine{обход ЛКП}beginwriteln('Меню: ');writeln('С - Поиск');writeln('I - Вставка'); writeln('A - Вывод');writeln('P - Обход ЛКП');writeln('O - Остановка программы');writeln('Выбор = ');

writeln('Ключ = ');writeln('Несуществующий узел');

write('Ключ =');write('Информация = ');

writeln(' Недопустимая операция ');end

Процедура Cautare возвращает через параметр-переменную Р адрес узла, который содержит ключ ch, задаваемый пользователем.

Процедура Inserare вставляет в дерево узел и записывает в его поля ключ ch и полезную информацию inf. Отметим, что адрес Т дерева поиска передается в процедуру Inserare не через параметр-значение, а через параметр-переменную. Использование параметра-переменной необходимо, так как замена пустого поддерева осуществляется через замену значения nil в одном из полей с адресом Stg, Dr узла предыдущего уровня на адрес вставляемого узла.

109

Page 110: Pascal material

Преимущество двоичных деревьев поиска состоит в меньшем количестве операций поиска, необходимых для нахождения полезной информации. Очевидно, что в процессе поиска количество пройденных узлов не превышает значения h+1, где h - высота дерева. Отметим, что в случае списков количество поисков может достигать количества ячеек в списке - n. Обычно h << n.

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

а б в

Рис. 6.17. Двоичные деревья поиска, построенные путем последовательной вставки в порядке:a – возрастания; б – убывания; в – определенном по методу деления пополам.

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

Например, в случае ключей 1, 2, 3, 4, 5, 6 и 7 узлы могут быть вставлены в следующем порядке: 4, 2, 6, 1, 3, 5, 7 (рис. 6.17). Отметим, что высота деревьев на рис. 6.17а и 6.17б является h=6, а высота дерева на рис. 6.17в – h=2.

Вопросы и упражнения

1. Является ли двоичное дерево на рис. 6.15 двоичным деревом поиска?2. Какие операции можно применять к двоичному дереву поиска? Как выполняются эти

операции?3. Перепишите в нерекурсивном виде процедуры Inserare и Cautare из программы Р132. 4. В журнал занесены следующие данные о каждом ученике: фамилия, имя, дата рождения (день,

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

a) имя и фамилию;b) дату рождения;c) средний балл.

Для простоты считается что, все записи имеют разные ключи.

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

6. Двоичное дерево поиска построено путем последовательной вставки n узлов. Порядок вставки определяется методом деления пополам. Вычислите высоту дерева и количество операций, необходимых для поиска определенного узла дерева.

7. Сбалансированным деревом называется двоичное дерево поиска, организованное таким образом, что для любого узла дерева h(Stg) - h(Dr) 1, где h(Stg) - высота левого поддерева, а h(Dr) - высота правого поддерева. Напишите программу, которая:

a) проверяет, является ли двоичное дерево сбалансированным;

110

Page 111: Pascal material

b) переводит, если это необходимо, любое двоичное дерево поиска в сбалансированное дерево.

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

- имя файла;- дата создания (день, месяц, год);- время создания (часы, минуты, секунды);- длина файла.

Напишите программу, которая строит и выдает на экран двоичные деревья поиска, используя в качестве ключей:a) имя файла;b) дату и время создания.

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

Указание. Рассмотрите следующие ситуации:a) удаляемый узел является терминальным – в этом случае связь к данному узлу

устанавливается в nil;b) от удаляемого узла ответвляется только одно поддерево – в этом случае связь к данному

узлу перенаправляется к соответствующему поддереву;c) от удаляемого узла ответвляется два поддерева – в этом случае данный узел заменяется на

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

10. Каталог библиотеки составлен из карточек. В каждой карточке находится следующая информация:

- имя и фамилия автора;- название книги;- год издания;- инвентарный номер;

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

a) все книги, написанные одним автором;b) инвентарный номер книги, определяемый по фамилии автора, названию книги и году

издания.

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

6.11. ДЕРЕВЬЯ m-го ПОРЯДКА

Рассмотрим динамические переменные типа record, в поле связей которых содержатся m 2 указателей адреса. Как и в случае двоичных деревьев, будем называть такие переменные узлами.

Дерево m-го порядка определяется рекурсивно:

a) отдельный узел является деревом m-го порядка;b) узел, который содержит не большее m связей с другими деревьями m-го порядка, также

является деревом m-го порядка.

111

Page 112: Pascal material

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

Деревья 2-го порядка называются двоичными деревьями и были изучены в предыдущих параграфах. Деревья 3-его, 4-ого, 5-ого порядка и т. д. называются (по-английски: multiway tree).

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

Данные, необходимые для создания и обработки дерева m-го порядка, можно описывать с помощью объявлений вида:

Адреса ветвей узла запоминаются в компонентах: Dsc[1], Dsc[2], … , Dsc[m] массива Dsc. Адрес корня сохраняется в переменной ссылочного типа Т.

Самыми распространенными методами обхода деревьев m-го порядка являются: обход в ширину и обход в глубину.

При обходе в ширину узлы обходятся в порядке их появления на уровнях. Например, для деревьев на рис. 6.18 обход узлов будет осуществлен в следующем порядке: A, B, C, D, E, F, G, H, I, J, K.

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

Обход в глубину определяется рекурсивно: если дерево – пустое, то при обходе не выполняется никаких действий; если непустое, то сначала производится обход корня, затем обход деревьев слева направо. При обходе в глубину дерева на рис. 6.18 узлы располагаются в следующем порядке: A, B, C, E, F, J, K, G, H, D, I. Обход в глубину легко реализуется с помощью рекурсивного алгоритма.

Например:

Program P133;{Деревья m-го порядка}{корень}{первый элемент очереди}{последний элемент очереди}

procedure ExtrageDinCoadawriteln ('Очередь пустая');

procedure CreareArbore{изначально дерево пустое}{изначально очередь пустая}writeln('Введите корень: ');{создание корня}{инициализация адреса корня}while {пока очередь не является пустой}writeln('Введите ветви узла', R^.Info);

procedure AfisareArbore writeln('Дерево пустое');

writeln('Узел ', R^.Info );

112

Page 113: Pascal material

write('Ветви: '); beginwriteln('Обход дерева в ширину: ');writeln('Обход дерева в глубину: ');end

Полезная информация, связанная с каждым узлом, считывается с клавиатуры. Признаком отсутствия ветвей является нажатие клавиши <ENTER>. Отметим, что процедура CreareArbore в процессе создания узлов осуществляет обход дерева в ширину. Очевидно, что процедура AfisareArbore обходит узлы в порядке их создания.

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

Вопросы и упражнения

1. Приведите примеры деревьев 3-го, 5-го и 6-го порядка. 2. Как определяется дерево m-го порядка? Какие операции можно применять к данным

деревьям?3. Объясните методы обхода деревьев m-го порядка. Приведите примеры.4. Напишите рекурсивную программу, которая строит в памяти компьютера дерево m-го

порядка. Полезная информация, связанная с узлами считывается с клавиатуры. 5. Напишите функцию, которая возвращает:

a) количество узлов дерева m-го порядка;b) уровень определенного узла дерева;c) высоту дерева.

6. Перепишите в нерекурсивной форме процедуру InAdincime из программы Р133. 7. Как можно изменить процедуру InLatime из программы Р133, чтобы обход узлов дерева на

рис. 6.18 осуществлялся в следующем порядке: A, D, C, B, I, H, G, F, E, K, J?8. Как можно изменить процедуру InAdincime из программы Р133, чтобы обход узлов дерева на

рис. 6.18 осуществлялся в следующем порядке: A, D, I, C, H, G, F, K, J, E, B?9. Дано дерево m-го порядка, в котором информация, находящаяся в узлах, представляет собой

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

Терминальные узлы представляют собой файлы, а нетерминальные – каталоги. Полезная информация, связанная с каждым узлом включает:- имя файла или каталога (string[8]);- расширение (string [3]);- дату и время последнего изменения (соответственно день, месяц, год и час, минута,

секунда);- длину (integer);- атрибуты ('A', 'H', 'R', 'S').

Напишите программу, которая имитирует операции поиска, создания и удаления файлов и каталогов.

11. Иногда порядок m дерева не известен на момент написания программы, поэтому становится невозможным использование типа данных array [1..m] of Arbore. Для устранения этого недостатка соответствующий массив можно заменить на односвязный или двусвязный список.

113

Page 114: Pascal material

Напишите подпрограммы, необходимые для создания и обработки деревьев с неизвестным порядком.

6.12. ТИП ДАННЫХ POINTER

Данный параграф полностью относится к TurboPASCAL.Множество значений предопределенного типа pointer (указатель) состоит из адресов и

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

К значениям типа данных pointer можно применять операции: = и < >. Значения этого типа не могут быть считаны с клавиатуры или выведены на экран.

Переменная типа pointer вводится описанием вида:var p: pointer. Так как такое описание не содержит информацию о базовом типе, тип динамической переменной

p^ неизвестен. Следовательно, на переменные типа pointer нельзя ссылаться с помощью символа ^, наличие которого после такой переменной является ошибкой.

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

Program P134;{Тип данных pointer}{р будет указывать на динамическую переменную типа integer}{на экран выдается 1}{ р будет указывать на динамическую переменную типа real}{на экран выдается 1.0000000000Е+00}{ р будет указывать на динамическую переменную типа string} {на экран выдается AAA} Основной областью использования переменных типа pointer является распределение внутренней

памяти компьютера. В Turbo PASCAL динамические переменные заносятся в специальную область внутренней памяти, называемой heap (куча). Адрес начала этой области, называемый базовым адресом, заносится в предопределенную переменную HeapOrg типа pointer. Переменная HeapPtr типа pointer содержит адрес первой свободной зоны, называемой вершиной данной области (рис.6.19).

Свободная зона

Зона предназначеннаядля динамических переменных

Рис. 6.19. Структура области heap

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

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

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

114

Page 115: Pascal material

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

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

Вызов процедуры mark имеет вид:mark (p),

где p является переменной типа pointer. Процедура запоминает адрес вершины из HeapPtr в переменную p.

Вызов процедуры release имеет вид:release (p)Эта процедура переводит адрес вершины на позицию, зарегистрированную ранее процедурой

mark: значение, содержащееся в переменной р типа pointer заносится в указатель HeapPtr. Распределение области памяти, предназначенной для динамических переменных, можно

осуществлять с помощью следующего алгоритма:1) с помощью процедуры mark запоминается адрес вершины;2) с помощью процедуры new создаются динамические переменные;3) созданные динамические переменные используются;4) когда динамические переменные уже не нужны, пространство, занимаемое ими в области heap,

освобождается с помощью процедуры: release.Например:Даны следующие описания:

Предположим, что выполняются операторы:

Состояние области heap представлено на рис. 6.20а. Перед тем как создать динамическую переменную k^, оператор mark (p) запоминает в переменной р типа pointer фактическое значение из HeapPtr.

Если присутствует оператор

Свободная зона Свободная зона

Рис. 6.20. Состояние области heap,до (а) и после (б) выполняется оператор release(p)

release (p)

то область памяти, занимаемая динамическими переменными после вызова процедуры mark, а именно, k^, m^ и n^, будет освобождена (рис. 6.20б).

Так как предопределенная переменная HeapOrg сохраняет базовый адрес области heap, то все пространство, предназначенное для динамических переменных, можно освободить с помощью оператора:

release (HeapOrg)

Следующая программа наглядно показывает использование процедур: mark и release.

Program P135;

115

Page 116: Pascal material

{Выделение внутренней памяти}function LSt;{Создание односвязного списка}procedure AfisLst{вывод списка на экран}procedure Stv{создание стека}function Arb{создание двоичного дерева}write('Введите левую ветвь');writeln('узла ', s, ':');write('Введите правую ветвь');writeln('узла ',s, ':');procedure AfisArb{вывод двоичного дерева на экран}

beginwriteln('Введите список: ');writeln('Созданный список: ');{р сохраняет адрес из HeapPtr}writeln('Введите корень:');writeln('Созданное дерево:');{освобождение области памяти, занимаемой деревом}writeln('Введите стек: ');writeln('Созданный стек: ');{ освобождение области памяти, занимаемой списком и стеком}end

Отметим тот факт, что в нынешних версиях Turbo PASCAL, процедуры dispose и release не присваивают значение nil указателю адреса переменной, которая была уничтожена (рис. 6.20б). Так как освобожденная область памяти используется повторно, то в результате применения операций присваивания к уничтоженным переменным могут измениться значения вновь созданных динамических переменных.

Вопросы и упражнения

1. Каково множество значений типа данных pointer? Какие операции можно применять к этим значениям?

2. Прокомментируйте следующую программу:

Program P136;{Ошибка}

3. Когда используются переменные типа pointer?4. Является ли область heap структурой данных типа стек? Аргументируйте Ваш ответ.5. Запустите следующие программы. Объясните результаты, выводимые на экран.

Program P137;{Создание переменных i^, j^, k^}{p сохраняет адрес из j}{уничтожение переменной j^ и создание переменной m^}{изменение адреса в j} {уничтожение переменной m^ и создание переменной k^}

116

Page 117: Pascal material

Program P138;{Создание переменных i^, j^}{освобождение области heap}{ создание переменных: k^ и m^}

6. Напишите процедуру, которая освобождает область памяти, занимаемую:a) односвязным списком;b) двоичным деревом;c) деревом m-го порядка.

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

7. Напишите программу, которая вначале создает очередь, а затем дерево m-го порядка. Область памяти, освобожденную после уничтожения очереди, необходимо использовать для размещения создаваемого дерева.

117

Page 118: Pascal material

Глава 7

МЕТОДЫ РАЗРАБОТКИ ПРОГРАММНЫХ ПРОДУКТОВ

7.1. МОДУЛЬНОЕ ПРОГРАММИРОВАНИЕ

Модульное программирование снижает уровень сложности больших программ путем их разбиения на модули.

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

В стандартном языке не предусмотрены средства для создания модулей. Программа на языке ПАСКАЛЬ является единым целым и должна компилироваться вместе со всеми своими подпрограммами. Однако это не удобно в случае больших программ, которые содержат десятки или даже сотни подпрограмм.

В версии TurboPASCAL модули реализуются с помощью Unit-ов. Общая форма модуля имеет вид:

unit <Имя>interface[uses <Имя> { <Имя>};][<Константы>][<Типы>][<Переменные>][{<Заголовок функции>; < Заголовок процедуры>;]

implementation[uses <Имя> { <Имя>};][<Метки>][<Константы>][<Типы>][<Переменные>][<Подпрограммы>][{function <Идентификатор>; < Тело>;procedure <Идентификатор>; < Тело>;][begin[<Оператор> {; <Оператор>}]]end.

Модуль программы состоит из трех разделов: интерфейсный раздел, раздел реализации, раздел инициализации.

Интерфейсный раздел начинается с ключевого слова interface. Здесь находятся описания констант, типов, переменных и подпрограмм, экспортируемых модулем. Эти элементы доступны любому модулю, который использует рассматриваемый модуль непосредственно или по транзитивности. Отметим, что в интерфейсном разделе находятся только заголовки экспортируемых процедур и функций. Если в данном модуле используются другие модули, то их имена указываются в строке uses.

Раздел реализации начинается с ключевого слова implementation. В этом разделе находятся локальные описания меток, констант, типов, переменных и подпрограмм. Элементы, определенные здесь, «скрыты» и не доступны для других модулей. После локальных описаний следует тело

118

Page 119: Pascal material

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

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

Например:Unit U1;{Обработка массивов}procedure Citire;{Считывание}procedure Afisare;{Вывод на экран} Модуль U1 экспортирует константу nmax, тип Vector, переменную n, функции sum, min, max,

процедуры Citire и Afisare. Исходное значение переменной n считывается с клавиатуры. Эти элементы доступны любой программе, которая содержит строку: uses U1.

Например:Program P139;{Использование модуля U1}writeln(‘Введите массив: ’);writeln(‘Был введен: ’);

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

1. Описания из раздела реализации видимы только в данном модуле.2. Описания из интерфейсного раздела видимы:

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

3. Если один и тот же идентификатор описан в нескольких модулях, то во внимание принимается самое последнее описание.

Например:Program P140;writeln (‘Программа P140’);

Unit U2;writeln(‘ Модуль U2:’);

writeln(‘ Модуль U3:’);

В программе Р140 модуль U2 используется непосредственно, а модуль U3 по транзитивности. Ссылка на переменную n из модуля U3 производится через U3.n. Идентификатор x появляется в описаниях var x: real в модуле U2 и var x: integer в программе P140. Компилятор принимает во внимание последнее описание.

119

Page 120: Pascal material

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

System – содержит все стандартные подпрограммы из Turbo PASCAL. Данный модуль автоматически вставляется во все программы, без включения строки uses.

Crt – позволяет использовать процедуры и функции для работы с экраном в текстовом режиме, а также с клавиатурой и громкоговорителем. Доступ к подпрограммам осуществляется через строку uses crt.

Graph – включает подпрограммы, предназначенные для графической обработки: выбор окон и страниц, выбор цвета и палитры, создание дуг, окружностей, многоугольников и других фигур, сохранение изображений и т. д. Доступ к подпрограммам данного модуля осуществляется через строку uses graph.

Printer – заменяет принтер на текстовый файл с именем lst. При использовании данного модуля программисту не требуется объявлять, открывать и закрывать данный файл. Модуль Printer становится доступным программе или модулю программы при наличии строки uses printer.

Назначение и способ использования констант, типов данных, переменных, функций и процедур стандартных модулей можно найти в руководствах по использованию и в системах помощи Turbo PASCAL’s Online Help.

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

Вопросы и упражнения

1. Каковы преимущества модульного программирования? Предусмотрены ли в стандартном языке средства для модульного программирования?

2. Какова стандартная форма модуля программы? Объясните структуру и назначение интерфейсного раздела, раздела реализации и инициализации.

3. Как определяется область видимости описаний в модулях программы?4. Укажите, что выведет на экран следующая программа.

Program P141;

Unit U4;

5. Прокомментируйте программу:

Program P142;{Ошибка}

Unit U6;

6. Дополните модуль U1 из данного параграфа подпрограммой, которая:

a) возвращает среднее арифметическое значение элементов массива;b) располагает элементы массива в порядке их возрастания;c) возвращает произведение элементов массива; d) возвращает количество положительных элементов массива;e) располагает элементы массива в порядке убывания.

120

Page 121: Pascal material

7. Напишите модуль, который содержит описания данных и подпрограммы для обработки матриц.

8. Целые числа n, n 10254 могут быть представлены в компьютере в виде строк, составленных из символов: ’+’, ‘-‘, ‘0’, ‘1’, ‘2’, …, ‘9’. Напишите модуль, который содержит процедуры и функции, необходимые для выполнения следующих операций:

a) чтение чисел с клавиатуры;b) вывод чисел на экран;c) +, -, *, mod, div;d) вычисление факториала;e) чтение и запись чисел в файлы последовательного доступа.

9. В программах Turbo PASCAL строки символов длины n, n 500, могут представляться переменными типа:

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

a) чтение строк с клавиатуры;b) вывод строк на экран;c) конкатенация (склеивание) строк;d) лексикографическое сравнение;e) вычисление длины строки.

10. Напишите модуль для обработки:

a) односвязных списков;b) двусвязных списков;c) очередей;d) стеков;e) двоичных деревьев;f) двоичных деревьев поиска;g) деревьев m-го порядка.

Для этого используйте описания типов, функций и процедур из главы 6.

11. Найдите в системе помощи Turbo PASCAL’s Online Help описание стандартных модулей, установленных на вашем компьютере. Выведите на экран текст каждого модуля, определите назначение и способ использования соответствующих процедур и функций.

7.2. ПРОВЕРКА И ОТЛАДКА ПРОГРАММ

Программа является правильной, если:a) процесс вычислений завершается за конечное время;b) полученные результаты являются решением именно той задачи, для которой была написана

программа.

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

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

121

Page 122: Pascal material

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

- функциональная проверка или метод черного ящика; - структурная проверка или метод прозрачного ящика.

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

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

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

- считывает с клавиатуры строку вещественных чисел;- выводит на экран среднее арифметическое значение положительных чисел строки.

Очевидно, область входных данных составлена из всевозможных строк вещественных чисел.Тестовые данные будут включать:a) нетипичные значения:

- пустую строку;- строку, которая не содержит положительных чисел;- строку, которая содержит только одно положительное число;

b) типичные значения:

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

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

a) выполнение каждого простого оператора (оператора присваивания, оператора вызова процедуры, оператора перехода goto);

b) выполнение каждого цикла for ноль, один и более раз;c) выполнение каждого оператора if, repeat, while для значений true, false соответствующих

булевых управляющих выражений;d) выполнение каждого случая, заданного в операторе выбора case.

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

Program P143;{ Cреднее арифметическое значение положительных чисел}writeln(‘Введите строку вещественных чисел: ’);writeln(‘Пустая строка’);writeln(‘Строка не содержит положительных чисел’);writeln(‘Среднее = ’, s/k);

Тестовые данные должны обеспечить выполнение операторов while и if для значений true и false булевых выражений: not eof, x>0, n=0 и k=0. Следовательно, тестовые данные будут включать:

122

Page 123: Pascal material

- пустую строку (not eof = false, n = 0);- непустую строку (not eof = true, n 0);- строку, которая содержит, по крайней мере, одно положительное число (x>0, k 0);- непустую строку, которая содержит только отрицательные числа (x0, k = 0).

Метод прозрачного ящика можно использовать независимо или вместе методом черного ящика для того, чтобы улучшить качество выполненных проверок. Например, в случае программы Р143 строку, содержащую, по крайней мере, одно положительное число, можно заменить на три строки, которые содержат соответственно одно, два, три или более положительных числа. Эти данные обеспечат выполнение операторов k:=k+1; s:=s+x и вычисление выражения s/k для типичных и нетипичных значений переменных k и s.

Применение структурной проверки связано со значительными трудностями из-за наличия условных операторов (if, case), операторов цикла (for, while, repeat) и операторов перехода (goto). Очевидно, существует огромное количество комбинаций, для которых необходимо выполнять все операторы присваивания и вызова процедур.

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

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

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

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

Подробное описание указанных средств можно найти в системе помощи Turbo PASCAL’s Online Help.

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

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

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

Вопросы и упражнения

123

Page 124: Pascal material

1. Когда программа на языке ПАСКАЛЬ является правильной? Как обеспечивается правильность программы?

2. Как производится отбор входных данных по методу функционального тестирования?3. Осуществите функциональную проверку программы Р124 из параграфа 6.4. Программа

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

- создает односвязный список;- выводит список на экран;- вставляет в список заданный элемент;- удаляет из списка элемент, указываемый пользователем.

4. Определите функции, которые выполняют следующие программы, и выполните функциональные проверки:

a) из главы 3;b) из главы 4;c) из главы 6;

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

a) из главы 3;b) из главы 4;c) из главы 6.

7. Какова разница между статической и динамической отладкой?

8. Найдите в системе помощи Turbo PASCAL’s Online Help описание средств для динамической отладки. Выполните отладку Ваших программ.

7.3. ЭЛЕМЕНТЫ СТРУКТУРНОГО ПРОГРАММИРОВАНИЯ

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

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

- блок (последовательность двух или более операторов присваивания и/или операторов вызова процедур);

- условие (if … then … или if … then … else …);- цикл с предусловием (while … do).

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

- выбор (case … of);- цикл с постусловием (repeat … until …);- цикл со счетчиком (for … do …).

124

Page 125: Pascal material

Основные правила структурного программирования:1. Структура любой программы или подпрограммы должна представлять собой комбинацию

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

задачи.3. Максимальная длина функции или процедуры 50-100 строк. Не рекомендуется использовать

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

процедур и модулей программы должны нести в себе информацию о соответствующих объектах.

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

6. Операции ввода-вывода необходимо выделять в отдельные подпрограммы. Правильность входных данных нужно проверять сразу после их считывания.

7. Вложенные операторы if необходимо заменять оператором case.

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

Вопросы и упражнения

1. Что такое структурное программирование?2. Укажите структуры управления, необходимые и достаточные для представления любого

алгоритма.3. Сформулируйте основные правила структурного программирования.4. Каковы преимущества структурного программирования?5. Удовлетворяют ли программы Р124, Р130 и Р135 из главы 6 основным правилам структурного

программирования?6. Программа Р144 выводит на экран всевозможные представления натурального числа n в виде

суммы последовательных натуральных чисел.

Program P144;writeln(‘Представлений не существует’);

Например, для n = 15 получаем:

Эти представления вычисляются с помощью метода перебора, рассматривая последовательности:1, 2, 3, … k;2, 3, … k;3, …, k

и т. д., где k = (n+1) div 2. Члены 1, 2, 3, … k вычисляются с помощью рекуррентного соотношения a: = a+1.

Расположите текст программы согласно логической и синтаксической структуре каждого оператора.

125