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

Язык Паскаль является одним из наиболее популярных языков программирования. Первая версия языка программирования Паскаль была разработана на кафедре информатики Стенфордского университета швейцарским ученым Никлаусом Виртом в 1968г., и названа в честь французского учёного Блеза Паскаля(1623-1662).
Существует ряд объективных причин, обусловивших выдающийся успех языка Паскаль. Среди них в первую очередь необходимо указать следующие:
1. Язык в естественной и элегантной форме отразил современные важнейшие концепции технологии разработки программ: развитая система типов, ориентации на принципы структурного программирования, поддержка процесса пошаговой разработки.
2. Благодаря своей компактности, концептуальной целостности, а также удачному первоначальному описанию, предложенному автором языка, Паскаль оказался весьма легок для изучения и освоения. В противоположность громоздким многотомным описаниям таких языков, как PL/1, COBOL,FORTRAN, достаточное описание языка Паскаль занимает около 30 страниц текста, а его синтаксические правила можно разместить на одной странице.
3. Несмотря на относительную простоту языка, он оказался пригоден для весьма широкого спектра предложений, в том числе для разработки очень больших и сложных программ, например, операционных систем.
4. Паскаль весьма технологичен для реализации практически для всех, в том числе и не традиционных, машинных архитектур. Благодаря этому для многих ЭВМ существует несколько различных реализаций языка, отражающих те или иные практические потребности программистов.
Язык Паскаль стандартизирован во многих странах. Во 1983г. был принят международный стандарт ISO 7185:1983.
Рассмотрим основные особенности языка Паскаль.
1. Паскаль является традиционным алгоритмическим языком программирования, продолжающим линию Algol-60. Это означает, что программа на языке Паскаль представляет собой специально организованную последовательность шагов по преобразованию данных, приводящих к решению некоторой задачи. Это отличает Паскаль от так называемых непроцедурных языков типа Пролог, по существу, представляющих собой формализмы для записи начальных условий некоторой задачи и синтезирующих решение посредством встроенных механизмов логического вывода.
2. Язык Паскаль содержит удобные средства для представления данных. Развитая система типов позволяет адекватно описывать данные, подлежащие обработке, и конструировать структуры данных произвольной сложности. Паскаль является типизированным языком, что означает фиксацию типов переменных при их описании, а также строгий контроль преобразований типов и контроль доступа к данным в соответствии с их типом (как на этапе компиляции, так и при исполнении программ).
3. Набор операторов языка Паскаль отражает принципы структурного программирования и позволяет записывать достаточно сложные алгоритмы в компактной и элегантной форме. Паскаль является процедурным с традиционной блочной структурой и статически определенными областями имён. Процедурный механизм сочетает в себе простоту реализации и использования и гибкие средства параметризации.
4. Синтаксис языка достаточно несложен. Программы записываются в свободном формате, что позволяет сделать их наглядными и удобными для изучения.
Turbo Pascal 7.0

Turbo Pascal - это реализация языка Паскаль фирмы Borland International для персональной IBM-совместимых ЭВМ. 
Система программирования Turbo Pascal включает в себя язык программирования и среду программирования, работающая в операционной системе MS-DOS (1992г.). 
Система Turbo Pascal довольно значительна по объёму. Она поставляется на нескольких дистрибутивных дискетах 3,5 и устанавливается на жёсткий диск. При развёртывании системы на жёстком диске обычно создаётся отдельный каталог с именем TP (или PAS, Turbo Pas, Pascal и т.д.). Для вызова Turbo Pascal необходимо отыскать в древовидной структуре каталогов ПК. Этот каталог и в нём файл с именем turbo.exe. Этот файл содержит готовую к работе диалоговую систему программирования Turbo Pascal, включающая в себя текстовый редактор, компилятор, компоновщик, загрузчик.
Всё управление средой ТР осуществляется в основном с помощью системы последовательно разворачивающихся меню. Лишь одно из них- главное меню постоянно присутствует на экране, остальные разворачиваются по мере выбора продолжений. Главное меню содержит фактически лишь оглавление дополнительных меню.
Меню опции File – действия с файлами выход из системы.
Open - открыть файл;
New – создать;
Save - сохранить
Save as - сохранить, как;
Save all - записывает содержимое всех файлов на соответствующих дисках;
Change dir - изменяет каталог;
Print - печатает содержимое активного окна;
Print setup - установка параметров принтера;
Dos shell – выход;
Exit - завершение работы.
Меню опции Edit.
Cut - удаляет выделенный блок из окна редактора и помещает в буфер;
Copy - копирует выделенный блок из окна редактора в буфер;
Paste - копирует содержимое буфера в окно редактора;
Clear - удаляет выделенный блок из окна редактора;
Меню опции Search.
Find - поиск нужного фрагмента текста;
Replace - отыскивает в окне редактора нужный фрагмент и заменяет его на новый;
Find procedure - поиск процедуры или функции;
Find error-отыскивает строку, вызвавшую ошибку.
Меню опции Run.
Run - осуществляет компиляцию, компоновку и исполнение программу из файла редактора;
Step over, trace into-отладка исполняемой программы под управлением встроенного отладчика;
Program reset - прекращает отладку;
Parameters - позволяет передавать строку параметров.
Опции Compile.
Debug - отладка программы;
Options - установка параметров среды;
Help - обращение к справочной службе.
Основные понятия языка Turbo Pascal.
Алфавит языка Паскаль содержит:
26 прописных (заглавных) букв латинского алфавита;
арабские цифры;
32 буквы русского алфавита;
специальные символы: +, -, *, /,:, ', <, >, =,.,,,;, (), [].
Алфавит содержит служебные слова.
Служебное слово – это слово, которое в языке Паскаль имеет определённое смысловое значение (иногда называют ключевым словом). Их используют только в том значении, которое заранее установлено в языке: program, var, begin, end, if, then, else, for, to, do и т.д.
Идентификатор (имя) – служит для обозначения каких либо объектов. Различают два вида идентификаторов: стандартные (integer, real, read, write, функции и т.д.), в качестве имени, определённые пользователем нельзя давать служебные слова и стандартные имена. Имя пользователя всегда начинается с буквы (состоит из букв и цифр) (в его длине 63).
Комментарии: { } или (* *) – пояснительный текст.
Оператор присваивания: <переменная>:=<выражение>.
Выражение может включать константу, переменную, функции, скобки, операции.
Целые типы.
Целые типы	Диапазон значений	Размер памяти в байтах	
Shortint	-127..127	1 	
Integer	-32768..32767	2	
Longint	-47483648..2147483647	4	
Byte	0..255	1	
Word	0..65535	2	

Вещественные типы.
Вещественные типы	Диапазон значений	Значение цифры	Размер памяти в байтах	
Real	2.9е-39…1.7е38	11-12	6	
Single	1.5е-45…3.4е38	7-8	4	
Double	5.0е-324..1.7е308	15-16	8	
Extended	3.4е-4932..1.1е4932	19-20	10	
Comp	-2e63..2e63-1	19-20	8	

Арифметические операции.
I – целый тип, R – вещественный тип.
Выражение	Тип операторов	Тип результата	Операция	
А + В	I, R	I, R	сложение	
А - В	I, R	I, R	вычитание	
А * В	I, R	I, R	умножение	
А / В	I, R	R	деление	
А div В	I, I	I	целое деление	
А mod В	I, I	I	Остаток от целого деления	

Стандартные математические функции.
Обращение	Тип аргумента	Тип результата	Функция	
abc(x)	I, R	I, R	|x|	
arctan(x)	I, R	R	arctg(x), x в радианах	
cos(x)	I, R	R	cos(x), x в радианах	
exp(x)	I, R	R	ex	
frac(x)	I, R	R	дробная часть x	
int(x)	I, R	R	целая часть x	
ln(x)	I, R	R	натуральный логарифм	
random		R	случайное число в [0,1]	
random(x)	I	I	случайное число в [0,x]	
round(x)	R	I	окружает до ближайшего целого	
sin(x)	I, R	R	sin(x), x в радианах	
sqr(x)	I, R	R	X2	
sqrt(x)	I, R	R	sqrt(x)	
trunc(x)	R	I	ближайшее целое не превышающее x по модулю	
pi		R	значение Пи	

An =exp(lna)*n – возведение в степень.

Старшинство (приоритет) операций:
Вычисление функций, унарный минус, *, /, div, mod, +, -.
Примеры записи математических выражений:

Ввод данных с клавиатуры.
Ввод данных с клавиатуры осуществляется путём обращения к стандартным процедурам.
Read (<список ввода>);
Readln (<список ввода>).
Элементы списка ввода – идентификаторы переменных вводимые значения отображаются на экране. При выполнении оператора пользователь набирает на клавиатуре соответствующую последовательность, разделяя их пробелами.
Ввод данных на экран.
Ввод данных на экран производится путём обращения к стандартным процедурам.
Write (< список ввода >)
Writeln (< список ввода >)
Элементы списка вывода – константы, переменные, выражения, форматы вывода.

Пример:
Write ( a:m:n) – вывод значения a, m – общее поле выводимого числа, включая знак числа, целую часть, точку и дробную часть, n – поле дробной части.

Структура программы на Паскале.
Program <имя программы>;
Label <раздел описания меток>;
Const <раздел описания констант>;
Type <раздел описания типов>;
Var <раздел описания переменных>;
Procedure ( function ) <описание подпрограмм>;
Begin <раздел описания операторов>;
End.
Для любой программы обязательным является лишь раздел операторов. Все программные объекты (константы, переменные, типы и пр.) должны быть описаны в соответствующих разделах описаний.

Пример: скорость первого автомобиля V1, второго – V2, расстояние между ними S км. Какое расстояние будет между ними через t2, если автомобили движутся в разные стороны.
Решение:
S1=S+(V1+V2)*t – если автомобили изначально двигались в противоположные стороны.
S2=(V1+V2)*t – S – если автомобили первоначально двигались навстречу друг другу.
Программа должна организовать ввод исходных данных, вычисление S1 и S2, вывод результата на экран. Все величины в программе: real .
Program PR1;
Var V1, V2, T, S, S1 S2: real;
Begin
write(’введи V1, V2, T, S:’);
readln(V1, V2, T, S);
S1=S + (V1+V2) * T;
S2=abs(V1+V2)*T - S);
writeln(’расстояние будет’, S1:7:4, ’км или’, S2:7:4, ’км’);
end.

Пример: вычислить (все переме5нные вещественные): (b +2 + 4ac)/2a – a3c + b-2

