РЕКОМЕНДАЦИИ: Для того, чтобы избежать зацикливания программы необходимо обеспечить изменение на каждом шаге цикла значения хотя бы одной переменной, входящей в условие цикла. После выхода из цикла со сложным условием (с использованием операций and, or, xor) как правило необходима проверка того, по какому условию цикл завершен.
ПРИМЕР: Пары неотрицательных вещественных чисел вводятся с клавиатуры. Посчитать произведение для каждой пары и сумму всех чисел.
program cycle_while;
var x,y,sum:real; otv:char;
begin
sum:=0;
otv='Д';
while (otv='Д') or (otv='д') do
begin
write('Введите числа x,y > 0 ');
readln(x,y);
writeln('Их произведение = ',x*y:8:3);
sum:=sum+x+y;
write('Завершить программу (Д/Н)? ');
readln(otv);
end;
writeln('Общая сумма = ',sum:8:3);
readln
end.
ПРИМЕР: В той же задаче можно использовать другой цикл с условием:
program cycle_repeat;
var x,y,sum:real; otv:char;
begin
sum:=0;
repeat
write('Введите числа x,y > 0 ');
readln(x,y);
writeln('Их произведение = ',x*y:8:3);
sum:=sum+x+y;
write('Завершить программу (Д/Н)? ');
readln(otv);
until (otv='Д') or (otv='д');
writeln('Общая сумма = ',sum:8:3);
readln
end.
ПРИМЕР: Нахождение наибольшего общего делителя двух целых чисел с помощью Алгоритма Эвклида.
program Evklid;
var a,b,c:integer;
begin
write('введите два целых числа : ');
readln(a,b);
while b<>0 do
begin
c:=a mod b;
a:=b;
b:=c;
end;
writeln('наибольший общий делитель = ',a);
readln
end.
В Турбо Паскале предусмотрен механизм создания новых типов, которые принято называть пользовательскими или конструируемыми. Их можно создавать на основе стандартных и ранее созданных типов. Описание новых типов происходит в разделе TYPE. После этого можно в разделе Var создавать переменные этих типов. Также, можно сразу описывать новый тип при создании переменной в разделе Var. В этой главе мы рассмотрим следующие пользовательские типы:
перечисляемый тип,
тип-диапазон,
массивы,
записи.
Перечисляемый тип задается перечислением тех значений, которые он может получать. Каждое значение должно являться идентификатором (смотри главу Алфавит языка) и располагаться в круглых скобках через запятую. Количество элементов в перечислении не более 65536. Вводить и выводить переменные перечисляемого типа запрещено. Перечислимый тип является порядковым (смотри главу Типы данных), поэтому к переменным такого типа можно применять функции Ord, Pred, Succ. Функция Ord возвращает порядковый номер значения начиная с нуля.
ПРИМЕР: Объявление перечисляемых типов.
Type Colors = (Red,Green,Blue);
Numbers = (Zero,One,Two,Three,Four,Five);
var c:Colors; n:Numbers;
begin
c:=Red; write(Ord(c)); {0}
n:=Four; write(Ord(n)); {4}
c:=Succ(c); {c=Green}
for n:=One to Five do write(Ord(n)); {12345}
end.
Следует отметить, что стандартные типы byte, word, char и boolean также можно считать вариантами перечислимого типа.
Тип-диапазон также называют ограниченным или интервальным типом. Он является подмножеством своего базового типа, в качестве которого может выступать любой порядковый тип кроме типа-диапазона. Тип-диапазон наследует все свойства своего базового типа. Имеются две стандартные функции, работающие с этим типом: High(x)- возвращает максимальное значение типа-диапазона, к которому принадлежит переменная x; Low(x) - возвращает минимальное значение.
ПРИМЕР: Объявление типа-диапазон.
type Numbers = (Zero,One,Two,Three,Four,Five);
Num = Two.. Four; {диапазон на базе типа Numbers}
Abc = 'A'.. 'z'; {все английские буквы : диапазон на базе типа Char}
Digits = 0.. 9; {цифры}
var n:Num; c,d:Abc; x:integer;
begin
n:=Four; writeln(Ord(n)); {4 как в базовом типе}
n:=Succ(n); { ОШИБКА (следующее значение вне диапазона)}
read(c,d);
if c=d then write('одинаковые буквы');
writeln(Low(c),'.. ',High(c)); { A.. z }
writeln(Low(x),'.. ',High(x)); { -32768.. 32767 }
end.
В тексте программы на Турбо Паскале могут встречаться директивы компилятору, которые также называют опциями. Опции {$R+} и {$R-} позволяют включать и отключать проверку соблюдения границ при работе с диапазонами. Когда проверка включена, при нарушении границ диапазонов происходит аварийное завершение работы программы. В другом случае ответственность за возможные ошибки лежит на программисте.
Массив - это упорядоченная структура однотипных данных, хранящая их последовательно. Доступ к элементу массива осуществляется через его индекс. Массивы описываются следующим образом:
Имя типа = ARRAY [ диапазоны индексов ] OF тип элемента массива;
В качестве типа для элементов массива можно использовать любые типы Турбо Паскаля кроме файловых. Диапазоны индексов представляют собой один или несколько диапазонов, перечисленные через запятую. В качестве диапазонов индексов нельзя использовать диапазоны с базовым типом Longint.
ПРИМЕР: Три способа описания одного и того же типа массива:
type {1} M1 = array [0..5] of integer;
M2 = array [char] of M1;
M3 = array [-2..2] of M2;
{2} M3 = array [-2..2] of array [char] of array [0..5] of integer;
{3} M3 = array [-2..2,char,0..5] of integer;
var A:M3;
{Обращаться к элементам массива можно следующим образом:}
begin
read(A[-1,'a',3]);
read(A[1]['x'][0]);
A[1]['c',1]:=100;
end.
Глубина вложенности, т.е. количество индексов, при определении массивов не ограничена. Играет роль только суммарный объем данных в программе. В стандартном режиме работы Турбо Паскаля этот объем ограничен размерами сегмента, т.е. 64 килобайта. Целиком над массивами допускается применение только операции присваивания массивов (подмассивов) одинаковых типов. Остальные операции должны выполняться поэлементно.
ПРИМЕР: Вычисление значения многочлена степени N, коэффициенты которого находятся в массиве A в точке X по схеме Горнера.
Pn(x) = A[0]*X^n + A[1]*X^(n-1) +... + A[n-1]*X + A[n] =
= (...((A[0]*X + A[1])*X + A[2])*X +... + A[n-1])*X + A[n].
program Scheme_Gorner;
type Mas = array[0..100] of integer;
var A:Mas; i,j,n:integer; x,p:real;
begin
write('степень многочлена = '); read(n);
writeln('введите целые коэффициенты : ');
for i:=0 to n do read(A[i]);
write('значение X = '); read(x);
p:=0;
for i:=0 to n do p:=p*x+A[i];
writeln('Pn(X) = ',p);
end.
Запись - это стpуктуpа данных, котоpая может содеpжать инфоpмацию pазных типов, объединенную под одним названием. Компоненты записи называются полями. Их фиксиpованное число. Описание записей имеет следующую стpуктуpу:
Имя типа = RECORD
список полей 1 : тип 1;
- -
список полей N : тип N;
CASE поле выбора : тип OF
значение 1 : (полей 1 : тип 1)
END;
Типы полей записи могут быть любыми. В свою очеpедь, тип запись может использоваться для создания массивов и новых записей. Степень вложенности не огpаничена.
Список полей может состоять из двух pазделов: постоянной и ваpиантной части. В постоянной части идет пеpечисление полей записи (идентификатоpов) с указанием их типов. Синтаксис такой же, как в pазделе var.
ПРИМЕР: Пример объявления типа запись.
type Men = Record
FIO,Adress : string;
Year : byte;
End;
var A,B : Men;
Для обpащения к полям записи указывается имя пеpеменной типа запись, точка, имя поля, напpимеp:
begin
A.FIO:='Иванов И.И.';
A.Adress:='пp. Ленина, д. 40, кв. 10';
A.Year:=1981;
end.
После описания постоянных полей может следовать ваpиантная часть, котоpая может быть только одна и имеет вид
CASE поле выбоpа : тип OF
значение 1 : (список полей 1);
- - -
значение N : (список полей N);
Поле выбоpа может отсутствовать. Если оно есть, то его воспpинимают как постоянное поле записи. Если его нет, указывается только тип, котоpый должен быть поpядковым, но он не влияет ни на количество пеpечисленных ниже значений, ни на типы этих значений.
Все ваpианты pасполагаются в одном и том же месте памяти, котоpой выделяется столько, сколько тpебуется для максимального по pазмеpу ваpианта. Это пpиводит к тому, что изменение одного ваpиантного поля оказывает влияние на все остальные. Это увеличивает возможности пpеобpазования типов, ПРИМЕР: Запись с вариантами.
var R = Record
rem : string;
Case byte of
3 : (n:integer);
5 : (x,y,z:char);
'a' : (i,j:byte);
end;
begin
R.rem:='запись с ваpиантами';
R.n:=25000;
write(R.i,R.x,R.j,R.y); {168и97a}
{ord('и')=168, ord('a')=97, 168+97*256=25000}
end.
Значения выбоpа могут повтоpяться. Имена полей записи не являются пеpеменными и, следовательно, могут повтоpяться, но только на pазных уpовнях, напpимеp:
var Rec:Record
x : real;
Sr : Record a : real; x,y : integer; end;
I : byte;
end;
Для удобства обpащения к полям записей может использоваться опеpатоp пpисоединения WITH пеpеменная DO опеpатоp;
Здесь пеpеменная - это запись, за котоpой может следовать список вложенных полей, напpимеp следующие тpи опеpатоpа эквивалентны:
With Rec,Sr Do a := x / y;
With Rec.Sr Do a := x / y;
Rec.Sr.a := Rec.Sr.x / Rec.Sr.y;
Тип String (строка) в Турбо Паскале широко используется для обработки текстов. Этот тип является стандартным и во многом похож на одномерный массив символов Array [0..N] of Char. Значение N соответствует количеству символов в строке и может меняться от 0 до 255. Символы, входящие в строку, занимают позиции с 1 до N. Начальный байт строки с индексом 0 содержит информацию о ее длине, т.е. это символ с кодом, равным длине строки.
Можно, также описывать переменные типа String[K], где K - целое число не больше 255. Так определяются строки с длиной не больше K. Этот тип уже не является стандартным. С символами строки можно работать как с элементами массива из символов, но в отличие от массивов, строки можно вводить целиком, сравнивать друг с другом и сцеплять операцией "+".