55885

Программирование и алгоритмические языки

Конспект

Педагогика и дидактика

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

Русский

2014-03-30

1006 KB

1 чел.

Государственноеобразоватеьное учреждение

Высшего профессионального образования

«МОСКОВСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ ЛЕСА»

А.В. Корольков, А.М. Ветошкин

Программирование и алгоритмические языки

Курс лекций для специальности 

«Прикладная математика»

Первый семестр

Москва

Издательство Московского государственного университета леса

2010
Содержание


Общие сведения.

Название курса: «Программирование и алгоритмические языки»

Вид занятий

часов в 1 семестре

часов во 2 семестре

Лекций

34 (2 час/нед)

34 (2 час/нед)

Практических

34 (2 час/нед)

17 (1 час/нед)

Лаборат

34 (2 час/нед)

34+17 (3 час/нед)

Отчетность

I семестр

Программы на 20 баллов

Контрольная

Коллоквиум

Зачет

Экзамен

II семестр

Программы на 10 баллов (до 1 апреля)

Контрольная

Курсовая работы

Экзамен

Содержание курса

I семестр

лек. 1- 7

лек. 8-12

лек.13-17

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

Технологии программирования, реализация на ТР

Модули, стандартные модули.

II семестр

лек.1-7

лек. 8- 14

лек. 15-17

Абстрактные Структуры Данных (АСД), реализация на ТР.

Технологии программирования, реализация на языке Fortran

Общие вопросы программирования

Дальнейшее обучение программированию (по семестрам)

Математическое обеспечение ЭВМ (3,4)

Методы разработки ПО (Объектно-ориентированное программирование ОП) (4)

Машинно ориентированные языки (4,5)

Компьютерная графика (5,6)

Проектирование трансляторов (6,7-кр)

Системное программное обеспечение (ПО) (6,7,8-кр)

Базы данных и экспертные системы (7,8)

ПО современных коммуникаций (9 каф ЭМТ)

Рекомендуемая литература

  •  Фигурнов. IBM PC для пользователей. "Ф и С", 1995.
  •  Йенсен К., Вирт Н. Паскаль: руководство для пользователя. – М.: Финансы и статистика, 1989.
  •  Фаронов В.В. Турбо-Паскаль 7.0. Начальный курс. Учебное пособие. М. 1997.
  •  Ван Тассел Д. Стиль, разработка, эффективность и испытания программ. -М.: Мир. 1985.
  •  Дал У., Дейкстра Э., Хоар К. Структурное программирование. - М.: Мир, 1975.
  •  Горелик А.М.,  Ушакова В.Л.,  Шура-Бура М.Р.  Мобильность программ на Фортране. "Ф и С", 1984.
  •  Боровин Г.К., Комаров М.М., Ярошевский В.С. Ошибки-ловушки при программировании на Фортране. Статистика, 1989.
  •  Вирт Н. Алгоритмы и структуры данных. – С-П, 2001.
  •  Дал У., Дейкстра Э., Хоар К. Структурное программирование. - М.: Мир, 1975.
  •  Программирование на языке Паскаль. Задачник. Под ред. О.Ф.Кусковой. Питер, 2002.

I семестр

Лекция 1

1.1 Алгоритм. Понятие алгоритма

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

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

1.2 Алгоритмические языки

Записать алгоритм можно на любом языке (на русском, на китайском, на языке условных знаков). Однако, для записи алгоритма для такого строгого исполнителя, как вычислительная машина, не все языки годятся. Вычислительная машина «умеет» выполнять лишь определенный набор машинных команд. Именно в терминах машинных команд должен быть сформулирован для нее алгоритм.

Записывать алгоритмы для вычислительной машины в кодах очень непроизводительно. Поэтому для записи алгоритмов для ЭВМ разработаны специальные строгие математические языки, называемые алгоритмическими языками. В настоящее время существует много алгоритмических языков. Они отличаются друг от друга различными выразительными средствами записи алгоритмов и различными возможностями. Но всех их объединяет одно – для каждого из них разработаны специальные программы, называемые трансляторами, с помощью которых текст, написанный на алгоритмическом языке, превращается в алгоритм, записанный на языке машинных кодов.

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

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

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

Здесь этап 1 – творческие усилия составителя алгоритма, этап 2 – формализованный перевод алгоритма в текст на алгоритмическом языке, этап 3 – трансляция текста с алгоритмического языка в коды машины.

1.3 Запись алгоритма

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

a). Элементарная операция присваивания. В прямоугольнике записывается сама операция.

b). Элементарная операция ввода. В параллелограмме записывается ключевое слово «Ввод» и список переменных через запятую, значения которых должны быть введены. В данном случае вводится значение единственной переменной X.

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

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

d). Подалгоритм, требующий дальнейшей детализации. В прямоугольнике с двойными боковыми ребрами записывается имя подалгоритма. В данном случае имя подалгоритма «Ф».

e). Решение. С помощь этой конструкции можно осуществлять ветвление алгоритма в зависимости от значения логического выражения Усл внутри ромбика. Если значение логического выражения «истина», то осуществляется переход по стрелке «да», в противном случае по стрелке «нет». Условимся всегда стрелку «да» рисовать влево, стрелку «нет» - вправо.

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

1.4 Элементарные структуры

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

Структура a) – линейная. Действия выполняются последовательно – сначала выполняется фрагмент Ф1, затем фрагмент Ф2. Структура b) – выбор. В зависимости от истинностного значения логического выражения Усл выполняется либо фрагмент Ф1, либо фрагмент Ф2. Структура с) – цикл. Многократно повторяется фрагмент Ф1 – тело цикла, перед каждым последующим выполнением тела цикла выполняется фрагмент Ф2 – модификатор. Логическое выражение Усл является условием выхода из цикла.

Если Вы хотите записать решение задачи с помощью перечисленных схем, попробуйте изложить решение задачи на бытовом, разговорном языке. В изложении решения неминуемо будут использоваться такие конструкции, как «сначала … затем», «если … то … иначе …», «повторяем … пока …», или на них похожие. Эти конструкции определяют соответствующие элементарные структуры. Попробуйте определить самую внешнюю структуру Вашего алгоритма. Если это удастся, то алгоритм разобьется на два подалгоритма (Ф1 и Ф2), которые можно записывать независимо, как решение двух более простых задач.

Заметим, что элементарные структуры имеют единственный вход и единственный выход. Таким образом, элементарные структуры топологически совместимы, то есть, вместо любого фрагмента можно поместить любую структуру. Поэтому, записав подалгоритмы Ф1 и Ф2, мы можем записать и сам алгоритм, связав решения соответствующей структурой.

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

Лекция 2

2.1. Договоренности о синтаксисе

Для того, чтобы построить таблицу перевода элементарных структур на алгоритмический язык, необходимо познакомиться с минимальными синтаксическими требованиями этого алгоритмического языка. На примере языка Турбо Паскаль (Turbo Pascal – ТР) мы сформулируем эти минимальные требования, чтобы каждый из вас мог самостоятельно построить таблицу перевода элементарных структур на другой алгоритмический язык. Поскольку в настоящем разделе мы познакомимся не с синтаксисом языка ТР, а лишь с его частью, достаточной для записи алгоритма, использоваться, пока, будет не вся мощь алгоритмического языка.

Нам потребуются следующие элементы языка ТР:

Целая константа - цепочка цифр, возможно со знаком (Например: 1,-1995,+22).

Действительная константа - цепочка цифр с точкой, возможно со знаком (Например: 3.1415, -0.0, +0.0001).

Переменная = <имя, тип, значение>. Имя - идентификатор (слово из латинских букв и цифр, начинающееся с буквы), Тип - действительный или целый (пока), значение должно соответствовать типу.

Арифметические операции + (сложение), - (вычитание), * (умножение), / (деление), div (деление целых), mod (взятие остатка).

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

Отношения: равно (=), не равно (<>), больше (>), больше либо равно (>=), меньше (<), меньше либо равно (<=) - связывают арифметические величины, результат - логическая величина (принимает значения либо «истина» (TRUE), либо «ложь» (FALSE)).

Логические операцииnot (отрицание), and (логическое умножение), or (логическое сложение).

Логические выражения – осмысленные комбинации логических величин, связанных логическими операциями.

2.2. Текст программы на Turbo Pascal

Текст программы на языке ТР представляет собой последовательность символов (латинские буквы и некоторые знаки кодовой таблицы). Транслятор читает этот текст последовательно, игнорируя разбиение на строки, не различая строчные и прописные буквы, пропуская комментарии (часть текста, заключенная в фигурные скобки { }). Символ пробел является разделителем слов, несколько пробелов подряд воспринимается как один пробел. Символ точка с запятой является разделителем между предложениями (операторами языка). В любом месте программы, где допустимо записать какой-нибудь оператор, можно записать пустой оператор (ничего не писать).

Текст программы на языке ТР начинается с заголовка program <имя программы>, где имя программы – уникальный идентификатор в программе. Заканчивается текст программы на языке ТР закрывающей логической скобкой end с точкой. С открывающей логической скобки begin, соответствующей последнему end программы, начинается секция действий. Секция действий состоит из записи алгоритма решения задачи на алгоритмическом языке ТР. Именно сюда и помещается текст, полученный из алгоритма по таблице перевода.

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

2.3 Элементарные операции

При записи на ТР элементарной операции присваивания следует учесть, что имя операции – комбинация символов := (двоеточие и равенство), слева от имени оператора записывается имя переменной, которой присваивается значение, а справа – выражение. В выражении должны использоваться только допустимые для данного типа операции, порядок выполнения операций лучше указать скобками.

Элементарные операции ввода реализуются предопределенными в ТР процедурами ввода read и readln.

Read ( <список элементов ввода через запятую>)

Readln ( <список элементов ввода через запятую>)

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

Элементарные операции вывода реализуются предопределенными в ТР процедурами вывода write и writeln.

Write ( <список элементов вывода через запятую>)

Writeln ( <список элементов вывода через запятую>)

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

2.4. Таблица перевода для структур

Пусть нам удалось записать на языке ТР фрагменты Ф1 и Ф2.

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

Чтобы связать фрагменты Ф1 и Ф2 структурой выбора, можно использовать следующий оператор ТР:

if Усл then begin Ф1 end else begin Ф2 end

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

Чтобы связать фрагменты Ф1 и Ф2 структурой цикла, можно воспользоваться следующей конструкцией:

M1: Ф1; if Усл then goto M2; Ф2; goto M1; M2:

Здесь используются метки M1 и M2, которые должны быть описаны в секции описаний. Предложенная реализация цикла довольно неуклюжа, однако, практически всегда можно модифицировать цикл так, либо фрагмент Ф1 отсутствовал, либо фрагмент Ф2 отсутствовал. Для таких частных случаев в языке ТР имеются очень удобные операторы:

repeat Ф1 until Усл

while not Усл do begin Ф2 end

Пример

Вычислить S = 1 - x2/2! + x**4/4! - x**6/6! + ... с точностью E.

Алгоритм:

Текст программы

PROGRAM Example01;

LABEL M17,M18;

var X,E,S,A:REAL; I,ZN:INTEGER;

BEGIN

READLN(X,E);

S:=0;

ZN:=1;

I:=0;

A:=1;

M17: S:=S+ZN*A;

IF A<E THEN GOTO M18;

ZN:=-ZN;

I:=I+2;

A:=A*X*X/(I*(I-1));

GOTO M17;

M18: WRITELN(S);

END.

2.5 Практические рекомендации по решению задач

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

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

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

2.6. Понятие о файловой системе

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

2.7. Интегрированная среда ТР

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

Лекция 3

3.1 Проект программы

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

  1.  Точная формулировка задачи, включая разработку будущего интерфейса пользователя, с описанием входных и выходных данных.
  2.  Выбор типов данных, соответствующих параметрам объекта исследования, выбор имен констант, переменных, процедур и функций, соответствующих этим параметрам и описывающих функционирование объекта исследования.
  3.  Создание структур данных, моделирующих взаимосвязь параметров объекта исследования.
  4.  Разработка иерархии алгоритмов и подалгоритмов (процедур и функций), обрабатывающих созданные структуры данных.
  5.  Разработка алгоритма решения задачи.

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

3.2. Частные случаи для структуры цикла

Полный цикл с) пункта 1.4 редко используется при разработке алгоритмов. При решении конкретных задач используются частные случаи этого цикла, в которых отсутствует один из блоков – либо Ф1, либо Ф2. Можно строго математически доказать, что этих двух частных случаев цикла достаточно для организации любого цикла.

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

S=1-1/2+1/3-1/4+1/5-1/6-...+1/999-1/n.

В этом решении использован полный цикл. Однако, нетрудно видеть, что подалгоритм «Накопление» можно реализовать по-другому. Сравните представленные ниже реализации:

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

Для реализации цикла с предусловием на языке ТР (как и на многих других языках) удобнее вместо условия выхода из цикла использовать условие продолжения цикла (напоминаю, в блоке решения стрелка влево всегда помечается значением «истина», стрелка вправо – значением «ложь»):

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

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

Цикл с постусловием

Цикл с предусловием

readln(n);

S=0; Zn=1; I=1;

repeat

  S=S+Zn/I;

  Zn=-Zn;

  I=I+1

until I>n;

writeln(S)

readln(n);

S=0; Zn=1; I=1;

while not(I>n) do

begin

  S=S+Zn/I;

  Zn=-Zn;

  I=I+1;

end;

writeln(S)

Если в решении задачи заранее известно количество повторений тела цикла (в нашей задаче n), можно упростить изображение структуры, указав лишь операции в теле цикла и границы изменения параметра цикла – начальное значение, конечное значение и шаг. Такой цикл называется циклом с параметром. На языке ТР имеется оператор цикла с параметром.

В решении задачи параметром цикла может оказаться любая переменная, соответствующая какому-либо параметру объекта исследования. Однако, решение можно всегда переформулировать так, что параметром цикла будет служить номер итерации (повторения выполнения тела цикла). В этом случае параметр цикла будет изменяться всегда от 1 до максимального номера итерации с шагом 1.

3.3 Массивы

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

x1,x2,...x10 – обозначения, принятые в математике, x[1],x[2],...x[10] – в ТР.