Управляющие конструкции языка.
Условный оператор. Краткая теория.
Условный оператор используется в тех случаях, когда вычисления (действия) могут пойти по различным путям, в зависимости от выполнения или невыполнения определенных условий, т.е. условный оператор – это средство ветвления вычислительного процесса. Структура условного оператора имеет вид: if <условие> then <оператор 1> else <оператор 2>;
Здесь if, then, else (если, тогда, иначе) – служебные слова; <условие> - произвольное логическое выражение. Если логическое выражение истинно, тогда выполняется <оператор 1>,  иначе (если логическое выражение ложно)- <оператор 2>. В качестве условий используются отношения. Отношения представляют собой записи равенств и неравенств. В общем случае отношение – это два выражения, разделенных одним из знаков =,<, >,<>,<=, =>. Если условие состоит из двух (и более) отношений соединенных между собой логическими операциями or (или), and (и), not (нет), тогда отношения заключаются в круглые скобки.
Допускается сокращенная форма условного оператора:
If  <условие> then <оператор >;
В условном операторе после then и else можно помещать по одному оператору. Однако часто необходимо в зависимости от результата проверки выполнить ту или иную группу операторов, тогда составной оператор заключается в операторные скобки: Begin <оператор> end.
Ключевые примеры программ для самостоятельного разбора:
Пример 1. Программа нахождения максимального из двух чисел.
Var a, b, max: real;
Begin read (a, b);
If a>b then max: =a, else max: =b;
Writeln (‘max= ’, max);
End.
Пример 2. Программа нахождения максимального из трех чисел.
Var a, b, с, max: real;
Begin read (a, b, c);
If a>b then max: =a, else max: =b;
If max<c then max: =c;
Writeln (‘max= ’, max);
End.
Пример 3. Программа решения квадратного уравнения.
Var a, b, с, d: real;
Begin read (a, b, c);
d: =b*b-4*a*c;
If d<0 then(‘корней нет’) else
If d=0 then Writeln (‘x= ’, -b/(2*a))
Else 
Begin
d: =sqrt (d);
a: =2*a;
Writeln (‘x1= ’, (-b+d)/a);
Writeln (‘x2= ’, (-b-d)/a);
End;
End.
Задачи для самостоятельного решения:
1. Пусть даны два числа. Если первое число больше второго по абсолютной величине, то необходимо уменьшить первое в пять раз. Иначе оставить числа без изменения. Составить программу.
2. Написать программу нахождения наибольшего из четырех чисел.
3. Написать программу полного исследования совокупности корней биквадратного уравнения. Если корней нет, то должно быть выведено сообщение об этом, иначе должны быть выведены два или четыре корня.

Оператор выбора.
Краткая теория.
Оператор выбора (варианта) используется в тех случаях, когда в зависимости от значения какого-либо выражения необходимо выполнить один из нескольких последовательных операторов. Оператор выбора относится к сложным и имеет следующую форму записи:
Case <выражение > of
<константа 1>: <оператор 1>;
<константа 2>: <оператор 2>;
…………………………………
<константа n>: <оператор n>;
Else <оператор >;
End;
Здесь Case (в случае), of (из), else (иначе), end (конец)- служебные слова. Оператор выбора действует следующим образом. Если значение выражения равно одной из констант, то выполняется соответствующий ей оператор. Затем управление передается за пределы оператора выбора. Если значение выражения не совпадает ни с одной константой, то управление передается оператору, стоящему за словом else. Выражение может быть любым стандартным типом кроме Real и String. Тип константы должен совпадать с типом выражения.
Программы для самостоятельного разбора:
Пример 1. Ввести номер недели и вывести соответствующий ему день недели.
Var n: integer;
Begin введите номер дня недели ’); readln (n);
Case n of
1: Writeln (‘понедельник’);
2: Writeln (‘вторник’);
3: Writeln (‘среда’);
4: Writeln (‘четверг’);
5: Writeln (‘пятница’);
6: Writeln (‘суббота’);
7: Writeln (‘воскресенье’);
Else Writeln (‘ошибка ввода’);
End;
End.
Пример 2. Программа имитации работы микрокалькулятора. Ввести два числа и один из знаков +,-, *, /. Вывести на экран результат соответствующего арифметического действия.
Var operation: char;
X, y, z: real;
Begin Writeln (‘x, y= ’); readln (x, y);
(‘операция’); readln (operation);
Case operation of
‘+’: z: =x+y;
‘-’: z: =x-y;
‘*’: z: =x*y;
‘/’: z: =x/y;
Else Writeln (‘ошибка ввода’);
End;
Writeln (‘z= ’, z);
End.

Метки и операторы перехода.
Краткая теория.
В языке Паскаль принят естественный порядок выполнения программы: все операторы выполняются последовательно один за другим в том порядке, как они записаны. Однако в практике программирования возникает необходимость нарушения последовательности выполнения операторов. Например, необходимо обойти участок программы, который имеет следующую форму записи:
Goto <метка>. Здесь Goto (перейти [на метку]) - зарезервированное слово. Метка в Турбо Паскале – это произвольный идентификатор, однако в целях совместимости со стандартным языком допускается в качестве меток использовать целые числа без знака. Метка располагается непосредственно перед помечаемым оператором и отделяется от него двоеточием. Метка должна быть объявлена  в разделе описаний с помощью зарезервированного слова –Label (метка). Объявление метки имеет вид: Label <метка1>, <метка2>…<метка n>;
Пример. Проверить имеются ли среди чисел cos(I3)*sin(I*n), I=1,...,n,
Меньше 0,0001. Если имеются, то вывести «есть», если нет  «нет».
Label a1, a2;
Var I, n: integer;
Begin read (n);
For I: =1 to n do
If cos (I*I*I)*sin (I*n)<0.0001 then goto a1;
Write (‘нет’); goto a2;
A1: Write (‘есть’);
А2: end.
Задачи для самостоятельного решения:
1. Написать программу, в результате выполнения которой выясняется, есть или нет среди 70 данных целых чисел точных квадратов. Если есть, то должно быть выведено одно из таких чисел, если нет, то должен быть выведен текст «квадратов нет».
2. Написать программу, в результате выполнения которой выясняется, есть ли среди чисел I3-17*I*n2+n3 (I=1,..,n) хотя бы одно число, кратное а и не кратное b.
3. Получить первое простое число, больше данного числа n.

Организация циклических процессов.
Краткая теория
При многих задач вычислительный процесс имеет циклический характер. Это означает, что часть операторов многократно выполняется при различных значениях переменных. Применение циклов в программе позволяет эффективно использовать ресурс машины, приводит к сокращению длины программы и сокращению времени на ее составление и отладку.
В языке Паскаль имеется три вида операторов цикла: 
1. оператор цикла с параме6тром; 
2. оператор с предварительным условием (предусловием); 
3. оператор цикла с последующим условием (постусловием).

Оператор цикла с параметром.
Оператор цикла с параметром используется в тех случаях, когда заранее известно, сколько раз должна повторится циклическая часть программы. Оператор цикла имеет вид: for i:=m1 to m2 do <оператор>;
Здесь for (для), to (до), do (выполнить) – служебные слова; i – некоторая переменная типа integer, которая называется параметром цикла; m1, m2 – начальные и конечные значения параметров цикла. Указанный оператор выполняется повторно для каждого значения параметра цикла i от его начального значения m1 до конечного значения m2 включительно с шагом +1. в качестве m1 и m2 могут быть выражения типа integer. Если параметр цикла уменьшается, то шаг его изменения –1 и в операторе цикла вместо служебного слова to записывается служебное слово downto. Вид оператора: for i:=m1 downto; m2 do <оператор>; 
Если в качестве оператора используется не один оператор, а несколько, другими словами, составной оператор, операторы циклической части заключаются операторные скобки.
For i:=m1 to m2 do
Begin
<Оператор 1>;
<Оператор 2>;
………………..
End;
Циклы могут быть вложены один в другой. При использовании вложенных циклов необходимо составлять программу таким образом, чтобы внутренний цикл полностью укладывался в циклическую часть внешнего цикла. Внутренний цикл в свою очередь может содержать другой внутренний цикл (циклы).
Ключевые примеры программ для  самостоятельного разбора.

Пример1. Вычислить n!
Var n, i, p:integer;  
Begin read(n); p:=1;
For i:=1 to n do p:=p*i;
Write(‘n!=’,p);
End.

Пример 2. Другой вариант программы вычисления факториала.
Var n, i, p:integer;  
Begin read(n); p:=1;
For i:=n downto 2 do p:=p*i;
Write(‘n!=’,p);
End.

Пример 3. Написать программу вычисления an.
Var i, n, a: integer;
Begin read(a,n);
For i:=1 to n do 
Begin
A:=a*a;
Write(‘a v stepeni n=’,a);
End;
End.

Пример 4. Написать программу получения всех совершенных чисел из диапазона от 1 до n (натуральное число называется совершенным, если оно равно сумме своих делителей, исключая самого себе, например: 6=1+2+3).
Var n, i, j, m: integer;
Begin read(n);
For i:=2 to n do
Begin m:=0;
For j:=1 to i-1 do
If I mod j = 0 then m:=m+j;
If m=i then writeln(i);
End;
End.

Оператор цикла с предварительным условием.
Цикл с предварительным условием (с предусловием) используется, как правило, в тех случаях, когда неизвестно число повторений цикла. Форма записи оператора цикла с предусловием:
While <логическое выражение> do
Begin
Оператор 1;
Оператор 2;
………….
End;

Здесь while (пока) и do (выполнить) – служебные слова. Если оператор один, то операторные скобки можно опустить. Вложенные циклы организуются аналогично циклам с параметрами. 

Ключевые примеры программ для  самостоятельного разбора.

Пример 1. Для двух данных чисел a, b (a>1) получить все члены бесконечной последовательности a, a2,a3,a4…, меньших числа b.
Var a, b, c:real;
Begin read(a,b); c:=a;
While c<b do
Begin
Writeln(c); c:=c*a;
End;
End.

Пример 2. Программа вычисления n!
Var n, i, p:integer;  
Begin read(n); p:=1; i:=0;
While i<n do
Begin i:=i+1; p:=p*i;
End;
Writeln(‘n!=’,p);
End.
 
Пример 3. Программа вычисления суммы 1+1/2+1/3+…+1/n.
Var n, i:integer;  
S:real;
Begin read(n); s:=1; i:=0;
While i<n do
Begin i:=i+1; s:=s+1/i;
End;
Write(s);
End.

Пример 4. Приближенно вычислить сумму 1+x/1!+x2/2!+x3/3!+… При суммировании учитывать только слагаемые, большие по абсолютной величине данного положительного числа e.

Var x, eps, i, y, s:real;  
Begin read(x,eps); 
s:=0; y:=1; i:=0;
While abs(y)>eps do
Begin s:=s+y; i:=i+1; 
Y:=y*x/i;
End;
Write(s);
End.

ОПЕРАТОР ЦИКЛА С ПОСЛЕДУЮЩИМ УСЛОВИЕМ
Цикл с последующим условием, как правило, используется в тех случаях, когда заранее неизвестно число повторений цикла. Оператор цикла имеет следующий вид:
Repeat
Оператор 1;
Оператор 2;
……..……..
until <логическое выражение>
Здесь repeat (повторить) и until (до тех пор) – служебные слова. Операторы циклической части выполняются повторно (по крайней мере один раз) до тех пор, пока значение логического выражения ложно. Условием прекращения циклических выражений является истинное значение логического выражения. Нижняя граница операторов циклической части четко обозначена словом until, поэтому нет необходимости заключить операторы циклической части в скобки вида begin – end. В тоже время и дополнительное наличие операторных скобок не является ошибкой.
Пример 1. Вычислить значение функции y=x2 при x=8, 6, 4, 2.
Var x, y:real;
Begin
X:=8;
Repeat
Y:=x*x;
Writeln(‘x=’,x,’y=’,y);
X:=x-2
Until x<0
End.

Задачи для самостоятельного решения.
Написать программу вычисления значений:
а) 1/1*2+1/2*3+…+1/(n-1), n>=2;
б) 1-1/2+…+(-1)n/n;
Написать программу получения в порядке убывания всех делителей данного числа.
Написать программы приближенного вычисления значений привиденных в задании 1. При суммировании учитывать только те слагаемые, большие по абсолютной величине данного положительного числа e.
Замечание. При решении задач использовать различные операторы цикла. Желательно привести два (три) варианта решения задач.
Данные логического типа
Краткая теория
В языке Паскаль имеются две логические константы: true (истина) и false (ложь). Логическая переменная принимает одно из этих значений и имеет тип Boolean. Логические данные (высказывания) широко используются при проверке правильности некоторых условий и при сравнении величин. Результат может оказаться «истинным» или «ложным». Для сравнения предусмотрены следующие операции отношений: <,>,=,=>,<=,<>. Из простых  высказываний в Паскале разрешается строить более сложные. Допускаются следующие операции над высказываниями: and(и), or(или), not(не), которые называются соответственно конъюнкцией, дизъюнкцией и отрицанием. 
Логические операции над данными типа Boolean
Операнд1	Операнд2	and	or	not	
false	false	false	false		
false	true	false	true		
true	false	false	true		
true	true	true	true		
false				true	
true				false	

При определении истинности высказываний, построенных из отношений с помощью знаков логических операций и круглых скобок, действуют следующие правила старшинства операций: самая старшая операция- отрицание, следующая - конъюнкция, потом - дизъюнкция. Первой из двух операций одного старшинства выполняется та, знак которой в выражении встречается раньше. Круглые скобки изменяют этот естественный порядок.
Пример1. Рассмотрим программу, в которой выясняется, принадлежит ли число x отрезку [a,b]. 
var x,a,b:real;
begin read(x,a,b);
If (x>=a) and (x<=b) then write(‘принадлежит’)
else write(‘не принадлежит’);
end.
Задача для самостоятельного решения.
Написать программу вычисления значения функции y=x, если x>=1 или x<=2, y=x2+2x-2 в остальных случаях.
Тип char
Краткая теория
До сих пор рассматривались исключительно программы, предназначенные для обработки числовых данных. Обработка символьных  данных становится возможной благодаря привлечению переменных типа char. Значениями типа char служат отдельные символы- все те символы, которые могут быть восприняты вычислительной машиной и напечатаны ею на бумаге или высвечены на экране. К этим символам обязательно должны относиться те, которые используются в текстах программ на Паскале: буквы, цифры, знаки операций, скобки и т.д. Если в программе имеется описание: u,v:char; то возможны, например операторы присваивания u:=’a’, v:=u, v:=’*’  и т. д. Апостроф употребляется, когда значение типа char явно указывается в программе. При выполнении оператора вывода апостроф не высвечивается. Выполнение операторов u:=’b’; write(u) приводит к печати или высвечиванию символа b. После служебных слов if, while и др. могут использоваться отношения <,>,=,<>,<=,=>, так как всё множество символов считается упорядоченным. Предполагается, что эта упорядоченность получается так: из всех символов составлен список, и из двух символов меньше тот, который встречается в списке раньше. Латинские буквы идут друг за другом, не перемешиваясь с другими символами, в алфавитном порядке и арабские цифры идут друг за другом, как обычно. Например, ‘a’<’c’, ’3’>’1’. В остальном вопрос порядка решается по- разному на разных компьютерах и версиях языка Паскаль. Упорядоченность открывает возможность использования в программах операторов цикла с параметром.
Примеры программ использования типов char
Пример1. Программа замены всех восклицательных знаков точками до первого символа /.
var c:char;
begin read(c);
while c<>’/’ do
begin if c=’!’ then write(‘.’)
           else write(c);
read(c);
end;
end.
Пример2. Программа вывода последовательно букв латинского алфавита.
var c:char;
begin
for c:=’a’ to ‘z’ do
writeln(c);
end.
Перечисляемый тип данных
Краткая теория
  Перечисляемый тип данных называется так потому, что задается в виде перечисления в строго определенном порядке и в строго ограниченном количестве всех значений, которые могут принимать данные рассматриваемого типа. Перечисляемый тип может быть задан пользователем в зависимости от того, какую задачу он решает. Перечисляемый тип состоит из списка констант. Переменные этого типа могут принимать любые значения  этих констант. Описание перечисляемого типа имеет вид:
type <имя типа>=(список констант);
var <имя переменной>:<имя типа>;
   Здесь под константой понимается  особый вид констант, задаваемых пользователем. Под списком понимается перечень констант, разделенных запятыми. Сам список заключается в круглые скобки.
Пример описания перечисляемого типа :
type god=(зима, весна, лето, осень);
var a:god;
Здесь god- имя перечисляемого типа; зима, весна, лето, осень - константы; а - переменная, которая может принимать значения любой из констант. В языке допускается  указывать константы перечисляемого типа непосредственно в разделе описаний переменных без использования  раздела type, например: var a:(зима, весна, лето, осень);
Каждая из констант имеет порядковый номер, счет начинается от нуля. Упорядоченность констант позволяет применить к ним операции отношения <,<=,<>,=,>=,>, а также стандартные функции ord, pred, succ.
ord(x)- находит порядковый номер элемента x;
pred(x)- нахождение элемента, являющегося предыдущим элементу x;
succ(x)- нахождение элемента, являющегося следующим за x.
Пример. Имеется перечень зверей. Определить в этом списке порядковый номер тигра и порядковый номер зверя после косули.
type zver=(лиса, волк, тигр, заяц, косуля, медведь, барс);
var p1,p2:zver;
      n1,n2;integer;
begin
p1:=тигр;
p2:=succ(косуля); {нахождение элемента, являющегося следующим за указанным}
n1:=ord(p1)+1;{находит порядковый номер, прибавляет 1, так как}
writeln(n1,n2);
end.
Множества в языке Паскаль
Краткая теория
Под множеством в языке Паскаль понимается ограниченный, неупорядоченный набор элементов одинакового типа. Всему множеству в целом дается имя. Тип элементов, входящих в множество, называется базовым. В качестве базового типа можно использовать простые типы: стандартный, кроме real, перечисляемый и ограниченный. Множества должны быть объявлены либо в разделе описания переменных, либо с использованием раздела типов type.
Объявление множества в разделе переменных имеет вид:
type <имя множества>=set of <базовый тип>;
 Объявление множества с использованием разделов типов имеет вид:
type <имя типа>= set of <базовый тип>;
var <имя множества>: <имя типа>;
Значение переменных и констант множества задаются в разделе операторов с помощью конструктора. Конструктор представляет собой список элементов базового типа, заключенный в квадратные скобки.
В языке Паскаль имеются следующие операции над множествами:
объединение множеств C:=A+B; пересечение множеств C:=A*B; вычитание(разность) множеств C:=A-B;=,<> проверка множеств на равенство; <=,>= проверка множеств на включение; in проверка на принадлежность множеству.
Пример1. Имеются три множества символьного типа, которые заданы своими конструкторами: y1=[‘a’,’b’,’r’,’m’], y2=[‘r’,’a’,’d’], y3=[‘a’,’r’].
Сформировать новое множество x=(y1*y2)+(y1-y2). Проверить включено ли множество y3 и x.
var y1,y2,y3,x:set of char;
      c;char;
begin
y1:=[‘a’,’b’,’r’,’m’];
y2:=[‘r’,’a’,’d’];
y3:=[‘a’,’r’];
{формировать и печатать множества x}
x:=(y1*y2)+(y1-y2);
write(‘множество x=’);
for c:=’a’ to ‘r’ do
if c in x then write(c);
{проверка включения множества y3 в x}
if y3<=x
then write(‘y3 включено в x’)
else write(‘не включено в x’);
end.
Пример2. Из множества целых чисел 1..20 выделить: множество чисел, делящихся на 6; множество чисел, делящихся или на 2. или на 3(деление нацело).
Const n=20;
Var n2,n3,n6,n23:set of integer;
                         K:integer;
begin n2:=[];n3=[];
        for k:=1 to n do