Индексами могут служить выражения.

Объявление массива в программе:

VAR <Имя>: ARRAY[<Нач_индекс>..<Кон_индекс>] of <Тип>;

где 

  •  <Имя> - имя переменной-массива;
  •  ARRAY, of - ключевые слова;
  •  <Нач_индекс> и <Кон_индекс> - целые числа (пока), определяющие диапазон изменения индексов (номеров) элементов массива;
  •  <Тип> - тип элементов массива.

Таким образом, при объявлении массива необходимо указать его идентификатор (имя), тип данных элементов массива и размер. В квадратных скобках указываются величины, соответствующие начальному и конечному индексам, разделенные двумя точками.

Например,

VAR

Matrix : ARRAY [1 .. 10]  OF  REAL;

Koef : ARRAY [1 .. 3]  OF  INTEGER;

Пример 

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

Массив Х, содержащий 100 элементов.

Ввести n (n<=100).

(Нарисовать схемы и записать тексты)

i:=1;

WHILE i<=n DO BEGIN

READLN(Х[i]);

i:=i+1

END;

i:=n;

WHILE i>=1 DO BEGIN

WRITELN(X[i]);

i:=i-1

END;

i:=1;

REPEAT

READLN(X[i]);

i:=i+1

UNTIL i>n;

i:=n;

REPEAT

WRITELN(X[i]);

i:=i-1

UNTIL i<1;

Цикл с параметром:

For i:=1 to n do readln(X[i]);

For i:=n downto 1 do writeln(X[i]);

For i:=1 to n do writeln(X[n-i+1]);

Лекция 4

4.0 Требования к защите бальных задач

  1.  Защищается алгоритм, а не текст программы на Паскале. Если Вы не в состоянии вразумительно объяснить ход решения, рисуйте схему алгоритма.
  2.  Текст на ТР должен соответствовать алгоритму.
  3.  После заголовка - комментарий, в котором ФИО, номер задачи и стоимость в баллах.
  4.  Перед каждым вводом должна быть подсказка о том, что вводить и с какими ограничениями.
  5.  Зацикливание программы, если это имеет смысл.
  6.  Задержка пользовательского экрана, если это необходимо.

Вот шаблон для оформления текста программы:

program <имя_программы>;

{Фамилия И.О., ПМ-1Х, задача I.15.3 сложность 3 балла}

…<Секция описаний>

var c:char;

begin <Начало секции действий>

 repeat

 writeln(‘Введите значение n, 0<n<=100’);

 readln(n);

 writeln(‘Конец работы?  - yes, no’);

 readln(c);

until c=’y’;

end.

4.1 Начало систематического изложения Turbo Pascal (TP)

  •  Алгоритмический язык TP ориентирован на работу в среде MS-DOS.

Базовый язык Pascal разработан Н.Виртом (1968) как язык обучения программированию. Все реализации языка унаследовали принципы, позволяющие разрабатывать читабельные, структурные, надежные и эффективные программы.

  •  В основе этих принципов заложена концепция типа данных,  которую можно сформулировать следующим образом:
  1.  каждая переменная, константа, выражение и функция относятся к определенному типу данных;
  2.  тип данных задается явно;
  3.  над данными каждого типа допустимы определенные операции.
  •  Язык Pascal называют языком со строгой типизацией данных. Строгая типизация данных требует некоторых дополнительных затрат от разработчика программы на этапе проектирования и реализации на алгоритмическом языке, однако эти затраты окупаются на стадии отладки и модификации программы, поскольку у компилятора имеется возможность более  детального синтаксического анализа исходного текста во время компиляции и создания машинного кода, способного более строго контролировать корректность операций на шаге выполнения.
  •  Каждая реализация языка ТP является расширением базового (стандартного) языка Pascal. Для того чтобы создавать мобильные программы, необходимо в данной конкретной реализации отличать средства, относящиеся к стандарту, и возможности, относящиеся к расширению стандарта.
  •  Программа - цепочка символов, слова, разделители, пробелы.
  •  Программа - последовательность предложений (вложенность)
  •  Структура программы: [Заголовок], секция описаний, секция действий.
  •  Алфавит языка  TP содержит прописные и строчные буквы латинского алфавита (буквой считается символ подчеркивания "_"), цифры от 0 до 9, символы + - * / = > < ( ) [ ] { } . , ; : ' @ # ^ $ и пробел.
  •  К элементам языка относятся:

идентификаторы - имена  переменных, констант,  процедур, функций и т.д., зарезервированные (или ключевые) слова,

стандартные идентификаторы (предопределенные имена)

специальные символы - комбинации символов алфавита.

  •  Идентификатором в TP может быть любое слово, состоящее из букв и цифр, начинающееся с буквы. Компилятор не различает прописные и строчные буквы, кроме того, следует иметь в виду, что компилятор анализирует лишь первые 63 символа идентификатора.
  •  Все зарезервированные (ключевые) слова алгоритмического языка следует помнить, поскольку нельзя использовать в программе идентификаторы, совпадающие с ключевым словом. В списке ключевых слов значком "+" помечены слова, не используемые в стандарте языка Pascal:

and

Mod

shr+

asm

file

Nil

string+

array

for

Not

then

begin

object+

to

case

function

Of

type

const

goto

or

unit+

constructor+

if

packed

until

destructor+

implementation+

procedure

uses+

div

in

program

var

do

inline+

record

downto

interface+

repeat

while

else

set

with

end

label

shl+

xor+

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

+ - * /  - арифметические операции;

+ - *    - операции над множествами;

=  <  >  <=  >=  <>   - отношения;

:= - присваивание;

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

,  - разделитель элементов списка;

:  - используется при описаниях;

;  - разделитель операторов языка;

.. - диапазон;

[ ] или (. .)  - селектор элемента массива;

{ } или (* *)  - скобки для выделения комментариев;

+  - операция конкатенации строк

#  - обозначение символа по его коду;

@  - обозначение адреса переменной;

$ - обозначение директивы компилятора или шестнадцатеричной константы;

^ - обозначение указателя.

  •  Комментарии { } (* *)
  •  Классификация типов данных:

  •  О совместимости типов данных.

TP - язык со строгой типизацией данных. Это означает, что во время выполнения программы производится проверка справедливости  (допустимости) выполняемых операций. Строгая типизация налагает определенные ограничения, которые объединены понятием совместимости типов данных.  В основном программист должен сам предвидеть и обеспечивать явное  преобразование типов  данных там, где это необходимо. В TP явное преобразование типа данных осуществляется по схеме NewType(value), где значение value будет преобразовано к  новому  типу  данных NewType.

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

  •  В TP выделены три вида совместимости типов данных, и каждый вид предоставляет определенные возможности по совместному использованию данных. Два типа данных могут характеризоваться как одинаковые, совместимые по операциям (или просто совместимые) и совместимые по присваиванию.
  •  Две переменные относятся к одинаковым (эквивалентным) типам, если описания переменных:
  1.  ссылаются на одно и то же имя типа;
  2.  ссылаются на различные имена типов (пусть Т1 и Т2), которые в разделе описания типов объявлены идентичными (TYPE T1=T2);
  •  Бинарные операции могут быть выполнены над операндами, относящимися к совместимым (по операциям) типам  данных. Два типа совместимы (по операциям), если:
  1.  типы одинаковы (эквивалентны);
  2.  оба типа целые или оба типа вещественные;
  3.  один  тип есть диапазон другого, или оба есть диапазоны от третьего;
  4.  оба типа - строка (STRING);
  5.  один тип - строка, а другой - ARRAY[1..n] of  CHAR, или просто CHAR;
  6.  оба  типа - множества с совместимыми по операциям базовыми типами;
  7.  один тип - ссылочный, другой бестиповый указатель;
  8.  оба типа - процедурные типы с одинаковым числом параметров, типы которых  соответственно эквивалентны. Для функциональных типов необходима еще и эквивалентность типов результатов.
  9.  Считается, что каждый объект типа "множество" совместим с пустым множеством и каждый объект типа "указатель" совместим с константой NIL.
  •  Величина может быть присвоена переменной, если их типы совместимы по присваиванию. Выражение f типа F называется совместимым по присваиванию с переменной w типа W, если :
  1.  F и W - эквивалентные, не файловые типы (и не содержат файловые типы в качестве полей);
  2.  оба типа - совместимые ординарные типы и значения выражения f  попадают в диапазон допустимых значений типа W;
  3.  оба вещественные типы и значение выражения f допустимо  для типа W;
  4.  W - вещественный тип ,  F - целый;
  5.  W - строка,  F - либо строка, либо символ, либо массив символов;
  6.  W и F - совместимые множественные типы,  причем множество f целиком входит во множество W;
  7.  W и F - совместимые ссылочные типы или  совместимые  процедурные типы;
  8.  W - процедурный тип, а f - имя процедуры или функции (параметры и типы должны быть согласованны);
  9.  W и F - объектные типы,  причем тип F потомок типа W,  либо оба типа ссылочные на совместимые объектные типы.

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

Лекция 5

5.1 Простые типы данных

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

=, <>, >, >=, <=, <.

Отношение между элементами простого типа является булевской величиной (относится к типу BOOLEAN).

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

Для ординальных типов данных в языке TP определены операции, которые реализованы в функциях и процедурах:

PRED (predecessor -предшествующий),

SUCC (succeedent – последующий),

ORD (ordinal – порядковое числительное),

Dec (decrease – уменьшать),

Inc (increase – увеличивать),

SIZEOF (size of … - размер чего-либо)

Функции PRED и SUCC получают в качестве аргумента значение ординального типа и возвращают предыдущий или последующий элементы этого типа. Считается ошибкой применение функции PRED к первому элементу, а функции SUCC к последнему элементу множества значений данного ординального типа. Функция ORD возвращает порядковый номеp элемента данного ординального типа, пеpвый элемент имеет номер 0, втоpой - 1 и т.д. Исключение представляют данные целого типа, поскольку ORD с целочисленным аргументом возвращает сам аргумент. Функцию ORD можно считать функцией пpеобpазования типа, поскольку для любого ординального аргумента результат будет целочисленный.

Процедуры Dec (или Inc) позволяют увеличить (или уменьшить) аргумент на заданную величину. Например функция Dec(x,n) (или Inc (x,n)) увеличивает (или уменьшает) значение ординальной переменной x на n значений. Если параметр n опущен, то увеличение (уменьшение) происходит на 1.

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

5.1.1 Перечислимый тип

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

type week_day=(Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday);

На множестве значений перечислимого типа определен естественный порядок Monday<Tuesday<Wednesday<…<Sunday. Если х и у – переменные var x,y:week_day; то можно переменным х и у присвоить значения, например: х:=Wednesday; y:=SUCC(x); применение функции ORD(Monday) – дает значение 0 целого типа, ORD(x) – 2 , ORD(y) – 3 ;

5.1.2 Интервальный тип

Интервальный ординальный тип (или тип – диапазон) является подмножеством последовательных величин ранее определенного (или предопределенного) перечислимого или стандартного ординального типа (базового типа).

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

TYPE work_day=Monday..Friday;

На интервальном типе данных определены те же операции, что и на базовом. Однако  программист должен гарантировать корректность операций на шаге выполнения. Если var D:work_day, то на шаге выполнения программы фрагмент D:=Friday; D:=SUCC(D) приведет к ошибке, поскольку для интервального типа work_day значение Friday является последним и не имеет последующего.

program datas;

type

  week_day=(Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday);

  dat=1..31;

  month=(January,Fabruary,March,April,May,June,July,

         August,September,October,November,December);

  year=1900..2100;

  attr_of_day=record

                 w_d:week_day;

                 d:dat;

                 m:month;

                 y:year

               end;

var

  today:attr_of_day;

  kol:integer;

function pred_week_day(w:week_day):week_day;

begin

  if w=Monday then pred_week_day:=Sunday else pred_week_day:=pred(w)

end;

function pred_month(m:month):month;

begin

  if m=January then pred_month:=December else pred_month:=pred(m)

end;

procedure pred_dat(var t:attr_of_day);

begin

  if t.d=1 then

  begin

     t.m:=pred_month(t.m);

     if t.m=December then t.y:=t.y-1;

     case t.m of

        January,March,May,July,August,October,December:t.d:=31;

        Fabruary:if (t.y mod 4)=0 then t.d:=29 else t.d:=28;

        April,June,September,November:t.d:=30

     end

  end else t.d:=t.d-1;

  t.w_d:=pred_week_day(today.w_d);

end;

begin

  today.w_d:=Monday;

  today.d:=2;

  today.m:=October;

  today.y:=2006;

  repeat

     pred_dat(today);

     if (today.y<=2000) and (today.w_d=Monday) and (today.d=13)

     then kol:=kol+1;

  until (today.y=1901) and (today.m=January) and (today.d=1);

  writeln('Kol= ',kol:4)

end.

5.1.3 Целочисленные типы

К целочисленным типам в TP относятся следующие предопределенные типы:

Тип

Диапазон

Размер (байт)

Shortint

-128..127

1 (со знаком)

Integer

-32768..32767

2 (со знаком)

Longint

-2147483648..2147483647

4 (со знаком)

Byte

0..255

1 (без знака)

Word

0..65535

2 (без знака)

Для целочисленных типов применимы все функции, допустимые для ординальных типов – PRED, SUCC, DEC, INC. Определены унарные операции + и - ( сохранить знак числа,  изменить знак числа),  арифметические бинарные операции сложения (+), вычитания (-),  умножения (*),  деления нацело (div), взятия остатка при целочисленном делении (mod), деление (/), в результате последней операции получается вещественная величина. Кроме общих функций для ординальных типов данных, для целочисленных типов данных определены следующие:

CHR(X) – возвращает символ (значение типа CHAR), код которого есть целое положительное число X (0 <= X <= 255).

Логическая функция ODD(X) возвращает TRUE, если X – нечетно, в противном случае – FALSE.

ABS(X)  - абсолютная величина X.

SQR(X) - квадрат величины X.