begin
if k mod 2=0 then n2:=n2+[k];
if k mod 3=0 then n3:=n3+[k]
end;
n6:=n2*n3;
n23:=n2+n3;
writeln(‘на 6 делятся числа’);
for k:=1 to n do
if k in n6 then write(k);
writeln(‘на 2 или на 3 делятся’);
for k:=1 to n do
if k in n23 then write(k);
end.
СТРОКОВЫЕ ПЕРЕМЕННЫЕ И ВЕЛЕЧИНЫ
Одним из основных направлений использования ЭВМ является накопление и обработка таблиц, справочников, словарей, где кроме числовых данных используется и текст.
В Pascal для описания строковых переменных используется string. Он во многом похож на одномерный массив array[0..n]of char, однако, в отличии от последнего, количество символов в строке-переменной может меняться от 0 до 255. Значение n определяется объявлением типа string[n]. Turbo Pascal разрешает не указывать n, в этом случае длина строки принимается максимально возможной, а именно n=255.
Строковые значения заключаются в апостроф, например: ‘tuRbo’.
Для обозначения строковых переменных используется до 8 символов, первый символ обязательно должен быть латинской буквой, а другие – латинскими буквами или цифрами. Пример присваивания строковой переменной a величины ‘pascal’: a:=‘pascal’.
Операции отношения =, <,>,<=,>=,<> выполняется над двумя строками посимвольно, слева направо с учетом внутрееней кодировки символов.
Основные функции и процедуры над строковыми величинами.
Пример 1. Сцепление, склеивание или соединение двух строковых величин.
Var a,b,c:string;
Begin
A:=’pas’;
B:=’cal’;
C:=a+b;
Write(c);
end.
На экране: pascal.
Пример 2. функция типа integer – length(a) – вычисляет длину строковой величины.
Var a:string;
X:integer;
Begin
A:=’pascal’;
X:=length(a);
Write(x);
End.
Ответ:6.
Пример 3. функция типа string – copy(a,x,y) – m позволяет вырезать из строки символов а, строку символов у, начиная с х позиции.
Var a,b:string;
Begin
A:=’pascal’;
B:=copy(a,2,3);
Write(b);
End.
На экране: asc.
Пример 4. процедура delete(st,x,y) удаляет из строки символов st строку символову, начиная с х позиции.
Var a,b:string;
Begin
A:=’turbo turbo pascal’;
B:=delete(a,1,6) ;
Write(b);
End.
Пример 5. Процедура insert(su,st,x) вставляет подстроку su в st начиная с х позиции.
Var a,b,c:string;
Begin
A:=’pascal’;
B:=’turbo’;
C:=insert(b,a,1);
Write(c);
End.
Пример 6. функция типа string – concat(a,b,c) возвращает строку, представляющую собой сцепление (соединение) a,b,c.
Var a,b,c,d:string;
Begin
A:=’turbo’;
B:=’pascal’;
C:=’urok’;
D:=concat(a,b,c);
Write(d);
End.
На экране:L turbo pascal urok.
Пример 7. функция типа integer – pos(a,b) – отыскивает в строке а первое вхождение подстроки b и возвращает номер позиции, с которй она начинается, если подстрока не найдена, возвращает ноль.
Var a,b:string;
C:word;
Begin
A:=’turbo pascal’;
B:=’pascal’;
C:=pos(a,b);
Write(c);
End.
Ответ: 7.
Пример 8. процедура str(x[:a[:b]],st) – преобразует число x( real или integer) в строку символов st; параметр а определяет общую ширину поля, выделяемого под символьное представление числа x; b – количество символов в дробной части, если х – real.
Var a,b:string;
X:real;
Begin
Write(‘введи число’);
Readln(x) ;
A:=str(x:10:3,a);
Write(a);
End.
Пример 9. Процедура val(st,x,code) преобразует стоку символов st в числовую переменную x; параметр code содержит 0, если преобразование прошло успешно и номер позиции st, где обнаружен ошибочный символ.
Var x:string;
B:word;
Y:real;
Begin 
Writeln(‘введи число’);
Readln(x);
Y:=val(y,x,b);
Write(y);
End.
Задачи со строковыми величинами и переменными.
Задача 1. Составить всевозможные слова путем вырезки и склеивания из слова «informatika».
Var y,a,b,c:string;
Begin 
Y:=’informatika’;
A:=copy(y,3,5);
B:=copy(y,3,2)+y[8]+copy(y,10,2);
C:=y[2]+y[4]+y[8]+y[7];
Writeln(a);
Writeln(b);
Writeln(c);
End.
Задача 2. написать программу подсчета числа вхождений буквы а в данный текст.
Var i,k:integer;
Y:string;
Begin
Write(‘введи строку’);
Readln(y);
K:=0;
For i:=1 to length(y) do
If y[i]=’a’ then y[i]:=’b’;
C:=c+y[i];
End;
Writeln(c);
end.
Задача 3. Составить программу замены в слове всех букв “а” на “б” и наоборот.
        Var I:integer;
 Y,c:string;
Begin
Writeln(‘vvedi stroku’);
Readln(y);
For I:=1 to length(y) do 
Begin 
If y[I]=’a’ then y[I]:=’b’
Else
If y[I]=’b’ then y[I]:=’a’;
C:=c+y[I];
End;
Writeln(c) ;
End.
Задача 5. написать программу подсчета вхождений слова х в у ( например: kolokol,kol).
Var I,xd,yd,k:integer;
X,y:string;
Begin
Writeln(‘vvedi slovo 1’);readln(x);
Writeln(‘vvedi slovo 2’);readln(y);
Xd:=length(x);yd:=length(y);
K:=0;
For I:=1 to xd do
If copy(x,I,yd)=y then k:=k+1;
Writeln(‘k=’,k);
End.
Задача 6. написать программу обращения слова.
Var I:integer;
Y,c:string;
Begin
Write(‘vvedi slovo’);read(y);
C:=’ ’;
For I:=1 downto 1 do
C:=c+y[I];
Writeln(c);
End.
Задача 7. написать программу проверки, является ли данное слово перевертышем.
Var I:integer;
Y,c:string;
Begin
Writeln(‘vvedi slovo’);readln(y);
For I:=length(y) downto 1 do
C:=c+y[I];
If c=y then writeln(‘перевертыш’);
End.
Задача 8. предложение состоит из слов, которые разделены одним пробелом. Определите число слов в предложении.
Var I,k:integer;
Y:string;
Begin
Writeln(‘vvedi text’);readln(y);
K:=1;
For I:=1 to length(y) do
If y[I]=’ ‘ then k:=k+1;
Writeln(k);
End.
Задачи для самостоятельного решения.
Составить с помощью вырезки и склеивания из слова “математика”.
Даны два слова. Сколько раз во втором слове встречается первая буква первого слова.
Контрольный пример:
Данные: ”буква”, ”бабочка”. Ответ:2.
Данные: ”буква”, ”звук”. Ответ:0.
Даны два слова одинаковой длины. Присвоить переменной к число равное количеству попарно одинаковых букв.
Контрольный пример: “Черепашка”, ”бегемошка”.     
Массивы.
Под массивом понимается совокупность конечного числа данных одного типа. Массив обозначается одним именем. Так, например совокупность чисел: 1,45,5,4,8,9 можно считать массивом и обозначить одним именем B. 
Каждый элемент массива обозначается именем массива с индексом. Для рассмотренного примера элементами массива B являются: B[1]=1,B[2]=45,B3]=5,B[4]=4,B[5]=8,B[6]=9.
Если в программе используется массив, то он должен быть описан либо в разделе переменных var, либо в разделе типов type.Форма описания для var имеет вид:
var имя массива:araray[1..n] of integer;
Именем массива может быть любая буква латинского алфавита или комбинация букв или символов, но первой должна быть буква. В квадратных скобках n указывает количество элементов массива. Of integer – указавает тип элементов массива .
      В языке PASCAL помимо явного описания массивов в разделе переменных имеется другая форма описания, состоящая из двух этапов. Форма объявления массива имеет вид: 
  type <имя типа>=array[1..n] of real;
  var имя массива: имя типа;
Имя массива и имя типа пользователь задает сам. Массивы, где каждому элементу массива соответствует один индекс называется одномерным.
Кроме этого массивы могут быть двумерными. Например, элементами двумерного массива может быть следующая таблица:
4.5  6.9  6
5.5  1.3  5   3.7
4     7   3.8  7.6
   Данный двумерный массив состоит из 3 строк и 4 столбцов. Каждый элемент обозначается 2 индексами, например a[I,j], где I –номер строки, j –номер столбца. В нашем случае a[1,2]=4.5, a[2,3]=3.7.
 Примеры описания двумерного массива :
type t=array[1..3,1..4] of real;
var a:t;
Здесь указывается тип t двумерного массива a, состоящий из 3 строк и 4 столбцов. Ниже приведена другая форма описания:
var a:array[1..3,1..4] of real;
 Элементами массива могут быть переменные типов: integer,real,char,string.
 Тип char – значениями данного типа являются символы, которые могут быть восприняты ЭВМ и напечатаны ею на бумаге или высвечены на экране.
К символьным переменным применимы отношения:>,<,<=,>=,<>. 
Программы по вводу и выводу массивов.
1.Программа ввода и вывода одномерного массива с клавиатуры.
   type massiv=array[1..6] of integer;
  var a:massiv;
I:integer;
  begin 
     for I:=1 to 6 do
   readln(a[I]);
 for I:=1 to 6 do
 writeln(‘a[‘,I,’]=’,a[I]);
end.
2. Программа ввода и вывода двумерного массива с клвиатуры.
  var s:array[1..4,1..6] of char;
  I,j:integer;
 begin
   fof I:=1 to 4 do
   fof j:=1 to 6 do
 readln(s[I,j]);
for I:=1 to 4 do
for j:=1 to 6 do
writeln(‘s[‘,I,’,’,j,’]=’,s[I,j]);
end.
3. Программа ввода и вывода символьного массива с клавиатуры. 
  var s:array[1..4] of char;
  I:integer;
  begin
  for I:=1 to 4 do 
writeln(‘s[‘,I,’]=’,s[I]);
end.
4. Программа ввода элементов массива с использованием генератора случайных чисел.
  type massiv=array[1..2,1..3] of integer;
  var a:massiv;
I,j:integer;
begin
   for I:=1 to 2do
   for j:=1 to 3 do
a[I,j]:=trunc(random(100));
 for I:=1 to 2do
 for j:=1 to 3 do
writeln(‘a[‘,I,’;’,j,’]=’,a[I,j]);
end.
5. Программа ввода значений массива , записанных в тексте программы.
 var a:array[1..4] of string;
I:integer;
begin
 a[1]:=’koli’;
 a[2]:=’oli’;
a[3]:=’kati’;
a[4]:=’lena’;
for I:=1 to 4 do
writeln(‘a[‘,I,’]=’,a[I]);
end.
6. Программа расчета элементов массива по формуле.
 var a:array[1..9,1..9] of integer;
  I,j:integer;
begin
  for I:=1 to 9 d0
  for j:=1 to 9 d0
begin
 a[I,j]:=I*j;
writeln(‘a[‘,I,’;’,j,’]=’,a[I,j]);
end;
end.
Задачи на обработку массивов.
Вычислить сумму элементов двумерного массива, элементы которого задаются генератором случайных чисел.
type massiv=array[1..2,1..3] of integer;
var a:massiv; 
I,j,s:integer;
begin
s:=0; 
     for I:=1 to 2 do
     for j:=1 to 3 do
begin
a[I,j]:=trunc(random(100));
s:=s+a[I,j];
end;
for I:=1 to 2 do
     for j:=1 to 3 do
writeln(‘a[‘,I,’;’,j,’]=’, a[I,j]);
writeln(‘s=’,s);
end.
2) Вычислить произведение элементов двумерного массива, элементы которого задаются генератором случайных чисел.
type massiv=array[1..2,1..3]of integer;
var a:massiv;
I,j,p:integer;
begin
p:=1;
for I:=1 to 2 do
for j:=1 to 3 do
begin
a[I,j]:=trunc(random(100)+1);
p:=p*a[I,j];
end;
for I:=1 to 2 do
for j:=1 to 3 do
writeln(‘a[‘,I,’;’,j,’]=’, a[I,j]);
writeln(‘p=’,p);
end.
Подсчёт количества элементов превосходящих p.
type massiv=array[1..2,1..3]of integer;
var a:massiv;
I,j,p,k:integer;
begin
write(‘vvedi p’);
readln(p);
for I:=1 to 2 do
for j:=1 to 3 do
begin
a[I,j]:=trunc(random(100)+1);
if a[I,j]>p then k:=k+1;
end;
for I:=1 to 2 do
for j:=1 to 3 do
writeln(‘a[‘,I,’;’,j,’]=’, a[I,j]);
writeln(‘k=’,k);
end.
Задан одномерный массив из 9 элементов. Сформировать из него двумерный массив 3х3.
type mas1=array[1..9] of integer;
        mas2=array[1..3,1..3] of integer;
var a:mas1;
      b:mas2;