В TP для данных типа INTEGER (и совместимых с INTEGER) определены побитовые операции:

  •  n1 shl n2 - левый логический сдвиг двоичного кода числа n1 на n2 позиций. Слева двоичные разряды пропадают, справа добавляются нули.
  •  n1 shr n2 - правый логический сдвиг.
  •  not n – дополнение к двоичному коду целого числа n (цифра 0 заменяется на 1, 1 на 0).
  •  n1 or n2 – логическое "или".
  •  n1 and n2 – логическое "и".
  •  n1 xor n2 – логическое исключающее "или".

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

Значение X

Операция

Результат

Дес

Шестн

дес

шестн

5

$00000005

not X

2147483643

$FFFFFFFA

5

$00000005

X shl 1

10

$0000000A

5

$00000005

X shr 1

2

$00000002

Значение X

Значение Y

Операция

Результат

Дес

Шестн

Дес

шестн.

дес.

шестн.

5

$00000005

15

$0000000F

X or Y

15

$0000000F

5

$00000005

15

$0000000F

X and Y

5

$00000005

5

$00000005

15

$0000000F

X xor Y

10

$0000000A

5.1.4 Данные типа CHAR

Данные типа CHAR занимают один байт памяти. Константными значениями служат символы кодировки ASCII (Американский стандартный код обмена информации), содержащие, кроме латинских и русских (больших и малых) букв, цифр и  используемых в TP специальных символов, различного рода служебные символы. Каждому символу соответствует некоторый код (целое число в диапазоне от 0 до 255), но не каждый символ имеет графическое представление (например, символы табуляции, символ возврата каретки и др.). Над данными типа CHAR можно производить операции, определенные для данных ординального типа. Функция ORD возвращает код аргумента. Если  символ имеет графическое представление, например буква А, указать такой символ можно, заключив его изображение в апострофы – 'А'. Следующий оператор

FOR C := 'A' TO 'Z' DO 

WRITELN('код символа', C, ' - ', ORD(C):3);

позволяет получить коды всех символов таблицы ASCII в диапазоне от A до Z.

Переменная C должна быть описана как CHAR.

При использовании значений типа CHAR, не имеющих графического представления, можно применить форму записи символов по их коду с помощью префикса #, например #65 – то же самое, что 'A' (65 – код символа A).

5.1.5 Тип BOOLEAN

Ординальный предопределенный тип BOOLEAN можно рассматривать как перечислимый тип с описанием

TYPE BOOLEAN = (FALSE,TRUE);

Переменные этого типа занимают один байт памяти. Операции AND, OR, XOR, NOT для операндов булевского типа понимаются компилятором как булевские операции умножения ("и"), сложения ("или"), "исключающего или" и "отрицания". Пусть A и B – выражения булевского типа, тогда булевские операции определяются следующим образом:

A

B

not A

A and B

A OR B

A xor B

T

T

F

T

T

F

T

F

F

F

T

T

F

T

T

F

T

T

F

F

T

F

F

F

AND Логическое И

OR Логическое ИЛИ

XOR Логическое исключающее ИЛИ

NOT Логическое НЕ

Функция ORD дает значение 0, если аргумент имеет значение FALSE, и 1, если TRUE.

5.1.6 Вещественные типы данных

Простые типы вещественных данных не являются ординальными. С помощью этих типов данных в языке задается некоторое конечное подмножество рациональных чисел. Константы вещественного типа записываются в виде цепочки цифр с точкой, например: 0.0, 3.14, 17.4 (вещественная константа должна начинаться и заканчиваться цифрой). Константа может быть представлена в экспоненциальной форме, например, 1.0E+5, 0.01E-0, 3.14E.

Кроме того, TP позволяет работать со следующими вещественными типами (табл.).

Тип

Диапазон

Цифры

Байты

real

2.9e-39..1.7e38

11-12

6

Single*

1.5e-45..3.4e38

7-8

4

Double*

5.0e-324..1.7e308

15-16

8

Extended*

3.4e-4932..1.1e4932

19-20

10

comp

-9.2e18..9.2e18

19-20

8

*Это форматы чисел, с которыми работает математический сопроцессор.

Над данными вещественного типа в языке TP определены следующие операции и функции:

  1.  унарная операция + возвращает величину операнда;
  2.  унарная операция – меняет знак операнда;
  3.  бинарные операции +, - ,*, / возвращают результат выполнения соответствующих операций над вещественными числами;
  4.  отношения <, >, <=, >=, =, <> возвращают булевскую величину как результат сравнения операндов.

  1.  функция TRUNC(X) возвращает целую часть X;
  2.  функция ROUND(X) - округленное значение  X до целого;
  3.  функция INT(X) - возвращает целую часть аргумента;
  4.  функция FRAC(X) - возвращает дробную часть аргумента;
  5.  функция PI - возвращает число 3.141592653897932385;
  6.  функция ABS(X) - абсолютную величину X;
  7.  функции SIN(X), COS(X), ARCTAN(X), LN(X), EXP(X), SQRT(X) и SQR(X) - возвращают значения синуса, косинуса, арктангенса, натурального логарифма,  экспоненты,  корня квадратного и квадрата аргумента X соответственно.

Лекция 6

6.1 Структура программы на Паскале

Программа на Паскале представляет собой обычный текст. Транслятор воспринимает этот текст как последовательность символов. На этапе лексического анализа текста выделяются слова (разделитель – пробел). Из слов составлены предложения (или операторы), разделителем служит символ «;» – «точка с запятой».

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

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

Раздел описания имен модулей (в стандарте Паскаля этот раздел отсутствует). Раздел начинается заголовком uses, далее списком через запятую указываются имена используемых в программе модулей.

Раздел описания меток. После заголовка раздела label записывается список используемых в программе меток.

Раздел описания типов данных. После заголовка раздела type следуют операторы описания типов данных, созданных в программе пользователем. Операторы описания типа имеют следующий формат: <имя типа>=<описатель типа>. Имя типа – идентификатор, описатель типа – конструкция, определяющая данный тип.

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

<список имен переменных через запятую>:<имя или описатель типа>

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

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

Текст программы на Паскале завершает секция действий, представляющая собой составной оператор, – последовательность операторов, заключенная в логические скобки begin end. В секции действий описана последовательность действий, то есть алгоритм решения задачи.

6.2 Процедуры для стандартного ввода/вывода

Для осуществления ввода и вывода данных стандартного типа используются предопределенные процедуры ввода и вывода READ, READLN, WRITE, WRITELN. Эти процедуры, кроме стандартных типов (целочисленные, вещественные, булевский, символьный), могут обслуживать диапазонные типы со стандартным базовым типом и данные типа string (строка). В качестве аргумента эти процедуры получают список элементов ввода или вывода. Список формируется как строка, в которой указываются через запятую имена элементов ввода или вывода, возможно со спецификацией (характеристикой). Спецификации служат для уточнения формата представления данных. Если спецификация не указана, используется формат, принятый по умолчанию для данного типа данных.

Элемент ввода или вывода может принимать одну из следующих форм:

E,{нет спецификации}

E:LEN,{указана характеристика длины}

E:LEN:ACCUR {указана характеристика длины и точности}

Здесь Е – выражение одного из перечисленных выше типов, обслуживаемых процедурами ввода и вывода, LEN и ACCUR – выражения типа INTEGER. Характеристика точности (ACCUR) может применяться только для вывода данных вещественного типа. Использование характеристик при выдаче данных в текстовый файл (или на экран монитора) показано на примерах:

VAR I:INTEGER; C:CHAR; PI:REAL; B:BOOLEAN; A,S:STRING;

I:=1234;

C:='a';

PI:=3.14159;

B:=TRUE;

S:='ABCD';

A:='ABCD';

Обращение к процедуре       результат

WRITE(I:6);                 ..1234

WRITE(I:1);                 1234

WRITE(I);                   .......1234

WRITE(C:6);                 .....a

WRITE(PI:10);               .3.142E+00

WRITE(PI);                  .3.1415926536E+00

WRITE(PI:10:4);             ....3.1416

WRITE(B:10);                ......TRUE

WRITE(B:2);                 .T

WRITE(S:6);                 ..ABCD

WRITE(S:2);                 AB

WRITE(S);                   ABCD

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

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

6.3 Массивы. Регулярный тип

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

Описатель массива ARRAY[<индексный тип>] OF <базовый тип>

<индексный тип> – имя  или описатель индексного типа,

<базовый тип> – имя или описатель базового типа.

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

Вот примеры описателей массивов:

ARRAY[1..10] OF REAL – массивы этого типа будут состоять из 10 элементов действительного типа, индексы – целые числа от 1 до 10.

ARRAY[CHAR] OF INTEGER – массивы этого типа будут состоять из 256 целочисленных элементов, индексы – символы кодовой таблицы от #0 до #255.

ARRAY[’A’..’Z’] OF INTEGER – массивы этого типа будут состоять из 26 целочисленных элементов, индексы – заглавные буквы латинского алфавита.

В качестве описателя базового типа может быть использован описатель массива. Вот пример описаний:

TYPE 

I1=<индексный тип 1>;

I2=<индексный тип 2>;

  

Ik=<индексный тип k>;

BAZ=<базовый тип>;

MASS=ARRAY[I1] OF ARRAY[I2] OF BAZ

В Паскале предусмотрена более компактная запись последнего оператора:

MASS=ARRAY[I1,I2] OF BAZ

Переменная типа MASS будет представлять собой двумерный массив (массив массивов). В описании VAR M:ARRAY[I1,I2, …, Ik] OF BAZ массив М объявлен как многомерный (k – мерный) массив. Количество индексных типов в описании массива – размерность массива.

Доступ к элементам массива осуществляется с помощью селектора [  ] – квадратные скобки. В квадратных скобках указывают значение (выражение) индексного типа. Если переменные x1,x2, …, xk описаны так: var x1:I1; x2:I2; …; xk:Ik, то

Mмассив ARRAY[I1,I2, …, Ik] OF BAZ,

M[x1]массив ARRAY[I2, …, Ik] OF BAZ,

M[x1][x2]массив ARRAY[ …, Ik] OF BAZ,

M[x1][x2] … [xk] – данное базового типа BAZ,

Допустимы сокращенные формы записи: M[x1,x2],…, M[x1,x2, …, xk], соответственно.

Приведем примеры описаний и использования массивов

TYPE M10=ARRAY[1..10] OF REAL;

IND=-5..5;

MIND=ARRAY[IND] OF REAL; {тип - массив из 11 элементов}

MINDM10=ARRAY[IND] OF M10; {тип - двумерный массив}

week_day=(Monday,Tuesday,Wednesday,Thursday,

         Friday,Saturday,Sunday);

dat=1..31;

month=(January,Fabruary,March,April,May,June,July,

         August,September,October,November,December);

VAR  X:M10;{массив}

K:IND;{переменная}

Y:ARRAY[1..10] OF REAL;

V:MIND;

MM:MINDM10;{двумерный массив}

Mdat:ARRAY[month] OF dat;

Mweek_day:ARRAY[month, dat] OF week_day;

В этих  условиях доступ к элементам иллюстрируется операторами:

K:=0;

V[K]:=17.0;

X[1]:= 22.5;

Y[5]:=X[1];

MM[-3, 1]:= 0;{то же самое, что MM[-3][1]:= 0;}

Mdat[January]:=31;

Mweek_day[October, 9]:= Monday;

В TP можно выполнить такое присваивание MM[0]:=X, если все компоненты массива V инициализированы (одинаковые типы данных). Нельзя выполнить присваивание X:=Y, поскольку переменные относятся к несовместимым по присваиванию типам данных.

6.4 Для работы с массивами – шаблоны

Шаблон 1. Ввод-вывод одномерного массива.

program …;

const NN=100;{Максимальное число элементов}

type MM=array [1..NN]of real; {Новый тип данных - массив}

var M:MM; k,i:integer;

begin