I,j,k:integer;
begin
for I:=1 to 9 do
read(a[I]);
k:=0;
for I:=1 to 3 do
for j:=1 to 3 do
begin
k:=k+1;
b[I,j]:=a[k];
writeln(‘b[‘,I,’;’,j,’]=’, b[I,j]);
end;
end.
Найти минимальный элемент массива.
const n=5;
type vec=array[1..n] of integer;
var a:vec;
I,min:integer;
begin
randomize;
for I:= 1 to n do
begin
a[I]:=trunc(random*100);
writeln(‘a[‘,I,’]=’,a[I];
end;
min:=a[1];
for I:=2 to n do
if a[I]<min then min:=a[I];
writeln(‘min=’,min);
end.

                 Задачи для самостоятельного решения

Задача1. Найти сумму элементов в каждой строке двумерного массива. 
Задача 2. В заданном массиве подсчитать количество положительных элементов.
Задача 3. Поиск максимального элемента в заданном массиве.
Задача 4. В заданном одномерном массиве поменять местами элементы, стоящие на четных местах с нечётными.
Процедуры и функции.
					Процедуры.
	В практике программирования часто приходиться производить одни и те же вычисления, но при различных исходных данных. Чтобы исключить повторение одинаковых записей, повторяющиеся вычисления оформляются в
самостоятельную часть программы. Такая автономная часть программы, реализующая определенный алгоритм и допускающая многократное обращение к ней из различных частей общей программы, называется подпрограммой.
	В языке Паскаль выделяют два вида подпрограмм: процедуру (procedure) и функцию (function). Любая программа может содержать несколько процедур и несколько функций. Процедуры и функции объявляются и записываются в разделе описания вслед за разделом переменных. Подпрограмма оформляется подобно основной программе, т. е. состоит из заголовка, раздела описаний и раздела операторов. Выполнение программы начинается с операторов основной программы. При необходимости вызывается подпрограмма и начинают действовать ее операторы. После выполнения подпрограммы управление вновь передается в основную программу, которая продолжает выполнятся.

			        С                           B

			       A			        D

	Диагональ делит четырехугольник на два треугольника, площади которых можно вычислить с помощью формулы Герона.
	S:=SQRT(p*(p-a)*(p-b)*(p-c)), где a, b, c – длины сторон треугольника, p:=(a+b+c)/2. простейшее решение – дважды записать в программе операторы, задающие вычисления по формуле. Однако можно избежать этого повторения, если воспользоваться подпрограммой – процедурой.
	Напишем вариант программы:
	VAR AB, BC, CD, DA, AC, S1, S, A, B, C, P:REAL;
	    PROCEDURE STR1;
		BEGIN P:=(A+B+C)/2;
		 S:=SQRT(P*(P-A)*(P-B)*(P-C));
		END;
	BEGIN READ(AB, BC, CD, DA, AC);
	  A:=AB; B:=BC; C:=AC; S:=STR1(a, b, c); S:=STR1;
	  A:=DA; B:=AC; C:=CD; S1:=STR1;
	WRITE(S1+S);
	END.
	В программе – два обращения к процедуре STR1. Связь процедуры с остальными операторами программы осуществляется через переменные a, b, c, s; в процедуре имеется еще переменная р, которая является вспомогательной внутри процедуры. Паскалем разрешается включать в описание процедуры совокупность описаний переменных. Тогда процедуру можно оформить следующим образом:
	PROCEDURE STR1;
	  VAR P:=REAL;
	    BEGIN P:=(A+B+C)/2;
		S:=SQRT(P*(P-A)*(P-B)*(P-C));
	  END;
	Теперь из раздела описаний переменных основной программы можно удалить переменную р.
	Продемонстрированный способ использования процедур неудобен из-за большого числа операторов присваивания, которые до обращения к процедуре определяют значения переменных a, b, c. Есть другой способ – описать процедуру с параметрами (аргументами), что позволит обращаться к процедуре:
	PROCEDURE STR1(VAR A, B, C, S:REAL);
	  VAR P:REAL;
	   BEGIN P:=(A+B+C)/2;
	   S:=SQRT(P*(P-A)*(P-B)*(P-C));
	  END;
	Указанные в скобках после имени процедуры параметры a, b, c, s – это формальные параметры, при выполнении программы в момент обращения к процедуре они заменяются фактическими параметрами: первый формальный параметр – первым фактическим параметром, второй формальный параметр – вторым фактическим и т. д. Типы формальных и фактических переменных должны соответствовать. Формальные параметры не описываются в основной программе. Обращение к процедуре:
	STR1(AB, BC, AC, S1); Новый вариант программы:

	VAR AB, BC, CD, DA, AC, S1, S2:REAL;
	  PROCEDURE STR1(VAR A, B, C, S:REAL);
		VAR P:REAL;
		BEGIN P:=(A+B+C)/2;
		S:=SQRT(P*(P-A)*(P-B)*(P-C));
		END;
	  BEGIN READ(AB, BC, CD, DA, AC);
		STR1(AB, BC, AC, S1);
		STR1(CD, DA, AC, S2);
		WRITE(S1+S2);
	END.
	Заголовок процедуры может быть устроен так, что некоторые группы формальных параметров не содержат слова VAR. Например:
	PROCEDURE STR1(A, B, C:REAL; VAR S:REAL);
	Формальные параметры, которые входят в группы, не содержащие слова VAR, называются формальными параметрами – значениями. A, B, C – это формальные параметры – значения, а S – это формальный параметр – переменная.
	Параметры – значения выполняют роль входных параметров процедуры. Они могут получать значения фактических параметров, но не могут передавать свои значения фактическим параметрам. Параметры – переменные выполняют роль как входных, так и выходных параметров процедуры. Они могут получать значения фактических параметров, изменять их в процедуре и возвращать новые значения фактическим параметрам. Для выделения параметров – переменных перед ними ставиться слово VAR в формальных параметрах.
	Пример. Оформить в виде процедуры SUMMA вычисление суммы 1+2+3+…+N и произведения 1*2*3*…*N целых чисел.
VAR N:INTEGER;
	SUM? PR:REAL;
PROCEDURE SUMMA (K:INTEGER; VAR X, Y:REAL);
	VAR I:INTEGER;
	BEGIN X:=0; Y:=1;
		FOR I:=0 TO K DO
		BEGIN
		X:=X+I;
		Y:=Y+I;
		END;
	END;
BEGIN
	WRITE(‘ВВЕДИ N’);
	READ(N);
	SUMMA(N, SUM, PR);
	WRITELN(‘SUM=’, SUM);
WRITELN(‘PR=’, PR);
END.

					Функции.
	Другой вид подпрограмм – функция – оформляется аналогично процедуре. Отличительные особенности функции: она имеет только один результат выполнения, но может иметь несколько входных параметров; результат обозначается именем функции и передается в основную программу. Обращение к функции приводит к вычислению ее значения – объекта типа: REAL, INTEGER, LONGINT, CHAR. Тип функции фиксируется в описании функции. Вызывается функция по ее имени с указанием фактических параметров. Вызов функции можно делать непосредственно внутри выражения.
	Функция оформляется в следующем виде:
Function имя (формальные параметры): тип;
	Раздел описаний
Begin
	Раздел операторов
End;
	Программу вычисления площади четырехугольника, варианты которой мы рассматривали с использованием процедур, можно записать и так:
Var ab, bc, cd, da, ac:real;

Function triang(a, b, c:real):real;
Var p:real;
Begin p:=(a+b+c)/2;
Triangl:=sqrt(p*(p-a)*(p-b)*(p-c));
End;

Begin
Read(ab, bc, cd, da, ac);
Write(triangl(ab, bc, ac)+triangl(cd, da, ac));
End.
	Пример. Найти разность факториалов F=m! – k!.
Var p, I, f, m, k:integer;
Function fact(n:integer):integer;
Begin
P:=1;
For I:=2 to n do
P:=p*I;
Fact:=p;
End;
Begin
Write(‘введите m и k’);
Read(m, k);
F:=fact(m) – fact(k);
Writeln(‘f=’, f);
End.
	Область действия имен. Имена, объявленные в разделе описания основной программы, действуют в разделе операторов основной программы и в любой программе (процедуре и функции). Эти имена называются глобальными. Имена, объявленные в подпрограмме, действуют только в этой подпрограмме и в любой объявленной процедуре и функции. Такие имена называются локальными. Они недоступны для операторов основной программы.
		Задания для самостоятельного решения
	Задание. Дан массив целых чисел а1, а2, а3,…,а15. Вычислить сумму элементов а1+а2+а3+…+а15. Найти произведение этих сумм. Вычисление суммы оформить как функцию.
					Вопросы.
что такое подпрограмма?
укажите особенности оформления подпрограмм в виде процедуры?
укажите особенности оформления подпрограмм в виде функции?
можно ли составить процедуру без параметров?
как вы понимаете глобальные и локальные данные?
Файловый тип данных.
В задачах, которые мы рассматривали, данные поступали с клавиатуры, а результаты выводились на экран дисплея. Поэтому ни исходные данные, не результаты не сохранялись. Всякий раз при выполнении одной и той же программы, особенно во время ее отладки, приходилось заново вводить исходные данные. А если их много? Тогда удобно оформить исходные данные и результаты в виде файлов, которые можно хранить на диске точно так же, как и программы.
Файл-это область памяти на внешнем носителе, в которой хранится некоторая информация. В языке Паскаль файл представляет собой последовательность элементов одного типа. Мы будем работать с файлами последовательного доступа. В таких файлах, чтобы получить доступ к элементу, необходимо последовательно просмотреть все предыдущие.
Объявление файловой переменной в разделе описаний переменных имеет вид:
Var<имя файловой переменной>file of<тип элементов>;
Например: var proba : file of integer;
Объявление файловой переменной с использованием раздла описания типов type:
Type<имя типа>=<file of <базовый тип>;
Var<имя файловой переменной>:<имя типа>;
Например:type=file of real;
Var proba: t; {здесь t- введенный тип данных}
Так как в описании указывается тип элементов, такие файлы называются типизированными. Все элементы файла пронумерованы начиная с нуля. Скаждым файлом связан так называемый файловый указатель. Это неявно описанная переменная, которая указывает на некоторый элемент файла.

(0)             (1)                  …….            (К)          (К+1)         ………                   

	файловый указатель
Все операции поизводятся с элементом, на который указывает файловый указатель.
      Обработка файлов.
Связь переменной файлового типа с файлом на диске.
Для установления связи между файловой переменной и файлом на диске имеется стандартная процедура:
Assing(<имя файловой переменной>,’<bvz yf lbcrt>’);
Например, assign(proba,’A:int.dat’);
После установления такого соответствия все операции, выполняемые над переменной proba, будут выполнятся над файлом, хранящимся на диске А и имеющим имя int.dat.
Файл в каждый момент времени находится в одном из двух состояний: либо он открыт только для записи, либо только для чтения.
Чтение файла.
Под чтением из файла понимается пересылка данных из внешнего файла, находящегося на диске, в оперативную память. Для чтения из файла необходимо открыть файл для чтения посредством процедуры
Reset (<имя файловой переменной >);
Собственное чтение данных из файла выполняется процедурой
Read (<имя файловой переменной > , <имя переменной>);
Переменная должна иметь тот же тип, что и компоненты файла. Отметим, что если оператор ввода имеет вид read (<имя переменной >); , то данные вводятся с клавиатуры, а в указанном выше виде- данные вводятся из файла, хранящегося на диске.
Закрытие файла.
После того как данные из файла прочитаны, его необходимо закрыть посредством процедуры.
Close (<имя файловой переменной>) ;
Признак конца файла 
Так как число элементов файлов неизвестно заранее, необходимо уметь определять, что файл кончился. Для этого используется логическая функция EOF ( <имя файловой переменной> (EOF-End OF File). Она принимает истинное значение(true), если достигнут конец файла, и ложное (false)- в противном случае.
Пример 1.
Var f1: file of integer;
      N : integer;
Begin
Assing(f1,’a:int.dat’);{связываю файловую переменную с файлом на диске}
Reset(f1);{открываем файл для чтения}

While not eof(f1) do {пока не достигнут конец файла f1}
Begin
Read(f1,n);{считываем очередное число из файловой переменной f1   и присваиваем  переменной n}
Write(n, ‘‘ ‘);{выводим его на экран }
         End;
Close(f1);{закрываем файлЪ
End.
            Запись в файл
Под записью в файл понимается вывод результатов программы из оперативной памяти ЭВМ в файл на диске. Для записи в файл необходимо открыть файл для записи посредством процедуры
Rewrite (<имя файловой переменной > ) ;
Собственная запись данных в файл выполняется процедурой
Write (<имя файловой переменной >,  <имя переменной значения, которые записываются в файл>); - данные выводятся на экран, а в приведенном выше виде - записываются в файл. После работы с файлом его необходимо закрыть.
Close(<имя файловой переменной>);
            Прямой доступ к элементам файла
Несмотря на то ,что в стандартном Паскале имеются лишь файлы последовательного доступа, Турбо Паскаль содержит процедуры и функции для более эффективной работы с файлами. Вчастности , имеется возможность осуществлять прямой доступ к элементам файла.
             Установка указателя
Процедура Seek(<имя файловой переменной>,N)устанавливает файловый указатель на N – ный элемент. Например Seek(proba, 3).
Напомним, что элементы файла нумеруются с нуля.
          Определение номера элемента
Функция FilePos(<имя файловой переменной>) возвращает номер элемента, на который указывает файловый указатель.
Пример. Найти номер элемента, с которым будет выполняться следущая операция.
N: = filepos (proba);
          Удаление файлов
Процедура Erase (<имя файловой переменной>); удаляет файл на внешнем носителе, с которым связана файловая переменная.

       Переименование файлов.
Процедура Rename(<имя файловой переменной>,’<новое имя на диске>’); переименовывает файо связанный с данной файловой переменной.
Пример. Ввести с клавиатуры , записать в файл DAN1.DAT
Последовательность целых чисел.
Var f:file of integer;
      N:integer;
Begin
      Assign(f,’DAN!.DAT’);
      Rewrite(f);
      Repeat{пока не будет введен 0}
      Writeln(‘введи число’);
      Readln(n);
If n <>0 then Write (f,n);
   Until n=0;
   Close(f);
End.
Вопросы:
1.Что такое файл?
2.Как описываются файлы?
3.Какие операции можно поизводить с файлами?
4.Как производить запись в файл?
5.Как производится чтение из файла?
6.Как закрыть файл?
7.Как получить доступ к элементу файла с данным номером?
8.Как подсчитать количество элементов в файл?

Текстовые файлы.
Текстовые фаайлы состоят из символьных строк. Строки могут иметь различную длину, и в каждой строке стоит признак конца строки. Для описания текстовых файлов используется служебное слово text:
Var a: text;
Обработка текстовых файлов.
Для обработки текстовых файлов используется те же процедуры и функции, что и для обработки обычных типизированных файлов. Для связывания файловой переменной с файлом на диске употребляется процедура assign. Текстовые файлы могут быть открыты для чтения процедурой reset или для записи rewrite.

Для чтения данных применяется процедура read.Если необходимо после чтения данных перейти на следующую строку, то используется процедура readln. Если необходимо просто перейти к следующей строке, то можно использовать процедуру readln(<имя файловой переменной текстового файла>), которая устанавливает файловый указатель на первый элемент следующей строки.
Процедура write записывает данные в текущую строку. Если надо записать данные и перейти к следующей строке, то можно использовать процедуру writeln.Если требуется только перейти для записи на новую строку, то применяется процедура writeln(<имя файловой переменной текстового файла>), которая записывает в файл признак конца строки и устанавливает файловый указатель на начало следующей строкию
Так как в строках может быть разное количество символов, имеется логическая функция Eoln(<имя файловой переменной текстового файла>),
Которая принимает значение true,если достигнут конец строки.
Кроме перечисленных процедур и функций , к текстовым файлам применяется процедура Append(<имя файловой переменной текстового файла>).Она окрывает файл для “дозаписи”, помещая файловый указатель в конец файла.
Пример. Дан тестовый файл, содержащий только целые числа, в каждой строке может быть несколько чисел, которые разделяются пробелами. Вывести на экран все числа с учетом разбиения на строки и подсчитать количество элементов в каждой строке.
Решение.
Пусть в файле содержится следующая информация:
-32 16 0 8 7
4 5 9 13 11 –5 –8
6 –8 0 –12
5 4 3 2 1 12
1 2 
2 –1 2 –4
3 –1 –3
Этот файл можно создать в среде Турбо Паскаль следующим образом:
создайте новый файл посредством команды New File:
запишите все числа, разделяя их пробелами, и разбейте на строки, как указано в задании;
сохраните файл , под именем INT1.DAT.
Этот файл используется в программе, которая приведена ниже.
Var f:text;
X,y:integer;
Begin
   Assign(f,’int1.dat’);{связывает файловую переменную с файлом на диске}
   Reset(f);{открываем файл для файла}
  While not eof(f) do{пока не достигнут}
Begin
  K:=0;{счетчик элементов строки}
  While not eoln(f) do {пока не достигнут конец строки}
Begin
  Read(f,x);{считываем очередное число}
  Write(x, ‘ ‘);{выводим его на экран}
  Inc(k);{увеличивается счетчик}
End;
  Writeln(‘в строке’,k, ‘ ‘элементов’);
  Readln(f);{переходим к следующей строке файла}
End;
  Close(f);{закрываем файл}
  Readln;
End.

Задание 1. Записать в файл все простые числа от 1 до m
{prost}
uses crt;
const n=200;
label br,np;
var pro: file of integer;
b,m,I,ii,j,k,q:integer;
p             :array[1..n] of integer;
begin
assign (pro, ‘ pros.dat’);
rewrite(pro);
write(‘m=’);
readln(m);
writeln(m);
writeln(‘n=’,n);
if(m>=2) then writeln(2);
if (m>=3) then writeln(3);
k:=1;p[k]:=3; I:=5;
while I<=m do
begin
for j:=1 to k do
begin
q:=p[j];

if (q*q>I) then goto br;
if(I mod q=0) then goto np
end;
if k-n then
   begin
   I:=m-1;
   Write(‘the rest numbers’);
   Writeln(‘can not be calculate’);
  End
Else
Br:begin
    Writeln(i); write (pro,I);
    If (k<=n-1) then begin 
                          K:=k+1;
                          P[k]:=1
                           End;
  End;
Np:I:=I+2
   End;
   Close (pro);
End.
Задание 2. Вывести на экран простые числа из файла, записанные в предыдущем задании.
Var cl:file of integer;
       N:integer;
      Begin assign(cl,’pros.dat’);
Reset(cl);
           While not eof (cl) do
           Begin
           Read(cl,n);
          Writeln(n);
          End;
          Close(cl);
End.

Задание для самостоятьельного решения.
Дан файл А, элементами которого являются целые числа.Найти:
А) оличество элементов в файле;
Б) наибольший из элементов.Если имеется несколько элементов с одинаковыми наибольшими значениями, то подсчитать количество таких элементов;
В)среднее арифметическое элементов.
Графические возможности языка Паскаля.
Для работы с графикой в Паскаль необходимо подключить модуль GRAPH, которая представляет собой мощную библиотеку графических подпрограмм.
Uses GRAPH;
В разделе описаний переменных необходимо указать  графический драйвер и текущий графический режим. Приведем фрагмент начала программ:
Uses crt, graph;
Var
Driver, Mode: integer; x,y: integer;
     Begin
            Driver:=CGA;
            Mode:=CGAC3;
             InitGraph(Driver,Mode,’c:\pascal\bgi\’);
SetColor(3);
………………………………………………………
Подчеркнутые части фрагмента, приведенной выше программы, организует графический режим работы и обязательны для всех программ, работающих в графическом режиме.
   Driver- должен содержать тип графического драйвера.
    Mode- устанавливает текущий режим.
‘c:\pascal\bgi\’’- указывает путь к драйверу bgi графического адаптера.
Примеры констант задания драйверов и режимы работы:
1). Driver-CGA, Mode- CGAC3, {320*200 пикселей, палитра 3}.
2). Driver-VGA, Mode- VgaHi, {640*480 пикселей, 16 цветов}.
Для указания пикселя используется следующая система координат: верхний левый угол графического экрана имеет координаты (0;0), горизонтальная координата Х увеличивается слева направо, вертикальная координата Y увеличивается сверху вниз.
Некоторые графические процедуры:
SetColor(c) – устанавливает цвет с, которым будет осуществляться рисование.
SetBkColor(c)- устанавливает цвет с фона.
PutPixel(x,y,c)- Выводит точку цветом с координатами x,y.
Line(x1,y1,x2,y2)- оисует линию от точки (x1,y1) до точки (x2,y2).
Circle(x,y,r)- рисует окружность с центром в точке (x,y) и радиусом r.
Bar(x1,y1,x2,y2)- рисует полосу заданного размера, где (x1,y1) и (x2,y2) координаты диагонали полосы.
Arc(x,y,un,uk,r)- рисует дугу радиусом: r от начала угла un к конечному uk, используя x,y координаты центра.
Fillellipse(x,y,xr,yr)- рисует эллипс, используя x,y как координаты центра и xr,yr- как горизонтальный и вертикальный радиусы.
Ellipse(x,y,un,uk,xr,yr)- рисует эллиптическую дугу от начального угла un к конечному углу uk, используя x,y как координаты центра и xr,yr- как горизонтальные и вертикальные радиусы.
OutText(x,y,’string’)- выводит текст string в заданное место экрана.
ClearDevice- очищает экран.
CloseGraph- закрывает графичекий режим.
Примечание. c,x,r,u,un,uk,xr,yr- переменные целого типа. Углы задаются в градусах, направление изменения- против часовой стрелки.
Некоторые константа цвета:
Black- 0- черный	Blue- 2- синий
Green- 2- зеленый	Red- 4- красный
Yellow-14- желтый	White- 15- белый.
Упражнения.  Получить изображения на экране графические элементы, используя перечисленные процедуры.
Пример 1:
Uses graph;
Var driver, mode: integer;
Begin
Driver:= CGA;
Mode:= CGAC3;
Initgraph(driver,mode,’c:=\pascal\bgi\’);
Arc(100,100,0,180,30);
End.
Пример 2:
Uses graph;
Var driver, mode: integer;
Begin
Driver:= CGA;
Mode:= CGAC3;
Driver:=detect;
Initgraph(driver,mode,’c:=\pascal\bgi\’);
Bar(0,0,100,10);
End.
Задания для самостоятельного разбора.
Задание 1. Составить программу построения графика функции f(x) на отрезке [0,b].
Комментарии к программе.  В программе запрашивается число b- граница отрезка, на котором строится график. В качестве функции задана функция sin(x). Если задать d=6.28, то программа нарисует график синусоиды на отрезке от 0 до 300, а по вертикали- от 0 до 200.
Uses graph;
Var driver, mode:integer; b,dx,x:real; i: integer; 
Function f(x:real): real;
Begin
F:= sin(x); end;
Begin
Write(‘Введи b’); readln(b);
Dx:=b/300;
Driver:= CGA;
Mode:= CGAC3;
Initgraph(driver,mode,’c:=pascal\tp7\bgi\’);
SetColor(1);
Line(0,0,0,200);
Line(0,100,320,100);
OutTextXY(4,0,’Y’);
OutTextXY(310,90,’X’);
For I:=1 to 300 do begin
PutPixel(I,trunc(100*(1-f(x))),3);
X:=x+dx; end;
End.
Задание 2.  Составить программу, рисующий на экране картинку- «Снежную бабу». При нажатии на клавиши «влево» и «вправо» картинка должна двигаться в соответствующем направлении, но не должна выходить за границу экрана. 
Комментарии к программе. В программе положении картинки зависит от целого числа х. После запуска программы х=160 и картинка расположена в центре экрана. При однократном нажатии на клавишу «влево» х уменьшается
на 10 и картинка сместится на 10 пикселей влево. Аналогично при однократном нажатии клавиши «вправо», х увеличивается на 10 пискселей вправо. Ширина картинки- 120 пикселей. Если х станет меньше 60 или больше 260, то картинка не сможет быть нарисована  и выполнение программы закончится. #0, #77, #75- коды нажатых клавиш. Readkey- чтение символа нажатой клавиши без эхоповтора на экран.
Uses Graph, crt;
Var Driver, Mode:integer; x,y:integer; k:char;

Procedure picture(a,b:integer);
Begin
    SetColor(3);
Fillellipse(a,b,26,26);
Fillellipse(a,b+58,35,35);
Fillellipse(a,b-40,16,16);
Fillellipse(a-32,b-17,10,10);
Fillellipse(a+32,b-17,10,10);
SetColor(0);
Circle(a+6,b-44,2);
Circle(a,b-20,2);
Circle(a,b,2);
Circle(a-6,b-44,2);
Line(a-6,b-32,a-4,b-30);
Line(a-4,b-30,a+4,b-30);
Line(a+4,b-30,a+6,b-32);
Line(a-1,b-37,a+1,b-37);
Line(a,b-39,a,b-35);
SetColor(3);
Line(a-35,b+85,a-45,b-55);
Line(a-45,b-55,a-52,b-70);
Line(a-45,b-55,a-34,b-70);
End; begin
Driver:= CGA;
Mode:= CGAC3;
InitGraph(Driver,Mode,’c:\pascal\tp70\bgi\’);
x:=160; y:=85;
while (x>60) and (x<260) do begin
picture(x,y); k:=#0;
while (k<>#77) and (k<>#75) do begin
k:=readkey;
k:=readkey;
end;
cleardevice;
if k=#77 then x:=x+10 else x:=x-10; end;
end.
Задание. Используя графические процедуры языка Паскаль получить изображение: домика; движущегося автомобиля.
ЗАПИСНЫЕ ТИПЫ
Во многих экономических и информационных задачах обрабатываются ведомости, документы, каталоги, списки. При этом появляется необходимость объединять данные различного типа в одну группу. Для работы с группой данных в языке Паскаль введено понятие записи. Запись - это структура данных, состоящая из фиксированного числа компонентов разного типа. Составляющие запись компоненты называется полями записи. В отличие от массива компоненты (поля) записи могут быть различного типа. Чтобы можно было ссылаться на тот или иной компонент записи, поля именуются. Записной тип еще называют комбинированным типом.
Записной тип данных предоставляет программисту возможность объединить в одну связанную структуру различные по типу и смыслу элементы. Элементами записи могут быть и структурированные типы данных, например массивы и другие подчиненные записи. Для обработки доступна как вся запись целиком, так и отдельные ее поля.
Понятие записи рассмотрим на примере ведомости списка учащихся с их оценками.
№	Фамилия И. 0.	Оценки	
1	Иванов И. И.	5	3	4	
2	Андреева А. А.	5	5	3	
3	Керенский А. Ф.	5	4	5	
4	Ульянов В. И.	5	5	5	
Каждая строка в этой ведомости состоит из отдельных элементов данных различного типа:
а) порядковый номер - целое десятичное число;
б) Фамилия И. О. - массив символов;
в) оценки - массив целых чисел.
Эти данные можно объединить в одну группу и считать записью. Введем следующие обозначения: В - имя всей записи; п -, порядковый номер; fio -фамилия, имя, отчество; mark - оценки.
Обращение к элементу записи в программе выполняется с помощью уточненного (составного) имени. Уточненное имя содержит имя записи и имя элемента и записывается в следующем виде:
имя записи.имя элемента. Например,
В.п 
B.fio
 В. mark
Записи, как и другие данные, объявляются в разделе описаний и используются в разделе операторов.
Структура объявления типа записи такова:
<имя типа> = record <список полей> end
Здесь <имя типа> - правильный идентификатор; record, end -зарезервированные слова (запись, конец); <список полей> - последовательность разделов записи, между которыми ставится точка с запятой. Каждый раздел записи состоит из одного или нескольких идентификаторов полей, отделяемых друг от друга запятыми. За идентификатором (идентификаторами) ставится двоеточие и описание типа поля (полей).
Для представленной ведомости объявление записи выглядит следующим образом:
type list = record n : integer;
fio : array [1..'!0] of Char;
mark : array [1..3] of integer end;
var В : list;
Возможно объявление записи в разделе переменных:
var В : record n : integer;
fio : array [1..20] of char;
mark : array [1..3] of integer end;
Элемент записи используется в программе в том же самом смысле, как и обычная переменная. Элемент записи можно указывать как в левой части оператора присваивания, так и в выражениях. Над элементом записи можно выполнять действия, допустимые для данных его типа. Если тип элемента записи - целый, то выполняются все операции, допустимые для целых данных. Для рассмотренной ведомости над элементами записи можно произвести, например, следующие операции:
порядковому номеру n записи В присвоить значение 2:
В.п := 2;
найти сумму трех оценок:
s := B.mark [1] + В.mark [2] + B.mark [3];
ввести значения порядкового номера:
read (B.n).
Обращение к записи в целом, а не только к ее элементам, допускается лишь в операторе присваивания. Слева и справа от знака присваивания при этом должны использоваться имена записей одинакового типа.
Объявим тип birthday, содержащий три поля с именами day, month и year; переменные а и b содержат записи типа birthday; с - запись, содержащая в качестве элемента подчиненную запись.
type 
birthday = record
day.month : byte;
year : word 
end;
var a,b : birthday;                                     
       с : record
name : string;
bd : birthday end;
В этом случае возможно а := b; a.day>:= 27; b.year := 1939; для вложенных полей необходимо продолжать уточнения: c.bd.year, c.bd.day, с.bd.month. 
Оператор присоединения With ... do
Обращение к конкретным полям записи связано с некоторыми неудобствами. Составные идентификаторы получаются длинными. При совместной обработке ряда полей одной записи длину идентификаторов можно сократить.
Чтобы упростить доступ к полям записи, используется оператор присоединения With:
with <переменная> do <оператор>
Здесь with, do - ключевые слова (с, делать); <переменная> - имя переменной типа запись, за которым, возможно, следует список вложенных полей; <оператор> - любой оператор Турбо Паскаля.
Оператор присоединения with ... do открывает запись. В поле его действия имена полей записи сокращаются. Например:
with c.bd do month := 9;                                             
 Это эквивалентно                                                   :
with с do with bd do month := 9;
или c.bd.month := 9.
В такой записи не чувствуется преимущество использования оператора with. Когда обрабатываются все поля записи, оператор with ... do дает существенную экономию в размере программы.
Задача. Составить программу формирования архива данных по изданным книгам. Данные включают: автора, название, год издания, город, где издана, и цену книги.
Предположим, что в архив необходимо занести данные о 50 книгах. Данные будут представлять собой массив записей. Каждая запись состоит из:
1) фамилии И. О. автора (author);
2) названия книги (title);
3) названия города, в котором книга выпущена, (city);
3) года издания (year);
4) цены (cost).
Данные author, title, city - символьного типа. Year - может быть переменной интервального типа. Цена (cost) должна быть переменной вещественного типа. Объявление нового типа данных entry как записного будет выглядеть следующим образом:
entry = record
author, title, city : string;
year : 1..9999;
             cost: real;
             end;