{Ввод массива}

  writeln(‘Введите кол-во элементов (не более ',NN:1,’)’);

  readln(k);

  writeln(‘Введите ’,k:1,’ элементов массива‘);

  for i:=1 to k do read(M[i]); readln;

{Вывод массива на экран}

  writeln(‘Вот результат:’); {Заголовок вывода}

  for i:=1 to k do write(‘M[‘,i:2,’]=’,M[i]:7:3); writeln;

end.

Шаблон 2. Ввод-вывод двумерного массива.

program …;

const NN=100; MM=100;{Максимальное число строк и столбцов}

type AA=array [1..NN,1..MM]of real;{Новый тип данных – двумерный массив}

var A:AA; n,m,i.j:integer;

begin

{Ввод двумерного массива}

  writeln(‘Введите кол-во строк (не более ’,NN:1,

          ’) и столбцов (не более ’,MM:1,’)');

  readln(n,m);

  for i:=1 to n do

  begin

     writeln(‘Введите ’,i:1,’-ю троку‘);

     for j:=1 to m do read(M[i,j]);

     readln

  end;

{Вывод двумерного массива на экран}

  writeln(‘Вот результат:’);{Заголовок вывода}

  for i:=1 to n do

  begin

     for j:=1 to m do write(M[i,j]);

     writeln

  end;

end.

Лекция 7

7.1 Строки

Строковый тип данных (STRING) предназначен для обработки цепочек символов (литер, элементов типа CHAR). Переменные типа STRING могут быть объявлены следующим образом:

<имя переменной>:STRING[длина]

или

<имя переменной>:STRING

В стандарте Паскаля такого типа данных нет.

Параметр длина задает максимальную длину строки (максимальное число символов цепочки). Если максимальный размер строки не указан, то он автоматически принимается равным 255 – максимально возможной длине строки. Для переменной типа string резервируется участок памяти длиной длина+1 байт. Дополнительный байт используется для хранения значения текущей длины строки.

В языке Паскаль широко используются константы строкового типа. Они представляют собой цепочки произвольных символов используемой кодовой таблицы, заключенные в апострофы. Например: ‘ВОТ’ – цепочка из трех символов, ‘’ – пустая цепочка.

Строка обладает всеми свойствами массива литер, то есть, структуры данных, описанной описателем array[0..длина] of char. Если имеются описания s,s1:string[10], то, в отличие от массива, допустимы присваивания

s:=’BOT’

s1:=’’.

При этом текущая длина строки s будет равна 3, текущая строка s1 – 0. Текущая длина строки – целое положительное число в диапазоне от 0 до длина – хранится в нулевом элементе строки как данное типа char (s[0]=chr(3), s1[0]=chr(0)). В первом элементе строки s – s[1] – хранится символ ‘B’, во втором – ‘O’, в третьем – ‘T’, значение элемента s[4] неопределенно, обращение к нему является ошибкой, поскольку индекс превышает текущее значение длины строки.

Текущая длина строки не должна превышать максимальную длину.

К строкам применимы стандартные процедуры ввода и вывода. Если выдать на экран значения строк s и s1, то получим:

writeln(s) – на экране строка ‘ВОТ’,

writeln(s1) – на экране пустая строка.

Над строковыми данными определена бинарная операция конкатенации (+). Результатом конкатенации двух строк является строка, содержащая последовательно все символы левого операнда, а затем все символы правого операнда. Вот примеры использования конкатенации:

writeln(s) – на экране текст ВОТВОТ;

s1:=s+’ KOT’; writeln(s1) – на экране ВОТ КОТ.

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

program Enter_int;

type status=(beginning,znak,Ok,Err);

var s:string; zn,k,i:integer; c:char;

  n:longint;

  stat:status;

  cifra:boolean;

begin

repeat

  writeln(‘Введите целое по модулю меньшее ’,$7FFF:1);

  readln(s);

  k:=length(s);

  zn:=1;

  n:=0;

  stat:=beginning;

  for i:=1 to k do

  begin

     c:=s[i];

     cifra:=(c>='0') and (c<='9');

     case stat of

        beginning: case c of

                       ' ': ;

                       '+': stat:=znak;

                       '-': begin stat:=znak; zn:=-1 end;

                       '0'..'9': begin n:=n*10+ord(c)-ord('0');

                                 stat:=Ok end;

                       else stat:=Err

                   end;

        znak:      if cifra then

                   begin

                      n:=n*10+ord(c)-ord('0'); stat:=Ok

                   end else stat:=Err;

        Ok:        if cifra then

                   begin

                      n:=n*10+ord(c)-ord('0'); stat:=Ok

                   end else stat:=Err;

     end;

  end;

  n:=zn*n;

  if abs(n)>=$7FFF then stat:=Err;

until stat=Ok;

writeln('rezult ',n)

end.

Переменную типа STRING можно сравнивать с другой переменной или константой типа STRING, используя отношения =, <, >, <=, >=, <>. Используется лексикографический порядок (как в каталогах библиотек).

В TP имеются следующие функции для обработки строк:

  •  CONCAT - функция имеет произвольное число параметров строкового типа,  результат - строка,  полученная последовательной склейкой параметров.  Если длина полученной  строки  превышает 255 символов, то происходит усечение;
  •  COPY(S:string; ind,count:integer):string - возвращает подстроку S длиной count, начиная с литеры номер ind. При несоответствии с максимальной длиной используется усечение;
  •  DELETE(var S:string; ind,count:integer) - удаляет из S count символов, начиная с ind;
  •  INSERT(St:string; var S:string; ind:integer) - вставляет в S St, начиная с позиции ind;
  •  LENGTH(S:string) - функция, возвращает текущую длину строки S;

Две процедуры  можно рассматривать как процедуры преобразования типа:

  •  VAL(S:string; var V; var code:integer) - где V - переменная целого или вещественного типа. Процедура выделяет из строки последовательность символов,  преобразует к типу соответствующей переменной и присваивает полученное значение этой переменной. Процедура VAL является строковым аналогом процедуры READ. Если при чтении из строки встречается недопустимый символ, то в переменной code возвращается его номер. В противном случае этот параметр равен нулю;
  •  STR(X; var S:string) - преобразует численное  значение целого или  вещественного  типа в его строковое представление. Эта процедура является  строковым  аналогом  процедуры WRITE. После выражения X можно указать длину и точность представления данных.

Вот примеры использования процедур VAL и STR.

var X:real; S:string; i:integer;

begin

X:=3.1415926;

STR(X:8:4, S); S:='X=' + S;

Writeln(S); { на экране 'X=  3.1416'}

S:=DELETE(S,1,2); {удалили первые два символа}

VAL(S,X,i);

if i=0 then writeln(X:10:6) {на экране '  3.141600'}

end.

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

7.2 Записи

Запись - структура данных, содержащая конечное число компонент различного типа. Компоненты называются полями. Как любой тип, определяемый программистом, тип "запись" должен быть объявлен в разделе TYPE. При описание типа запись указывает тип каждого поля и идентификатор, который именует поле. Тип данных RECORD предоставляет возможность объединить в одну связанную структуру различные по типу и смыслу поля, причем элементами записи могут быть и структурированные типы данных, например массивы и другие (подчиненные) записи. Для обработки доступна как вся запись целиком, так и отдельные поля.

Описатель записей:

RECORD <фиксированная часть> <вариантная часть> END

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

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

TYPE

REC = RECORD

A, B : INTEGER;

C    : CHAR

END;

DATE = RECORD

DAY : 1..31;

MONTH : 1..12;

YEAR: 1900..2100

END;

Если VAR X:REC; Y, Z:DATE; то к полям записей X, Y и Z имеется доступ по имени поля. Например, X.A - поле A записи X, элемент типа INTEGER.

Инициализация записи - инициализация всех полей записи Y.DAY := 17; Y.MONTH := 3; Y.YEAR := 1992;

Если запись Y инициализирована, то можно ее использовать в правой части оператора присваивания   Z := Y ; Z и Y совместимы по присваиванию, поскольку относятся к одному и тому же типу данных.

Посмотрите, как используется запись в программе Datas лекции 5.

Вариантная часть всегда следует  за  фиксированной,  если она есть.

CASE <тег:>  тип of <список описаний вариантов>

Описание варианта -  это  константное  значение  или  диапазон константных значений,  относящихся к типу «тип» описания вариантной части. Далее ставится двоеточие, и в скобках - описание полей варианта.  Описание полей варианта осуществляется по тем же правилам, что и полей фиксированной части. Имена всех полей должны быть уникальными идентификаторами внутри записи.

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

TYPE  SHAPE = (TRIANGLE, RECTANGLE, SQUARE, CIRCLE);

COORDINATES = RECORD { фиксированная часть }

X, Y, AREA : REAL;

CASE S : SHAPE OF { вариантная часть }

TRIANGLE : (SIDE : REAL; BASE : REAL);

RECTANGLE: (SIDEA, SIDEB : REAL);

SQUARE   : (EDGE : REAL);

CIRCLE   : (RADIUS : REAL)

END;

В памяти поля разместятся как показано на рисунке

фиксированная часть

вариантная часть

X

Y

AREA

S

SIDE

BASE

X

Y

AREA

S

SIDEA

SIDEB

X

Y

AREA

S

EDGE

-

X

Y

AREA

S

RADIUS

-

Если S = RECTANGLE,  то доступны поля SIDEA и SIDEB. Например, при инициализации записи:

X : COORDINATES;

X.S := RECTANGLE;

X.SIDEA := 17.5;

X.SIDEB := 20.4;

В стандартном языке Pascal (и в TP) можно вообще не  указывать поле тега:

COORDINATES RECORD

X, Y : REAL;   { фиксированная часть }

AREA : REAL;

CASE SHAPE OF  { вариантная часть }

END

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

Проанализируйте самостоятельно следующий пример:

program record_;

type

  T_education=(begining,medium,higher);

  T_profession=(teacher,driver,woker);

  T_category=(A,B,C,D);

  T_anketa=

     record

        name   :string[20];

     case profession:T_profession of

        teacher:(education:T_education;

                 pedagogical_length_of_service:byte);

        driver :(licence:record

                 case drivers_licence:boolean of

                    true :(category:T_category;

                           drivers_length_of_servie:byte);

                    false:(drivers_school:string[20])

                 end);

        woker  :(specialization:string[20];

                 class:string[20])

     end;

var a1,a2,a3:T_anketa;

begin

  writeln(sizeof(T_profession)); {1}

  writeln(sizeof(T_anketa)); {64}

  a1.name:='Ivan';

  a1.profession:=teacher;

  a1.education:=higher;

  a1.pedagogical_length_of_service:=1;

  a2.name:='Vlad';

  a2.profession:=driver;

  a2.licence.drivers_licence:=true;

  a2.licence.category:=B;

  a3.name:='Mike';

  a3.profession:=woker;

  a3.specialization:='shoe-maker';

  a3.class:='master';

end.

Оператор присоединения WITH позволяет  один раз указать имя записи и обращаться непосредственно к полям записи. Синтаксис оператора WITH:

WITH <список переменных> DO <оператор>,

где в списке «список переменных»  указываются  имена  записей.

Например, если Y запись типа DATE (см. пример выше), то значения полям этой записи можно присвоить так:

WITH Y DO BEGIN

DAY :=17; MONTH := 3; YER := 1992

END;

Оператор  WITH V1, V2,...,Vn DO S;

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

WITH V1 DO WITH V2 DO ... WITH Vn DO S;

Вот как массив строк может помочь распечатать (выдать на экран) данное перечислимого типа (день недели 1 января 1901 года):

program datas;

type

  week_day=(Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday);

  dat=1..31;

  month=(January,Fabruary,March,April,May,June,July,

         August,September,October,November,December);

  year=1900..2100;

  attr_of_day=record

                 w_d:week_day;

                 d:dat;

                 m:month;

                 y:year

               end;

var

  today:attr_of_day;

  kol:integer;

  prn_week_day:array[week_day] of string[9]

function pred_week_day(w:week_day):week_day;

begin

  if w=Monday then pred_week_day:=Sunday else pred_week_day:=pred(w)

end;

function pred_month(m:month):month;

begin

  if m=January then pred_month:=December else pred_month:=pred(m)

end;

procedure pred_dat(var t:attr_of_day);

begin

  if t.d=1 then

  begin

     t.m:=pred_month(t.m);

     if t.m=December then t.y:=t.y-1;

     case t.m of

        January,March,May,July,August,October,December:t.d:=31;

        Fabruary:if (t.y mod 4)=0 then t.d:=29 else t.d:=28;

        April,June,September,November:t.d:=30

     end

  end else t.d:=t.d-1;

  t.w_d:=pred_week_day(today.w_d);

end;

begin

  prn_week_day[Monday]:=’Monday’

  prn_week_day[Tuesday]:=‘Tuesday’

  prn_week_day[Wednesday]:=‘Wednesday’

  prn_week_day[Thursday]:=‘Thursday’

  prn_week_day[Friday]:=‘Friday’

  prn_week_day[Saturday]:=‘Saturday’

  prn_week_day[Sunday]:=‘Sunday’

  today.w_d:=Monday;

  today.d:=2;

  today.m:=October;

  today.y:=2006;

  repeat

     pred_dat(today);

     if (today.y<=2000) and (today.w_d=Monday) and (today.d=13)

     then kol:=kol+1;

  until (today.y=1901) and (today.m=January) and (today.d=1);

  writeln('Kol= ',kol:4);

  writeln(prn_week_day[today.w_d])

end.

Лекция 8

8.1 Множества

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

SET OF базовый тип

Базовым типом может являться любой ординальный тип, содержащий не более 256 элементов. Например: VAR set1,set2,even,anyset: SET OF 0..100;

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

set1:=[1..20];

even:=[2,4,6,8,10,12,14,16,18,20];

set2:=[15..25];

anyset:=[3,3+2,11..15,17..4*5];

Над данными типа множество определены следующие операции:

  •  set1=set2 - сравнение (результат операции - FALSE);
  •  set1<>set2 - сравнение на несовпадение (TRUE);
  •  set2<=set1- входит ли set2 как подмножество в set1? (FALSE);
  •  set1>=even- содержит ли set1 как подмножество even? (TRUE);
  •  5 in set1 - является ли 5 элементом множества set1? (TRUE).
  •  set1+set2 - объединение множеств - множество [1..25],
  •  set1*set2 - пересечение множеств - множество [15..20],
  •  set1-even - разность множеств - множество нечетных чисел меньших 20.

Вместо оператора cifra:=(c>='0') and (c<='9') в программе Enter_int (см. лекцию 7) можно использовать более ясную и лаконичную конструкцию
cifra:=c in ['0'..'9'].

В TP множество реализуется как последовательность бит, с помощью которой устанавливается, принадлежит (1) или нет (0) элемент, номер которого совпадает с порядковым номером бита, данному множеству. Таким образом, для базового типа из K элементов каждое множество задается строкой из K бит.

8.2 Файлы

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

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

Пример описаний файлов, в котором определены размеры буферов файлов различного типа:

program files;

var f1:file of real; {В стандарте f1^ - переменная типа real - типизированный файл}

f2:file; {нетипизированный файл}

f3:text; {текстовой файл}

begin

writeln(sizeof(f1),sizeof(f2),sizeof(f3))

end.

Результат: 128 128 256

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

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

<имя>: file of <базовый тип>;

<имя> - файловая переменная. В стандарте файловая переменная является указателем на буфер файла. В ТР, как видно из примера, это не так.

<базовый тип> - любой, кроме файлового и записи, содержащей файловый тип.

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

assign (var f:text; <ИмяФайла>:string);

Имя файла задается согласно принятым в MS-DOS правилам. Оно может быть полным, т. е. состоять не только непосредственно из имени файла, но и включать путь к файлу. Существуют определенные договоренности при записи имени файла, например:

assign ( f, 'a:\result.txt');{Полное имя файла}

assign (f,'\students\ivanov\korni.txt'); {Указан путь относительно текущей директории}

Имя файла может быть задано строкой:

fname:='otchet.txt';

assign(f,fname);

8.3 Процедуры открытия и закрытия файлов:

RESET(F) - открытие существующего файла F на чтение (файловая переменная F связана с существующим файлом MS DOS процедурой ASSIGN). В стандартном Паскале при открытии файла на чтение в динамической памяти создается буфер файла, в который помещается первая запись файла. Для нетипизированных файлов размер записи может быть указан вторым параметром. В ТР буфером является сама файловая переменная, размер буфера в примере пункта 8.2. Если открываемый на чтение файл не существует в файловой системе, возникает ошибка этапа выполнения программы.

REWRITE(F) – создает  и открывает на запись новый файл. Если файловая  переменная F связана с существующим файлом, то данные этого файла уничтожаются. В стандартном Паскале при открытии файла на запись в динамической памяти создается буфер файла для промежуточного хранения записей. Для нетипизированных файлов размеры записей могут задаваться вторым параметром. В ТР буфером является сама файловая переменная, размер буфера в примере пункта 8.2.

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

8.4 Процедуры ввода/вывода:

WRITE(F, E) - запись значения выражения E базового типа в файл; (не применима к нетипизированным файлам)

READ(F, V) - чтение из файла записи в переменную; (не применима к нетипизированным файлам)

BLOCKREAD; BLOCKWRITE - только для нетипизированных файлов.

SEEK(F, n) - делает доступной для обработки запись n файла F (эта процедура не применима к текстовым файлам);

EOF(F) - функция,  возвращает TRUE,  если достигнут конец файла F.

При работе с файлами в TP очень полезна функция IORESULT, которая возвращает  значение  кода ошибки выполнения последней операции ввода/вывода. Следующий фрагмент является шаблоном для открытия файла на чтение. Он позволяет избежать прерывания программы при попытке открытия на чтение не существующего файла

repeat

writeln('введите имя файла'); readln(s);

assign(f,s);

{$I-}      {отключение режима прерывания выполнения программы при возникновении ошибки в/в}

reset(f);

{$I+}      {включение режима прерывания выполнения программы при возникновении ошибки в/в}

i:=IORESULT;

if i<>0 then begin

writeln('Ошибка',i:3);

writeln('Попробуйте еще');

end;

until i = 0;

Здесь i – переменная типа integer, s – строка. {$I-} – псевдокомментарий – директива компилятору при выполнении дальнейших действий снять контроль проверки правильности выполнения операции ввода/вывода. Если открытие файла F прошло успешно, то IORESULT возвращает значение 0, в противном случае IORESULT возвращает код ошибки, отличный от нуля.

Лекция 9

9.1 Текстовые файлы.

Текстовый файл (описатель text в отличие от типизированного файла file of char) представляет собой файл символов, сгруппированных в строки. Разбиение на строки обеспечивается признаком (комбинаций символов) конца строки. Для текстовых файлов существует  специальный вид операций чтения и записи (read, write, readln, writeln), который позволяют считывать и записывать значения, тип которых отличается от символьного типа (это действительные, целочисленные типы и строки, выводить можно также и данные булевского типа). Такие значения автоматически переводятся в символьное представление и обратно. Например, Read(f,i), где i - переменная целого типа, приведет к считыванию последовательности цифр, интерпретации этой последовательности как десятичного числа, и сохранению его в i. Предопределены две стандартные переменные типа text – это Input и Оutput. Стандартная файловая переменная Input – это доступный только для чтения файл, связанный со стандартным файлом ввода операционной системы (обычно это клавиатура), а стандартная файловая переменная Оutput – это доступный только для записи файл, связанный со стандартным файлом вывода операционной системы (обычно это дисплей). Перед началом выполнения программы файлы Input и Оutput автоматически открываются, как если бы были выполнены следующие операторы:

Assign(Input,'con'); Reset(Input);

Assign(Output,'con'); Rewrite(Output);

После завершения работы программы эти файлы автоматически закрываются.

Обращение к процедурам ввода и вывода для текстовых файлов организуется так:

Read(f,<список элементов ввода>), 

write(f,<список элементов вывода>),

readln(f,<список элементов ввода>),

writeln(f,<список элементов вывода>)

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

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

Переменная типа CHAR принимает значение текущего символа.  

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

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

Пример:

VAR I, J : INTEGER; S :STRING[100]; CH : CHAR;

...

READ(f, I, J, CH, S);

Пусть читаемые данные:  36 24 ABCDEFGHIJKLMNOPQRSTUVWXYZ.

После выполнения процедуры READ:

I =36, J = 24, CH = ' ', S = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.

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

program ReadEoln {Плохое решение};

var c:char; f:text;

begin

assign(f,'text.txt');

reset(f); {Нужно использовать шаблон безопасного открытия}

while not(eof(f)) do

begin

read(f,c);

write(c);

end;

close(f);

writeln;

readln;

end.

program Copy {хорошее решение, шаблон!};

var c:char; f:text;

begin

assign(f,'text.txt');

reset(f){Нужно использовать шаблон безопасного открытия};

while not(eof(f)) do

begin while not(eoln(f)) do

begin

read(f,c);

write(c);

end;

readln(f);

writeln;

end;

close(f);

writeln;

readln;

end.

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

Вот два примера работы с текстовыми файлами (предложены Путинцевым А).

{Добавление записей в файл данных о дневной температуре воздуха}

program aprec;

var

    DayTemp:record {дневная темперарура}

         day:integer;     {число}

         month:integer;   {месяц}

         temper:integer;  {температура}

    end;

    f:text;{ файл дневной температуры}

begin

    assign(f,'a:\temperat.txt');

    append(f); {открываем файл для добавления записи}

               {Нужно использовать шаблон безопасного открытия}

    write('Введите в одной строке, разделяя пробелами');

    writeln(' число, номер месяца и температуру');

    write('->');

    with DayTemp do

         begin

              readln(day,month,temper);

              writeln(f,day,' ',month,' ',temper);

              {Следовало бы указать характеристики длины}

         end;

    close(f);

    writeln('Данные добавлены');

end.

{Чтение записей из файла}

program readrec;

var

    DayTemp:record      {дневная температура}

         day:integer;       {число}

         month:integer;     {месяц}

         temper:integer;    {температура}

         end;

    f:text; {файл дневной температуры}

    mes:integer;{номер месяца}

    n:integer;{кол-во дней месяца, о которых есть данные в файле}

    summ:integer;    {сумма температур месяца}

    sredn:real;      {средняя температура}

begin

    n:=0;

    summ:=0;

    writeln('Вычисление среднемесячной температуры.');

    write('Месяц->');

    readln(mes);

    assign(f,'a:\temperat.txt');

    reset(f);{Нужно использовать шаблон безопасного открытия}

    while NOT EOF(f) do begin

         with DayTemp do readln(f,day,month,temper);

         {Область действия оператора with}

         if DayTemp.month=mes

              then begin

                   n:=n+1;

                   summ:=summ+DayTemp.temper;

              end;

    end;

    close(f);

    if n<>0 then begin
         sredn:=summ/n;

         writeln('Средняя температура:',sredn:6:3);

    end

    else writeln('Данных о температуре за',mes:3,' месяц нет.');

end.

9.2 Проект программы:

  •  Точная формулировка задачи
  •  Типы данных
  •  Структуры данных
  •  Процедуры и функции
  •  Алгоритм

9.3 Простейший сканер.

Формулировка задачи: Программа читает текстовый файл, выделяет слова и распознает идентификаторы. Имя текстового файла запрашивается. На экран выдается список слов по одному слову в строку, идентификаторы помечаются символом *. Разделителем не является признак конца строки.

Спецификации (типы данных и структуры данных):

Определяются три состояния чтения текста:

  •  ident – подозрение на идентификатор,
  •  news – начало чтения нового слова,
  •  ordin – читаемое слово не идентификатор.

Состояния объединены в перечислимый тип status.

chars – множество всех символов, letter, digit и separ - подмножества букв, цифр и разделителей слов, соответственно.

Процедуры и функции - нет.

Алгоритм: Чтение (из файла) посимвольно. Определяется изменение состояния в зависимости от состояния s и вновь прочитанного символа c. Начальное состояние - news.

Входной алфавит V – буква, цифра, разделитель, символ.

Алфавит состояний Q – News, Ident, Ordin.

Функция переходов f:QVQ:

буква

цифра

разделитель

символ

News

Ident

Ordin

News

Ordin

Ident

Ident

Ident

News

Ordin

Ordin

Ordin

Ordin

News

Ordin

Начальное состояниеNews

Множество заключительных состояний – {}

{Symplest scaner}

program Symplest_Scanner;

{Программа читает текстовый файл,

выделяет слова и распознает идентификаторы}

type

status=(ordin,ident,news);

chars=set of char;

var

letter,digit,separ:chars;

anytxt:string;

s:status;

i:integer;

c:char;

F:text;

begin

letter:=['A'..'Z','a'..'z'];

digit :=['0'..'9'];

separ :=[' '];

repeat

writeln(' Введите имя обрабатываемого файла');

readln(anytxt);

assign(F,anytxt);

{$I-} reset(F); {$I+}

i:=IOResult;

if i<>0 then

writeln(' Ошибочка ',i:3,' , попробуйте еще раз');

until i=0;

s:=news;

while not eof(F) do

begin

while not eoln(F) do

begin

read(F,c);

write( c);

case    s of

news : if c in letter then s:=ident

else if not(c in separ) then s:=ordin;

ident: if c in separ then

begin s:=news; writeln('*') end

else

if not((c in letter) or (c in digit))

then s:=ordin;

ordin: if c in separ

then begin s:=news; writeln end;

end;

end;

if s=ordin then begin s:=news; writeln end;

if s=ident then begin s:=news; writeln(' *') end;

readln(F);

end;

end.

9.4 Копия любого файла

program Copy;

var c:byte;

f,g:file of byte;

begin

assign(f,'file.abc');

assign(g,’file_copy.abc’);

reset(f); rewrite(g);

while not(eof(f)) do

begin

read(f,c);

write(g,c);

end;

close(f);

end.

Лекция 10

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

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

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

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

procedure <имя>(<формальные параметры>);{заголовок процедуры}

<секция описаний процедуры>

begin

<секция действий процедуры>

end;

function <имя>(<формальные параметры>):<тип>;{заголовок функции}

<секция описаний функции>

begin

<секция действий функции>

end;

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

Формальные параметры представляют собой список через «точку с запятой» предложений вида:

[var/const]<список переменных>:<имя типа>

Необязательные параметры var и const указывают способ передачи данных. Ключевое слово var означает, что данные передаются по адресу. Такие данные называются параметрами-переменными. Ключевое слово const означает, что данные передаются по адресу, но с защитой от изменения их значений. Такие данные называются параметрами-константами. Если перед списком переменных ключевое слово отсутствует, то данные передаются по значению. Такие параметры называются параметрами-значениями.

Обращение к подпрограммам осуществляется по следующей схеме:

Вызов процедуры (как самостоятельного оператора):

<имя>(<список фактических параметров>)

Вызов функции (в выражении, где допустим тип функции):

…<имя>(<список фактических параметров>)…

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

Тип передачи

Ключевое слово

Фактический параметр

По значению

-

Любые выражения соответствующего типа

По адресу

var

Имена переменных

По адресу

const

Любые выражения соответствующего типа

Между формальными (в описании подпрограммы) и фактическими (при обращении к подпрограмме) параметрами должно быть согласование по количеству, типам и порядку следования. (!)

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

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

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

1. Программа вычисляет величину y=max(min(x1,x2,x3),max(min(x3,x5,x4),x4))

program minmax;

var y,x1,x2,x3,x4,x5:real;

function max(a,b:real):real;

begin if a>b then max:=a else max:=b end;

function min(a,b:real):real;

begin if a<b then min:=a else min:=b end;

begin

  readln(x1,x2,x3,x4,x5);

  y:=max(min(x1,min(x2,x3)),max(min(x3,min(x5,x4)),x4));

  writeln(y)

end.

Обратите внимание на порядок обращений к подпрограммам!

2. Программа подсчитывает количество символов ‘A’,’B’ и ‘C’ в введенной пользователем строке:

program ABC;

var s:string; i:integer;

procedure kolABC(s:string; var kolA,kolB,kolC:integer);

begin

  kolA:=0; kolB:=0; kolC:=0;

  for i:=1 to length(s) do

     case s[i] do

        ‘A’: kolA:=kola+1;

        ‘B’: kolB:=kolB+1;

        ‘C’: kolC:=kolC+1;

     end;

end;

begin

  readln(s);

  kolABC(s,kolA,kolB,kolC);

  writeln(kolA,kolB,kolC);

end.

Функция ввода данного типа integer с защитой:

function enter_integer(s:string):integer;

var i,n:integer;

begin

  repeat

     readln(s);

     val(s,n,i);

     if i=0 then enter_integer:=n

  until i=0;

end;

10.2 Передача параметров в процедуры и функции

Как было сказано выше (!), список фактических параметров должен соответствовать списку формальных параметров по количеству (очевидно), порядку следования (очевидно), по типу (как это?).

Если передача данных осуществляется по значению, то значение фактического параметра должно быть присвоено переменной, являющейся формальным параметром. Если передача данных осуществляется по адресу, то переменной, являющейся фактическим параметром, должно быть присвоено «новое» значение в подпрограмме. В любом случае необходима совместимость по присваиванию. Например, легко понять, что при описании формального параметра массива не может использоваться описатель массива вида array [Ind] of type, поскольку в вызывающей программе, в этом случае, невозможно описать переменную того же типа, то есть, совместимую с формальным параметром. Вот как следует поступать:

program factich_par;

type mass=array [1..10] of real;

var i:integer;

   m:mass;

procedure pr_mass(m:mass);

var i:integer;

begin

  for i:=1 to 10 do write(m[i]:10:5); writeln

end;

begin

  for i:=1 to 10 do read(m[i]);

  pr_mass(m)

end.

Указанный механизм передачи данных в подпрограмму позволяет обрабатывать в подпрограмме только массивы, определенного в вызывающей программе типа. Это хорошее «паскалевское» решение. В качестве некоего послабления (и отклонения от принципов строгой типизации данных) в ТР (не в стандарте!) можно воспользоваться следующим механизмом передачи массивов в подпрограмму, называемым «открытым массивом». При описании открытого массива указывается лишь базовый тип, в качестве фактического параметра может использоваться любой массив с тем же базовым типом, в качестве индексного типа используется диапазон 0..N, где N – номер максимального элемента индексного типа фактического параметра:

var i:integer;

   m:array [0..10] of real;

procedure pr_mass(m:array of real{Open array};n:integer);

var i:integer;

begin

  for i:=0 to n do write(m[i]:10:5); writeln

end;

begin

  for i:=0 to 10 do read(m[i]); readln;

  pr_mass(m,10)

end.

10.3 Глобальные переменные. Перекрытие (экранирование)

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

Каждый объект (константа, тип данных, переменная или подпрограмма), описанный в программе на Паскале, имеет свою область «видимости» (соответствующее описание имеет свою область действия). Область действия описания начинается с места описания и заканчивается концом блока (оператором end), в котором выполнено описание. Для программы, структура которой условно изображена на схеме, подпрограмма А «видна» в любой части программы после ее описания. Подпрограмма В определена для секции действий программы. Подпрограммы А1 и А2 могут использоваться в секции действий подпрограммы А, причем подпрограмма А1 может быть использована в подпрограмме А2. Ни подпрограмма А1, ни подпрограмма А2 не могут выть использованы вне описания подпрограммы А. Подпрограмма А может быть вызвана в описании подпрограммы В (в секции действия В, или в секциях действия В1, В2, В21 и В22).

Аналогично определяется область действия описания типов данных, констант и переменных. Объект (подпрограмма, константа, тип данных или переменная) «виден» в тексте программы с места описания, до конца блока, в котором находится описание. Объект, использованный в блоке, входящем в область «видимости» его описания, называется глобальным по отношению к этому блоку. Использование глобальных объектов для обмена данными между программой и подпрограммой является альтернативой для механизма формальных и фактических параметров. Выбор способа передачи данных (для каких данных использовать механизм глобальных параметров, а для каких механизм формальных и фактических параметров) является одним из важнейших вопросов разработки проекта программы (не зависимо от того, на каком языке программирования будет реализован проект).

Внутри блока могут использоваться как глобальные, так и локальные объекты. К локальным объектам относятся формальные параметры и параметры, описанные внутри блока. Если локальный параметр совпадает по имени с одним из глобальных параметров, то глобальный параметр в данном блоке недоступен (правило экранирования). Внутреннее описание более сильное, оно перекрывает описание внешнего блока.

Program prog;

var i,x:integer; {глобальные переменные}

procedure p1(u:integer; var v:integer);

var i,y:integer; {локальные переменные}

begin

x:=1;

i:=2; y:=3;

writeln(x,i,y,u,v);

u:=7; v:=8;

end;

Begin

x:=0; i:=0;

writeln(x,i);

p1(i,i);

writeln(x,i);

end.

Результат работы программы:

00

12300

18

10.4 Процедурные типы

В TP можно использовать переменные процедурного типа. Переменные процедурного типа позволяют передавать в подпрограмму имена процедур и функций. Вот примеры описаний процедурных типов:

Type Proc1 = Procedure (a,b,c:real; var d:real);

Proc2 = Procedure (var a,b:real);

Func1 = Function: string;

Proc3 = Function (var s:string):real;

PROC = procedure; { процедура без параметров }

PROC4 = procedure (var x : real; y : integer);

FUN2 = function (x, y : real) : real;

var  f : FUN2;

Переменную f можно использовать, например, так:

{$F+}{Использование дальней адресации}

function deg(a,b:real):real;

begin {вычисляем степень: a**b}

deg:=exp(ln(a)*b);

end;{deg}

{$F-}

begin {программа}

  f := deg; writeln('2**15=',f(2,15));

end.

10.6 Рекурсия. Косвенная рекурсия

Функция вычисления факториала:

1. Рекуррентное определение

function Factor(n:integer):integer;

var i,f:integer;

begin

f:=1;

for i:=2 to n do f:=f*i;

Factor:=f;

end.

2.Рекурсивное определение

function Fact(n:integer):integer;

var f:integer;

begin

if n=0 then f:=1 else f:=Fact(n-1)*n

end.

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

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

Работа рекурсивной функции вычисления факториала показано на слайдах (прилагаются).

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

Лекция 11

11.1 Статическая и динамическая память программы

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

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

11.2 Динамическая память (куча, heap) с точки зрения ТР

Пусть Т – некоторый тип данных, тогда ^T – новый тип данных, такой, что q:^T – переменная (называемая указателем), которая может принимать значение адреса участка динамической памяти, куда может быть записано значение типа Т.

Инициализация указателя осуществляется процедурой new(q). Процедура new выделяет в области динамической памяти участок свободной памяти, объем которой достаточен для хранения данного типа Т, и переменной q присваивает значение адреса начала этого участка. Выделенный участок памяти объявляется занятым в области динамической памяти, сам выделенный участок является динамической переменной типа Т с именем q^.

Инициализация динамической переменной может быть осуществлена как и инициализация обычных статических переменных. Например, если t:T – инициализированная переменная типа Т, то можно выполнить присваивание динамической переменной q^:=t.

Когда динамическая переменная q^ выполнила свою функцию, и больше не нужна, от нее следует избавиться, освободив отведенную под нее память. Это можно сделать с помощью процедуры DISPOSE(q). Динамическая переменная q^ перестает существовать, память, отведенная под нее, становится свободной, а указатель q становится неопределенной (неинициализированной) переменной.

В ТР существует предопределенная константа NIL, совместимая со всеми указателями, которую можно трактовать, как «несуществующий адрес». Если переменной-указателю присвоить значение NIL (q:=NIL), то указатель q становится инициализированной переменной, однако q^ – бессмысленно .

11.3 Операции над указателями

Указатель может находиться в одном из трех состояний:

  1.  Указатель не инициализирован. Указатель можно инициализировать процедурой NEW, значением другого (инициализированного) указателя, или константой NIL.
  2.  Указатель инициализирован процедурой NEW. Можно использовать динамическую переменную q^, сам указатель сравнивать с другими указателями (только на совпадение или несовпадение), переинициализировать любым способом (см.1.);
  3.  Указатель инициализирован константой NIL. Можно указатель сравнивать с другими указателями (только на совпадение или несовпадение), переинициализировать любым способом (см.1.);

11.4 Пояснения с помощью картинки

Указатель q:^T описан в тексте программы на ТР. С помощью процедуры new(q) указатель q инициализируется. Диспетчер динамической памяти выделяет участок свободной памяти размером sizeof(T) в области динамической памяти (в куче) и адрес его начала присваивает переменной q. Теперь динамическая переменная q^ типа Т доступна для использования, однако, пока не инициализирована. Инициализировать ее можно, например, присваиванием q^:=t, где t – константа типа Т.

11.5 Динамическая цепочка

Зачем нужна динамическая переменная? Одиночная динамическая переменная не представляет никакого интереса. Интерес представляют различные структуры данных, созданные в области динамической памяти. Такие структуры создаются и развиваются на этапе выполнения программы, они могут быть адаптированы к текущим данным, объемы которых становятся известными лишь на этапе выполнения программы. Вернемся к задаче (*). Пользователь набирает на клавиатуре последовательность символов. Окончание набора фиксируется набором комбинации клавиш Ctrl+z, Enter. Для хранения введенных символов необходимо использовать структуру данных достаточного объема. Все статические структуры данных (структуры данных, созданные в статической памяти) имеют ограничения на количество вводимых символов. Попробуем организовать хранение введенных с клавиатуры символов в динамической памяти. Для этого в программе опишем новый тип данных, представляющий собой запись, содержащую поле типа char для хранения введенного символа, и поле типа «указатель» на следующую запись:

PElem=^Elem;

Elem=Record 

inf:char;

next:PElem 

end

В начале работы программы создается пустая цепочка записей. После каждого ввода очередного символа создается новая запись и подсоединяется к цепочке. Пусть p – данное типа PElem, x:char, тогда

  •  p:=nil; {Создана пустая цепочка p}
  •  while not eof do

begin

readln(x);

new(q);

q^.inf:=x;

q^.next:=p;

p:=q;

end; {Создана цепочка записей, p – указатель на первую запись цепочки}

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

Задача: Распечатать третью запись цепочки, если она есть.

writeln(p^.next^.next^.inf) {а если её нет?!}

Задача: Распечатать k-ую запись цепочки.

q:=p;

i:=1;

while (q<>nil) and (i<k) do

begin

i:=i+1;

q:=q^.next;

end;

if q<>nil then writeln(q^.inf) else writeln(‘нет записи’);

Распечатать информационные части цепочки p.

Традиционное решение

Рекурсивное решение

Procedure prnchar(p:PElem);

begin

  while p<>NIL do

  begin

     write(p^.inf);

     p=p^.next

  end

end

Procedure prnchar(p:PElem);

begin

  if p<>NIL then

  begin

     write(p^.inf);

     prnchar(p^.next)

  end

end

Задача: Распечатать информацию, вводимую с клавиатуры, в прямом порядке.

Задача: «Перевернуть» файл (Указание – использовать цепочку)

Лекция 12

12.1 Цикл жизни программы. Проект программы

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

Проектирование Кодирование ОтладкаТестирование Сопровождение

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

Проектирование = типы данных + структуры данных + процедуры и функции + алгоритмы

На этапе проектирования программы определяется язык (или языки) программирования для реализации проекта.

Кодирование – воплощение проекта в коды на выбранном алгоритмическом языке. Творческая составляющая этапа кодирования ограничена рамками проекта. От кодировщика во многом зависит читабельность текста программы.

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

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

12.2 Характеристики качества программ

Существует очень много различных характеристик качества программы. Значимость их в критериях качества программы в целом зависит от назначения и условий функционирования программы. Невозможно разработать единый критерий качества для всех программ. Вот некоторые из характеристик качества программы:

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

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

Модифицируемость (или открытость). Доступность исходного кода программы. Иногда под модифицируемостью понимают предусмотренные в проекте программы возможные изменения.

Читабельность + внутренняя документированность. Очень важные свойства на этапе ведения программы. Помогают разобраться в программе программисту, не участвовавшему в создании программы.

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

Надежность. Эффективное функционирование в условиях воздействия различных отрицательных факторов.

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

12.3 Программное окружение

Эффективность работы программиста определяется его квалификацией и опытом работы. В профессиональной деятельности программиста его опыт материализуется в программном окружении. Программное окружение программиста – библиотека программных продуктов (процедур, функций, объектов, компонент программных сред и т.п.), используемых программистом как дополнительные средства языка. В эту библиотеку могут входить как программные продукты, разработанные самим программистом, так и средства общего назначения (библиотеки процедур и функций общего назначения, редакторы, трансляторы, кросс-трансляторы, редакторы связей и тому подобное), называемые инструментальными средствами (или утилитами).

Для создания и поддержки программного окружения в языках программирования разработаны свои средства. В языке ТР это модули.

12.4 Модули

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

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

Погружение программы в область описаний модуля осуществляется в предложении uses. Это предложение записывается сразу после заголовка программы и имеет следующий формат:

uses <список модулей через запятую>

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

Структура модуля:

Unit <имя модуля>;

interface

[uses ...]

<описания глобальных типов данных, переменных, констант, процедур и функций>

implementation

[uses ...]

<реализация>

begin

<инициализация>

end.

Имя файла, содержащего исходный текст модуля (.pas) или объектный код (tpu), должно совпадать с именем модуля. Если имя модуля длиннее восьми символов, то оно должно совпадать с именем файла по первым восьми символам.

В списке uses имен модулей не должно быть «рекурсий» и «циклов»

При работе с модулями следует помнить, что в среде ТР имеется возможность управлять размещением кодов в файловой системе и режимами трансляции:

Options/Directories/EXE&TPU - сюда будут помещены загрузочные и объектные коды

Options/Directories/Unit Directories - здесь будет осуществляться поиск объектных (TPU) кодов модулей

Compile/Compile – компиляция только программы

Compile/Make – компиляция программы и модулей, текст которых был изменен

Compile/Build – компилируется и программа, и все модули

Пример

 Печать данного перечислимого типа. Вот простой пример модуля (пусть имя файла с  представленным  ниже текстом My_Unit.pas):

Unit My_Unit;

Interface

type Color=(Red,Yellow,Green);

procedure WriteColor(x:Color);

Implementation

var mass:array[Color] of string[6];

procedure WriteColor;

begin writeln(mass[x]:6) end;

begin

mass[Red]:=' Red';

mass[Yellow]:='Yellow';

mass[Green]:='Green'

end.

После трансляции  этого модуля средствами интегрированной среды ТР в директории  модулей интегрированной среды образуется файл My_Unit.tpu. Теперь можно воспользоваться новым средством

Uses My_Unit;

var Col:Color;

begin

Col:=Red;

WriteColor(Col)

end.

На экране появится  Red

12.5 Обзор модуля System

Модуль System не нужно указывать в предложении uses, поскольку он доступен каждой программе ТР по умолчанию. В модуле предопределены переменные Input и Output как стандартные текстовые файлы ввода и вывода.

12.5.1 Процедуры и функции, обслуживающие файловую систему

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

s disk:\kat\kat\...\file – поиск объекта file осуществляется с корневого каталога; s disk:kat\kat\...\file – поиск с текущей директории указанного диска.

GetDir(d:byte;var s:string); (d=0 – текущий дисковод, 1 – a:, 2 – b: и т.д.), s – текущий каталог.

ChDir,MkDir,RmDir(s:string) – изменение, создание, удаление пустого

Rename(f; newname:string) – переименование файла;

Задача: Написать процедуру удаления любого каталога (даже непустого).

12.5.2 Процедуры управления работой программы

Exit - выход из программы, функции, процедуры.

Halt(kod:word) - выход из программы.

12.5.3 Процедуры и функции распределения динамической памяти

GetMem, FreeMem(var p:pointer; size:word) - создает, уничтожает динамическую переменную.

MaxAvail, MemAvail:longint - объем максимального непрерывного участка и полный свободный объем динамической памяти;

Mark, Release(var p:pointer); - создает, удаляет новую кучу

12.5.4 Функции для работы с указателями

Addr(x):pointer; х - идентификатор переменной, процедуры или функции.

Seg(x):word;

Ofs(x):word;

Ptr(segm,ofset:word):pointer;

Программы с параметрами:

ParamCount:word; - количество параметров в командной строке (разделители пробелы и таб)

ParamStr(index:word):string; - возвращает заданный параметр командной строки.

Пример - программа, вычисляющая сумму

program sum;{ex_04}

var

s,x:real;

i,j,k:integer;

begin

s:=0;

i:=ParamCount;

j:=1;

while j<=i do

begin

val(ParamStr(j),x,k);

if k=0 then s:=s+x;

j:=j+1;

end;

writeln(s:10:5)

end.

Sum.pas ->sum.exe

Option/Directories

Выполнение в DOS: sum 3 5 7

Выполнение в ТР: Run..., Parameters

12.6 Список процедур и функций модуля

Процедуры управления 

Procedure Break Обеспечивает немедленный выход из операторов повторения.  

Procedure Continue Завершает очередной итерационный цикл операторов повторения. 

Procedure Exit Позволяет немедленно выйти из текущей подпрограммы. При вызове из тела основной программы завершает ее работу. 

Procedure Halt [ (ExitCode: Word)] Останавливает выполнение программы и возвращает управление в операционную систему. Необязательный параметр ExitCode определяет код завершения программы. 

Procedure RunError [ (ErrorCode: Byte)] Останавливает выполнение программы и генерирует ошибку периода выполнения программы. Необязательный параметр ErrorCode определяет код ошибки. 

Процедуры динамического распределения памяти 

Procedure Dispose(var P: Pointer [,Destructor]) Уничтожает динамическую переменную, связанную с указателем Р. Необязательный параметр Destructor определяет метод-деструктор для динамического объекта. 

Procedure FreeMem(var P: Pointer; Size: Word) Уничтожает динамическую переменную P размером Size байт. 

Procedure GetMemt(var Р: Pointer; Size: Word) Создает новую динамическую переменную Р заданного размера Size. 

Procedure Mark(var P: Pointer) Записывает в указателе Р текущее состояние кучи. 

Procedure New(var P; Pointer [,Constructor]) Создает новую динамическую переменную, связанную с указателем Р. Необязательный параметр Constructor определяет метод-конструктор для динамического объекта. 

Procedure Release (var P: Pointer) Возвращает кучу в состояние, которое было сохранено в указателе Р процедурой Mark. 

Функции динамического распределения памяти 

Function MaxAvail: LongInt Возвращает размер наибольшего непрерывного свободного блока кучи, соответствующий размеру наибольшей динамической переменной, которая может быть помещена в кучу. 

Function MemAvail; LongInt Возвращает количество имеющихся в куче свободных байт памяти. 

Функции преобразования 

Процедуры Pack и UnPack, определенные в стандартном Паскале, в Турбо Паскале не реализованы.

Function Chr(X: Byte): Char Возвращает символ с заданным порядковым номером X. 

Function Ord(X) : LongInt Возвращает порядковый номер, соответствующий значению X порядкового типа. 

Function Round (R: Real) : LongInt Округляет значение R вещественного типа до ближайшего целого. 

Function Trunc(R: Real): LpngInt Усекает значение вещественного типа до значения типа LongInt путем отбрасывания дробной части. 

Арифметические функции 

При компиляции в режиме использования сопроцессора или его эмуляции арифметические функции возвращают значение типа EXTENDED, в противном случае - типа REAL. 

Function Abs(R; Real): Real Возвращает абсолютное значение аргумента. 

Function ArcTan(R: Real): Real Возвращает арктангенс аргумента. 

Function Cos(R: Real): Real Возвращает косинус аргумента. 

Function Exp(R; Real): Real Возвращает экспоненту аргумента. 

Function Frac(R; Real): Real Возвращает дробную часть аргумента. 

Function Int(R; Real): Real Возвращает целую часть аргумента. 

Function Ln(R: Real) : Real Возвращает натуральный логарифм аргумента. 

Function Pi: Real Возвращает значение числа pi=3.1415926535897932385. 

Function Sin(R: Real): Real Возвращает синус аргумента. 

Function Sqr(R: Real): Real Возвращает аргумент в квадрате. 

Function Sqrt(R; Real): Real Возвращает квадратный корень аргумента. 

Процедуры порядкового типа 

Procedure Dec (var X [; DX: LongInt] ) Уменьшает значение переменной X на величину DX, а если параметр DX не задан - на 1. 

Procedure Inc (var X [; DX: LongInt]) Увеличивает значение переменной X на величину DX, а если параметр DX не задан - на 1. 

Функции порядкового типа 

Function Odd(X) : Boolean Проверяет, является ли аргумент нечетным числом. 

Function Pred(X) Возвращает предшествующее значение аргумента. Тип результата совпадает с типом аргумента. 

Function Succ(X) Возвращает последующее значение аргумента. Тип результата совпадает с типом аргумента. 

Строковые процедуры 

Procedure Delete (var S: String; Index, Count: Integer) Удаляет Count символов из строки S, начиная с позиции Index. 

Procedure Insert (SubS: String; var S: String; Index: Integer) Вставляет подстроку SubS в строку 5, начиная с позиции Index. 

Procedure Str(X [: width [: Decimals]]; var S: String) Преобразует численное значение X в его строковое представление S. 

Procedure Val(S; String; var X; var Code: Integer) Преобразует строковое значение S в его численное представление X. Параметр Code -содержит признак ошибки преобразования (0 - нет ошибки). 

Строковые функции 

Function Concat(S1 [, S2,...,SN]): String Выполняет конкатенацию последовательности строк. 

Function Copy(S: String; Index, Count: Integer): String Возвращает подстроку из строки S, начиная с позиции Index и длиной Count символов. 

Function Length(S: String): Byte Возвращает текущую длину строки S. 

Function Pos(SubS, S: String): Byte Возвращает позицию, начиная с которой в строке S располагается подстрока SubS (О - S не содержит SubS). 

Функции для работы с указателями и адресами 

Function Addr (X) : Pointer Возвращает адрес заданного объекта X. 

Function Assigned: (var P) : Boolean Проверяет, хранит ли ли указатель Р значение, отличное от NIL, и возвращает TRUE в этом случае. 

Function CSeg: Word Возвращает текущее значение регистра CS.

Function DSeg: Word Возвращает текущее значение регистра DS.

Function Ofs (X) ; Word Возвращает смещение заданного объекта. 

Function Ptr(Seg, Ofs: Word): Pointer Преобразует сегмент Seg и смещение Ofs в значение типа указатель. 

Function Seg (X) : Word Возвращает сегмент для заданного объекта X. 

Function SPtr: Word Возвращает текущее значение регистра SP. 

Function SSeg: Word Возвращает текущее значение регистра SS. 

Процедуры разного назначения 

Procedure Exclude (var S: set of Т; I: T) Исключает элемент T из множества S. 

Procedure FillChar(var X; Count: Word; Value) Заполняет заданное количество Count последовательных байт переменной X указанным значением Value (выражение любого порядкового типа). 

Procedure Include (var S: set of Т; I; T) Включает элемент T во множество S. 

Procedure Move (var X, Y, Count: Word) Копирует заданное количество последовательных байт из источника X в переменную Г. 

Procedure Randomize Инициализирует случайным значением (текущим системным временем) встроенный генератор псевдослучайных чисел. 

Функции разного назначения 

Function Hi(X; Word) : Byte Возвращает старший байт аргумента X.

Function High (X) Возвращает максимальное значение порядкового типа.

Function Lo(X: Word): Byte Возвращает младший байт аргумента X.

Function Low(X) Возвращает минимальное значение порядкового типа. 

Function ParamCount: Word Возвращает число параметров, переданных программе в командной строке (строке вызова). 

Function ParamStr(N; Byte): String Возвращает N-ый параметр командной строки. 

Function Random [ (Range: Word)] Возвращает псевдослучайное число. Если параметр Range опущен, функция возвращает вещественное число в диапазоне от 0 до 1, если указан - целое число в диапазоне от 0 до Range-1. 

Function SizeOf(X): Word Возвращает число байт, занимаемых аргументом. 

Function Swap(X) Производит перестановку старших и младших байт двухбайтного аргумента X. Тип функции соответствует типу аргумента. 

Function UpCase(C: char): Char Преобразует латинскую букву в заглавную. 

Процедуры ввода/вывода 

Procedure Assign (var F; Name: String) Связывает внешний файл Name с файловой переменной F. 

Procedure ChDir(S: String) Устанавливает текущий каталог.  

Procedure Close (var F) Закрывает открытый файл.  

Procedure Erase (var F) Удаляет внешний файл. 

Procedure GetDir(D: Byte; var S: String) Возвращает каталог по умолчанию S на заданном диске D. 

Procedure MkDir(S: String) Создает подкаталог S. 

Procedure Rename (var F) Переименовывает внешний файл. 

Procedure Reset (var F) Открывает существующий файл для чтения или изменения. 

Procedure Rewrite (var F) Создает и открывает новый файл. 

Procedure RmDir(S: String) Удаляет пустой подкаталог. 

Procedure Seek (var F; N: LongInt) Устанавливает текущую позицию файла на указанный элемент (не используется с текстовыми файлами). 

Procedure Truncate (var F) Усекает размер файла до текущей позиции в файле (не используется с текстовыми файлами) 

Функции ввода/вывода 

Function EOF (var F) ; Boolean Возвращает для файла F признак конца файла. 

Function FilePos (var F) : LongInt Возвращает текущую позицию в файле (не используется с текстовыми файлами) 

Function FileSize(var F) : LongInt Возвращает текущий размер файла (не используется с текстовыми файлами). 

Function IOResult; Integer Возвращает целое значение, являющееся состоянием последней выполненной операции ввода/вывода. 

Процедуры для текстовых файлов 

Procedure Append (var F: Text) Открывает существующий файл для расширения.  

Procedure Flush (var F: Text) Выталкивает буфер файла вывода. 

Procedure Read ([var F: Text;] V1 [, V2,...,VN]) Считывает одно или более значений из текстового файла в одну или более переменных. 

Procedure Readln Выполняет те же действия, что и Read, а потом делает пропуск до начала следующей строки файла. 

Procedure SetTextBuf (var F: Text; var Buf [; Size: Word]) Назначает буфер ввода/вывода для текстового файла. Параметр Size определяет длину буфера в байтах (если Size опущен, длина буфера равна 128 байтам). 

Procedure Write([var F: Text;] V1 [, V2,...,VN]) Записывает в текстовый файл одно или более значений. 

Procedure WriteLn Выполняет те же действия, что и Write, а затем добавляет к файлу маркер конца строки. 

Функции для текстовых файлов 

Function Eoln(var F: Text): Boolean Возвращает признак конца строки. 

Function SeekEof [ (var F: Text)]: Boolean Возвращает признак конца файла. Предварительно пропускает все пробелы, символы табуляции и признаки конца строк. 

Function SeekEoln [ (var F: Text)]: Boolean Возвращает признак конца строки. В отличие от Eoln предварительно пропускает все пробелы и символы табуляции. 

Процедуры для нетипизированных файлов 

Procedure BlockRead(var F: File; var Buf; Count; Word [;var Result; Word]) Считывает в переменную Buf Count записей из файла F. Необязательный параметр Result содержит истинное количество считанных записей. 

Procedure BlockWrite(var F; File; var Buf; Count: Word [;var Result: Word]) Передает Count записей из переменной Buf файла F. Необязательный параметр Result содержит истинное количество переданных записей. 

Лекция 13

13.1 Модуль CRT - средства работы с экраном, клавиатурой и др.

T7TPLFIX.EXE - утилита в BIN. Экран 80х25

ClrScr - очистка текущего окна (закраска цветом фона)

GotoXY(x,y) - позиционирование курсора.

WereX, WereY - возвращают позиции курсора по вертикали и горизонтали.

Window(x1,y1,x2,y2);

Delay(M:word) - задержка в миллисекундах.

Sound(G:word) - частота в герцах.

NoSound - выключение динамика.

TextBackGround(0..7)

TextColor(0..15)

KeyPressed: boolean;

ReadKey: char;

13.2 Обзор примеров программ

Очистка буфера клавиатуры:

while KeyPressed do c:=ReadKey;

{Ex_01} - День недели по дате (ранее разобран)

{Ex_02}- Symplest scanner (ранее разобран)

program DemoCRT; {Ex_03}

uses CRT;

Const

S1=' Конец pаботы  ';

S2=' Работа 1      ';

S3=' Работа 2      ';

Col=15; Fon=0;

FonInv=Col; ColInv=Fon;

var

ActivStr:integer;

c:char;

Procedure OverWrite;

begin

GotoXY(4,ActivStr);

Case ActivStr of

7  : write(S1);

8  : write(S2);

9  : write(S3);

end

end;

Procedure Wind(k:integer);

begin

OverWrite;

ActivStr:=ActivStr+k;

if ActivStr<7 then ActivStr:=9;

if ActivStr>9 then ActivStr:=7;

TextBackGround(FonInv);TextColor(ColInv);

OverWrite;

TextBackGround(Fon);TextColor(Col);

end;

begin

Activstr:=9;

while TRUE do

begin

TextBackGround(Fon); TextColor(Col);

ClrScr;

GotoXY(10,3);

Writeln('PROGRAM DEMO CRT');

GotoXY(10,5); Writeln(' основное меню');

GotoXY(4,7); WRITE(S1);

GotoXY(4,8); WRITE(S2);

GotoXY(4,9); WRITE(S3);

WIND(0);

repeat

c:=ReadKey;

if c=#0 then

begin

c:=ReadKey;

if c=#72 then WIND(-1);

if c=#80 then WIND(1);

end;

until c=#13;

case ActivStr of

0 :;

7 :begin ClrScr;writeln(S1);Delay(1000);Halt; end;

8 :begin ClrScr;writeln(S2);Delay(1000); end;

9 :begin ClrScr;writeln(S3);Delay(1000); end;

end;

ClrScr;

end;

end.

{УСТАHОВКА ЦВЕТА}

program ex_06;

uses Crt;

var Fon,Col,ColD,FonInv,ColInv,ColInvD:byte; OldC:byte;

procedure Frame(i1,j1,i2,j2:integer);

var i,j:integer;

begin

if (i1 < 1) or (i2 > 80) or (i1 >= i2) or

(j1 < 1) or (j2 > 25) or (j1 >= j2) then exit;

GotoXY(i1,j1);

write('г');for i:=i1 + 1 to i2 - 1 do

write('=');write('¬');

for j:=j1 + 1 to j2 - 1 do

begin GotoXY(i1,j);write('¦');

GotoXY(i2,j);write('¦')

end;

GotoXY(i1,j2);

write('L');for i:=i1 + 1 to i2 - 1 do

write('=');write('-');

GotoXY(i2 - 1,j1 + 1)

end;

procedure MySetColor(var Fon,Col,ColD,FonInv,ColInv,ColInvD:byte);

var c:char;

begin

ClrScr; Writeln('УСТАHОВКА ЦВЕТА ДЛЯ МЕHЮ И ПАHЕЛЕЙ');

Writeln('клавиша                  ц в е т ');

Writeln('c               основной   цвет ');

Writeln('v            выделенный цвет ');

Writeln('f                   цвет фона       ');

Writeln('i инверсный   основной   цвет ');

Writeln('j инверсный выделенный цвет');

Writeln('g    инверсный   цвет фона     ');

begin

Writeln('Hажмите <ENTER> после установки');

Frame(2,10,41,15); Window(3,11,40,14);

repeat

TextBackGround(FonInv); ClrScr;

TextBackGround(Fon);

TextColor(Col);Write(' Основной текст   ');

TextColor(ColD   );

Write  ('   Выделенный цвет          ');

TextBackGround(FonInv);

TextColor(ColInv );

Write  (' Инвеpсный основной текст  ');

TextColor(ColInvD);

Write('Инвеpсный выделенный текст  ');

c:=ReadKey;

case c of

'f': Fon    :=(Fon+1)     mod  8;

'g': FonInv :=(FonInv+1)  mod  8;

'c': Col    :=(Col+1)     mod 16;

'v': ColD   :=(ColD+1)    mod 16;

'i': ColInv :=(ColInv+1)  mod 16;

'j': ColInvD:=(ColInvD+1) mod 16;

else;

end

until c=#13;

TextBackGround(Fon);

TextColor(Col    );

end;

TextBackGround(0);

TextColor(15);

OldC:=TextAttr;

Fon:=0;Col:=15;ColD:=14;FonInv:=7;

ColInv:=0;ColInvD:=1;

MySetColor(Fon,Col,ColD,FonInv,ColInv,ColInvD);

Window(1,1,80,25);ClrScr;

writeln('Установлены цвета:');

writeln('   Fon    Col    ColD   FonInv ColInv ColInvD');

writeln(Fon:7,Col:7,ColD:7,FonInv:7,ColInv:7,ColInvD:7);

repeat until KeyPressed;

TextAttr:=OldC

end.

***********************************

CheckBreak: (Boolean)

Controls user termination of an application using the CRT window.

const CheckBreak: Boolean = True;

When CheckBreak is True, the user can terminate the application at any time by pressing Ctrl-Break

CheckEOF: (Boolean)

Controls the end-of-file character checking in the CRT window.

Const CheckEOF: Boolean = False;

When CheckEOF is True, an end-of-file marker is generated when the user presses Ctrl+Z while reading from a file assigned to the CRT window. When CheckEOF is False, pressing Ctrl+Z has no effect.

13.3 Процедуры и функции модуля Crt

Функции

KeyPressed - Возвращает True, если на клавиатуре была нажата  клавиша, и False в противном случае.

ReadKey - Читает символ с клавиатуры.

WhereX - Возвращает Х координату текущей позиции курсора  относительно текущего окна. Х - горизонтальная позиция.

WhereY - Возвращает Y координату текущей позиции курсора   относительно текущего окна. Y - вертикальная  позиция.

Процедуры

AssignCrt - Назначает текстовый файл на экран.

ClrEol -  Удаляет все символы от текущей позиции курсора до конца строки без передвижения курсора.

ClrScr - Очищает экран и помещает курсор в верхний левый угол.

Delay - Задержка на указанное число миллисекунд.

DelLine - Удаляет строку на которой находится курсор и перемещает все строки ниже этой строки на    строку вверх. Нижняя строка очищается.

GotoXY - Позиционирует курсор. Х - горизонтальная позиция и Y - вертикальная позиция.

HighVideo - Устанавливает высокую интенсивность символов.

InsLine - Вставляет пустую строку в позиции курсора.

LowVideo - Устанавливает низкую интенсивность символов.

NormVideo - Устанавливает нормальную интенсивность символов.

NoSound - Выключает внутренний громкоговоритель.

Sound - Включает внутренний громкоговоритель.

TextBackground - Устанавливает цвет фона.

TextColor - Устанавливает цвет символов.

TextMode - Устанавливает текстовый режим.

Window - Определяет текстовое окно на экране. 

Лекция 14

14.1 Модуль DOS - работа с файловой системой. 

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

DiskFree(d:word):longint; - свободных байт на диске d (0-тек, 1-a:, ...)

DiskSize(d:word):longint; - полный объем.

Переменная DosError:integer;

0

нет ошибки

2

файл не найден

3

путь не найден

5

доступ запрещен

6

неверный обработчик

8

нет памяти

10

неправильная среда

11

неправильный формат

18

больше нет файлов

FindFirst(path:string; attrib:byte; var s:SearchRec);

FindNext(var s:SearchRec);

type SearchRec=record

Fill:array[1..21]of byte;

Attr:byte;

Time:longint;

Size:longint;

Name:string[12]

end;

const

ReadOnly=$01;

Hidden=$02;

SysFile=$04;

VolumeId=$08;

Directory=$10;

Arhive=$20;

AnyFile=$3F;

GetAttr(var F; var Attr:byte) - Возвращает атрибут файла

SetAttr (var F; var Attr:byte) - Устанавливает атрибут файла

14.1.1 Прерывания.

Примитивы ввода-вывода и других системных операций BIOS и DOS.

Схема:  регистры - прерывание - регистры.

Registers=record

case integer of

0:(AX,BX,CX,DX,BP,SI,DI,DS,ES,Flag:word);

1:(AL,AH,BL,BH,CL,CH,DL,DH:byte);

end;

Intr(nom:byte; var R:Registers);

MsDos(var R:Registers); - прерывание номер $21 DOS.

Пример: прерывание $10(BIOS) - обмен данными с дисплеем

Функц.

Исходные данные

Результат

8

AH=8; BH=0 - страница дисплея;

(AL) - символ в тек поз курс;(AH) - атрибут

9

AH=9; BH=0 - страница дисплея;

(BL) - атрибут символа;

(CX) - счетчик; (AL) - символ;

Помещает в текущую позицию курсора

(СХ) штук символов (AL)

с атрибутом (BL)

10

AH=10; BH=0 - страница дисплея;

(CX) - счетчик; (AL) - символ;

Помещает в текущую позицию курсора

(СХ) штук символов (AL)

с текущим атрибутом

$11

чтение конфигурации системы

$13

обмен данными с диском

$20 - $3F

прерывания DOS.

$21

функции DOS.

$25

абсолютное чтение с диска.

$26

абсолютная запись на диск.

$27

завершение программы с сохранением ее в памяти (резидентная программа).

{Ex_07_10}

program Txt;

uses Crt,Dos;

var R:registers; i,j,k :integer;

begin

ClrScr;

GotoXY(20,10);

R.AH:=10; R.BH:=0;

R.CL:=255; R.CH:=0;

R.AL:=ord('A');

Intr(16,R);

readln

end.

procedure PutTxtImege(x1,y1,x2,y2:integer; var p:pointer);

var R:registers; i,j,k :integer; pr:^byte;

begin

GetMem(p,(x2-x1+1)*(y2-y1+1)*2);

k := 0;

for i:=x1 to x2 do

for j:=y1 to y2 do

begin

GotoXY(i,j);

R.AH:=8; R.BH:=0;

Intr(16,R);

pr:=ptr(seg(p^),ofs(p^) + k);

pr^:=R.AL;

pr:=ptr(seg(p^),ofs(pr^)+1);

pr^:=R.AH;

k := k + 2;

end;

end;

procedure GetTxtImege(x1,y1,x2,y2:integer;

var p:pointer);

var R:registers; i,j,k :integer; pr:^byte;

begin

k := 0;

for i:=x1 to x2 do

for j:=y1 to y2 do

begin

GotoXY(i,j);

R.AH:=9; R.BH:=0;

R.CL:=1; R.CH:=0;

pr:=ptr(seg(p^),ofs(p^) + k);

R.AL:=pr^;

pr:=ptr(seg(p^),ofs(pr^)+1);

R.BL:=pr^;

Intr(16,R);

k := k + 2;

end;

FreeMem(p,(x2-x1+1)*(y2-y1+1)*2);

end;

14.1.2 Процедуры и функции модуля Dos

Процедуры даты и времени

GetDate - Возвращает текущую дату, установленную в DOS

GetFTime - Возвращает дату и время последней записи в файл

GetTime - Возвращает текущее время, установленное в DOS

PackTime - Преобразует запись   в   4   байтовое  упакованное значение даты и времени типа longint, используемое  процедурой   SetFTime.  Поля  записи  DateTime  не проверяются на диапазон

SetData - Устанавливает текущую дату в DOS

SetFTime - Устанавливает время и дату последней записи в файл

SetTime - Устанавливает текущее время в DOS

UnpackTime - Преобразует 4-х байтовое упакованное значение даты и времени, возвращаемое GetFTime, FindFirst или FindNext в распакованную запись типа DateTime

Процедуры обслуживания прерываний

GetIntVeс - Возвращает адрес, хранящийся в указанном векторе прерывания

Intr - Выполняет указанное программное прерывание

MSDos - Выполняет функцию операционной системы

SetIntVec - Устанавливает адрес для указанного вектора прерывания

Функция статуса диска

DiskFree -  Возвращает число свободных байт на указанном диске

DiskSize - Возвращает полный объем указанного диска в байтах

Процедуры обработки файлов

FindFirst - Ищет в  указанном  или  текущем справочнике первый файл,  соответствующий  заданному  имени  файла  и  набору атрибутов

FindNext - Возвращает следующий файл,соответствующий имени и атрибутам, указанным в предыдущем вызове FindFrst

GetFAttr - Возвращает атрибуты файла

SetFAttr   Устанавливает атрибуты файла

FSplit - Разбивает имя файла на 3 составные части (справочник, имя файла, расширение)

Функции обработки файла

FExpand - Берет имя файла  и  возвращает  полное  имя  файла (устройство, справочник, имя и расширение)

FSearch - Ищет файл в списке справочников

Процедуры обработки процессов

Exec - Выполняет заданную программу с указанной командной строкой

Keep - Завершает программу   и   оставляет   ее   в  памяти (реализует   прерывание   "завершить   и    оставить резидентным"- TSR)

SwapVectors - Меняет сохраненные вектора прерываний с текущими векторами

Функции обработки процессов

DosExitCode - Возвращает код завершения подпроцесса

Функции управления средой

EnvCount - Возвращает число строк, содержащихся в среде DOS

EnvStr - Возвращает указанную строку среды

GetEnv - Возвращает значение указанной переменной среды

Дополнительные процедуры

GetCBreak - Возвращает состояние проверки Ctrl-Break в DOS

SetCBreak - Устанавливает состояние проверки Ctrl-Break в DOS

GetVerify - Возвращает состояние флага верификации в DOS

SetVerify - Устанавливает состояние флага верификации в DOS

Дополнительные функции

DosVersion - Возвращает номер версии DOS

Лекция 15

15.1 Модуль Graph.

На примере программы построения графика заданной функции

program Graphic;

uses Graph,Crt;

var Xmax,Ymax,Xmin,Ymin,hx,hy,x,y,xx1,xx2,yy1,yy2 : real;

Gd,Gm,xx,yy,mx,my,i,Color,x1,x2,y1,y2 : integer;

s : string[40];

function F(x : real) : real;

begin

F:=sin(10*x*x)    {Функция, график которой строим}

end;

begin {Тело программы}

{ Начальные установки =======================================}

Color:=15;

writeln('Введите реальные координаты графика Xmax,Xmin,Ymax,Ymin');

readln(Xmax,Xmin,Ymax,Ymin);

writeln('Введите относительные координаты экрана x1,x2,y1,y2');

readln(xx1,xx2,yy1,yy2);

{ Установка графического режима =============================}

Gd:=Detect;

InitGraph(Gd,Gm,'d:\bp\BGI\');

i:=GraphResult;

if i<>grOk then

begin

writeln('Ошибка', i:3,'Нажмите любую клавишу');

repeat until KeyPressed; Exit

end;

{ Масштабирование ==========================================}

mx:=GetMaxX; my:=GetMaxY;

x1:=round(xx1*mx); x2:=round(xx2*mx); {Относительные координаты}

y1:=round(yy1*my); y2:=round(yy2*my);  {выржаются в пикселах}

hx:=(x2-x1)/(Xmax-Xmin);

hy:=(y2-y1)/(Ymax-Ymin);

{ Рисуем оси координат =======================================}

xx:=x1-round(Xmin*hx);

if (xx>x1)and(xx<x2) then Line(xx,y1,xx,y2);

yy:=y1-round(Ymin*hy);

if (yy>y1)and(yy<y2) then Line(x1,yy,x2,yy);

{Подпись}

OutTextXY(x1,y2+round(0.1*my),'Pic.1. My picture');

{ Устанавливаем шкалы на оси и рисуем сетку ===================}

for i:=1 to 11 do

begin

xx:=x1+(i-1)*(x2-x1) div 10;

x:=Xmin+(Xmax-Xmin)/10*(i-1);

Str(x:5:2,s);

if odd(i) then OutTextXY(xx-20,y2+round(0.05*my),s);

Line(xx,y1,xx,y2);

yy:=y1+(i-1)*(y2-y1) div 10;

y:=Ymax-(Ymax-Ymin)/10*(i-1);

Str(y:5:2,s);

Line(x1,yy,x2,yy);

OutTextXY(x1-round(0.1*mx),yy-5,s);

end;

{ Рисуем график =============================================}

for i:=x1 to x2 do

begin

x:=Xmin+(i-x1-1)/hx;

y:=F(x);

yy:=y1+Round((Ymax-y)*hy);

PutPixel(i,yy,Color)

end;

{ Задержка ========================================}

repeat until KeyPressed;

CloseGraph

end.

Задание.

Заменить PutPixel на LineTo

Посмотреть, какие еще процедуры и функции имеются в модуле Graph

Задача «Часики» (CRT, Graph)

15.1.1 Общие сведения:

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

- 64 -