Далее следует объявить массив из 50 элементов, имеющих тип entry. Ввод элементов записи (рис. 16) организуем в цикле, причем окончание цикла зафиксируем вспомогательной переменной ch. Перед вводом содержимого очередной записи сделаем запрос на продолжение пополнения архива. Для ввода компонентов записи используем оператор readln. Компоненты записи в программе имеют составные имена: m[i]. author, m[i]. title, m[i].city, m[i].year, m[i].cost.

Программа:
program archives;
uses crt;
label 10;
type
entry = record {Выходные данные по книге} author, title, city : string;
year : 1..9999;
cost : real;
end;
var m : array[1..50] of entry;
{Архив не превышает 50 книг} 
{Массив, элементами которого являются записи}
 i: integer;
ch : char;
begin i := 0;
{Блок формирования архива данных по книгам}
 writein ('Пополняешь архив? - Да - [Y]');
ch := readkey;
if upcase(ch) = 'Y' then repeat i :=i+1;
writeln('Автор книги '); readln(m[i].author);
writeln('Название книги '); readln(m[i].title);
writeln('Город издания '); readln(m[i].city);
writeln('Год издания '); readln(m[i].year);
writeln('Цена книги '); readtn(m[i].cost);
writein ('Пополняешь архив? - Да - [Y]');
ch := readkey
 until upcase(ch) <> 'Y'
     else 
       begin write ('Вы передумали? До cвидания!');
goto 10 end;
repeat until keypressed;
10:end.
Задача. Усложним предыдущую задачу. Составить программу подборки книг по указанному автору из сформированного массива записей.
Для формирования архива используем предыдущую программу. Введем переменную символьного типа ss - фамилию автора, список книг которого необходимо вывести. Размер архива запомним в переменной k. Для более компактного представления используемых переменных, воспользуемся оператором присоединения with ... do. При этом имена полей записи могут фигурировать как имена обычных переменных. Для возможности вывода нескольких списков организуем внешний цикл с признаком окончания ch = ‘Y'.
Программа:
program archives2;
uses crt;
 label 10;
 type
             entry = record {Выходные данные по книге}
            author, title, city : string;
             year : 1..9999;
             cost : real;
             end;
var m : array[1..50] of entry;
{Архив не превышает 50 книг}
 {Массив, элементами которого являются записи}
 i, i, k : integer;
ss : string; {Фамилия для поиска} ch : char;
begin i :=0;
{Блок формирования архива данных по книгам}
 writein ('Пополняешь архив? - Да - [Y]');
ch := readkey;
if upcase(ch) = 'Y' then
 repeat
      i := i+1;
with m[i] do begin
writeln('Автор книги');readln(author);
 writeln('Название книги'); readln(title);
        writeIn(‘ Город издания'); readln(city);
       writeln('Год издания '); readln(year);
       writeln('Цена книги '); readln(cost);
end;
writein ('Пополняешь архив? - Да - [Y]);
 ch := readkey 
    until upcase(ch) <> 'Y'
    else
 begin
   write ('Вы передумали? До свидания!');
        goto 10;
 end;
k:=i;
{Блок подборки всех книг по указанному автору}
 repeat writeln('Укажите фамилию автора'); readln(ss);
writeln('Cnиcoк книг, автор которых ', ss : 15);
for i := 1 to k do with m[i] do begin if ss = author then
begin
 writeln(title);
writeln(‘Город '.city);
writeln(‘Год издания '.year);
writeln('Цена ",cost:8:2);
writein end end;
writeln( "Нужно еще выдавать авторский список? - Да -[Y]');
ch := readkey;
until upcase(ch) <> 'Y';
repeat until keypressed;
10:end.
 Вариантные записи
Состав данных зависит от вида объекта, на который составлена запись. Например, если выходные данные книги содержат ее название, год и место издания, название издательства, то для журнальной статьи важно знать название журнала, номер и год выпуска. Возникает необходимость внесения в структуру записи некоторой вариантной части. С помощью записей с вариантами можно одновременно сохранять различные структуры данных, которые имеют общую часть, одинаковую во всех структурах, и небольшие отличающиеся части в различных структурах.
Вариантный записной тип - это записной тип, содержащий несколько вариантов структуры записи. Различие может касаться как числа компонент, так и их типов.
Предположим, что есть, например, такое описание:
type status = (married, widowed, divorced, single),
что означает женатый, вдовец, разведенный, одинокий. В этом случае человека можно описать с помощью данных следующего типа:
type person = record
{здесь поля общие для всех person} case status of
married: ( { поля только для семейных });
single: ({ поля только для одиноких });
end;
Каждому значению, относящемуся к типу, на основании которого идет различение вариантов (типу признака), должен соответствовать один из вариантов. Это означает, что перед вариантами должны появляться все значения типа признака. В нашем примере, кроме констант married и single, должны появиться и константы widowed и divorced.
Обычно некоторая компонента (поле) записи сама указывает, о каком варианте идет речь. В приведенном описании типа следовало бы иметь общее для всех вариантов поле ms : status. Описание определяющей вариант компоненты можно включить в заголовок варианта. Такое описание называется полем признака. Например:            
case ms : status of
Прежде чем начать определять структуру записи с вариантами, соответствующую, например, типу person, полезно бывает выписать всю необходимую информацию.
1. Имя (name) - первое, последнее (first, last).
2. Рост (height) - целое число.
3. Пол (sex) - муж., жен. (male, female).
4. Дата рождения (date) - год, месяц, день (year, month, day).
5. Число иждивенцев (depds) - целое число.
6. Семейное положение (status):
Если в браке (married) или вдов (widowed):
а) дата свадьбы (mdate) - год, месяц, день (year, month, day). Если разведен (divorced):
а) дата развода (ddate) - год, месяц, день (year, month, day),
б) первый развод (firstd) - нет, да (false, true). Если одинокий (single):
информации нет.
Определение записного типа person можно сформулировать так:
type status = (married, widowed, divorced, single);
date = record
year : 1900..2100;
то : (jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec);
day : 1..31;
end;
natural = O.-max;
person = record
name : record first, last: string[15] end;
height: natural;
sex : (male, female);
birth : date;
depdts : natural case ms : status of
married, widowed : (mdate : date);
divorced : (ddate : date; firstd : boolean);
single: () 
end {person};
Задача. Составить программу формирования перечня сведений по данным архива книг и журналов.
Данная задача отличается от задачи 19 тем, что состав данных в записи различается для книги и для журнала. Введем перечисляемый тип данных entrytype, определяющий варианты, type entrytype = (book, magazine).
Данные по каждому наименованию архива включают:
1) автора книги-или статьи (author) - переменная типа string;
2) наименование книги или статьи (title) - string;
3) год издания книги (журнала) - интервальный тип 1 ... 1999;
4) если книга (book):
а) издательство (publisher) - string;
б) город (city) - string. Если журнал (magazine):
а) наименование журнала (magname) - string;
б) номер журнала (vol) - integer;
в) количество страниц (page) - integer.
Программа:
program archives3;
uses crt;
label 10;
type entrytype = (book.magazine);
{Вводится специальный тип данных, определяющий варианты}
 entry = record
author, title : string;
   year : 1..9999;
   case tag:entrytype of 
  {Поле tag определяет ветвь варианта}
   book : (publisher,city : string);
    magazine : (magname : string; vol, page : integer)
    end;
var m : array[1..50] of entry;
i, j, k : integer;
ss : string;
ch : char;
begin i := 0;
{Блок формирования архива данных по книгам} 
writein (‘Пополняешь архив? - Да - [Y]');
ch := readkey;
if upcase(ch) = 'Y' then repeat i := i+1;
writeln(‘Ecли вводите данные по книге, нажмите Y ');
ch := readkey;
if upcase(ch) = 'Y' then
m[i].tag := book
{Переменной варианта присваивается признак книги - book} else m[i].tag := magazine;
writeln('Автор '); readln(m[i].author);
writeln('Название '); readln(m[i].title);
    writeln('год издания '); readln(m[i].year);
{Проверка условия принадлежности объекта к книге}
if m[i].tag = book then
{Ввод данных в поля, специфические для книги} begin writeIn(‘ Город '); readln(m[i].city);
      writeln('Издательство'); readln(m[i]. publisher);
end else
{Ввод данных в поля, специфические для журнала} 
begin
 write ('Название журнала'); readln(m[i].magname);
writeIn(‘ Номер '); readln(m[i].vol); 
                   writeln( 'Страница '); readln(m[i].page);
end;
writein ('Пополняешь архив? - Да - [Y]');
. ch := readkey;
until upcase(ch) <> 'Y'
    else
         begin write ('Вы передумали? До свидания!');
goto 10 end;
{Блок подборки списка трудов указанного автора}
    repeat
     writeln('Укажите фамилию автора'); readln(ss);
writeln('Список трудов ', ss : 15);
for i := 1 to k do
    begin
          if ss = m[i].author then
             begin
               writeln(m[i].title);
                writeln('Год издания ',m[i].year);
                  if m[i].tag = book then 
                    begin
                 writeln('Гopoд ',m[i].city);
                  writeln('Издательство ',m[i]. publisher);
                writein 
                    end
                   else
       begin 
writeln('Haзвание журнала ',m[i].magname);
writeln('Hoмep ',m[i].vol);
writeln( "Страница ',m[i].page);
writein 
end
 end
 end;
writeln('Нужно еще выдавать авторский список? - Да -[Y]');
ch := readkey;
until upcase(ch) <> 'Y';
repeat until keypressed;
10:end.