Файл: Основы программирования на языке Pascal (Вариант 15).pdf
Добавлен: 02.04.2023
Просмотров: 294
Скачиваний: 2
Числа с плавающей запятой:
|
Тип |
Диапазон |
Кол-во значащих цифр |
Размер в байтах |
Поддержка |
|
Real |
Зависит от платформы |
? |
? |
Все компиляторы; на современных обычно эквивалентен Double |
|
Real48 |
-39..38 |
11-12 |
6 |
Все компиляторы; на современных обычно эквивалентен Double |
|
Single |
-45..38 |
7-8 |
4 |
Большинство вариантов под IEEE 754-совместимые машины |
|
Double |
-324..308 |
15-16 |
8 |
Большинство вариантов под IEEE 754-совместимые машины |
|
Extended |
-4951..4932 |
19-20 |
10 |
Большинство вариантов под x86 |
|
Comp |
−9223372036854775808..9223372036854775807 |
8 |
Borland; рассчитываемое на сопроцессоре 8-байтовое целое; актуально для 16-битного x86 |
|
|
Currency |
−922337203685477.5808..922337203685477.5807 |
8 |
Borland и другие компиляторы под Windows; связано с OLE; фиксированная запятая с единицей, равной 10000 |
|
var { секция объявления переменных }
r: Real; { переменная вещественного типа }
i: Integer; { переменная целого типа }
c: Char; { переменная-символ }
b: Boolean; { логическая переменная }
s: String; { переменная строки }
t: Text; { переменная для объявления текстового файла }
e: (apple, pear, banana, orange, lemon); { переменная типа-перечисления }
В Pascal над целыми типами (byte, shortint, word, integer, longint и их диапазоны) допустимы побитовые операции. Логические операции над битами:
Над битами двух целых операндов можно выполнять ранее рассмотренные логические операции: not, and, or, xor. Отличие между побитовыми и логическими операциями состоит в том, что побитовые (поразрядные) операции выполняются над отдельными битами операндов, а не над их значением в десятичном (обычно) представлении.
Выделяется понятие порядковых типов данных (ordinal), к ним относятся целые типы (знаковые и беззнаковые), логический (boolean), символьный (char), перечислимые типы и типы-диапазоны.
Порядковые типы задаются целым числом (кодом), которое можно получить с помощью функции ord. Все операции, выполняемые над порядковыми типами, выполняются с их кодами.
Диапазоны содержат подмножество значений других порядковых типов:
var
x: 1..10;
y: 'a'..'z';
z: pear..orange;
Для порядковых типов определены операции inc, dec, succ, pred, ord, операции сравнения (= > < => <= <>), их можно использовать в операторах case, for (как счётчик цикла), как границы массивов, для задания элементов множеств и типов-диапазонов.
В Pascal, в отличие от Си-подобных языков, с типами boolean и char арифметические целочисленные операции не определены.
Множества
В отличие от многих распространённых языков, Pascal поддерживает специальный тип данных множество:
var
set1: set of 1..10;
set2: set of 'a'..'z';
set3: set of pear..orange;
Множество - фундаментальное понятие в современной математике, которое может быть использовано во многих алгоритмах.
В Паскале тип множество может содержать только однотипные элементы порядкового типа. Эта особенность
широко используется и обычно быстрее эквивалентной конструкции в языке, не поддерживающем множества.
К примеру, для большинства компиляторов Паскаля:
if i in [5..10] then { проверка на принадлежность элемента множеству }
...
обработается быстрее, чем
if (i>=5) and (i<=10) then { проверка логическими условиями }
...
Для задания значения множества используется список элементов множества, отделенных запятыми и заключённый в квадратные скобки (как уже было показано выше):
var { секция объявления переменных }
d:set of char;
begin { начало блока }
d:=['a','b'];
...
В Паскале Йенсен и Вирта строки представлялись как упакованные массивы символов; следовательно, они имели фиксированную длину и обычно дополнялись до этой длины пробелами.
Составные типы
Новые типы могут быть определены из существующих:
type {секция объявления типов}
x = Integer;
y = x;
...
Более того, из примитивных типов могут быть сконструированы составные:
type {секция объявления типов}
a = Array [1..10] of Integer; {определение массива}
b = record {определение записи}
x: Integer;
y: Char;
end;
c = File of a; {определение файл}
Файловые типы в Паскале делятся на типизированные, текстовые и файлы без типов.
Как показано в вышеприведённом примере, типизированные файлы в Паскале — это последовательности
однотипных элементов. Для каждого файла существует переменная-указатель на буфер, которая обозначается f^. Процедуры get (для чтения) и put (для записи) перемещают указатель к следующему элементу. Чтение
реализовано так, что read(f, x) представляет собою то же, что и get(f); x:=f^. Соответственно, запись реализована так, что write(f, x) представляет собою то же, что и f^:= x; put(f). Текстовые файлы text определены как расширение типа file of char и помимо стандартных операций над типизированными
файлами (чтение, запись символа), позволяют осуществлять символьный ввод-вывод в файл всех типов данных аналогично консольному вводу-выводу.
Файлы без типов объявляются как переменные типа file. С ними можно проводить операции побайтового нетипизированного ввода-вывода по несколько блоков байт указанной длины через буфер, для этого служат специальные процедуры blockread и blockwrite (расширение UCSD).
Строки
В современном Паскале для работы со строками используется встроенный тип string, поддерживающий операции конкатенации (+) и сравнения (> < = <> >= <=). Строки сравниваются в лексикографическом порядке. Например, строки считаются равными, если они имеют одинаковую длину и коды всех символов с одинаковыми индексами совпадают.
Тип string [n] или просто string в диалектах языка 1970—1990-х годов определялся в виде массива символов array [0..n] of char (n по умолчанию принимало значение 80 в UCSD Pascal и 255 в Turbo/Borland Pascal), нулевой элемент массива при таком представлении служит для задания длины строки,
соответственно строка могла иметь максимальный размер 255 символов. По умолчанию в Delphi и FreePascal в качестве String используется тип AnsiString, память под который выделяется и освобождается компилятором
динамически, а максимальный размер строки в текущих реализациях составляет 2 гигабайта. Кроме того, в Delphi и Free Pascal в качестве string может использоваться тип UnicodeString, где применяется 16-битное представление символов в кодировке UCS-2, при этом средства преобразования из однобайтовых строк в многобайтовые и обратно в стандартной библиотеке FPC отсутствуют, но имеются в Delphi.
В Delphi 2009 и выше имеется конструкция для объявления AnsiString с определённой кодовой страницей:
type
CyrillicString = AnsiString(1251);
CP866String = AnsiString(20866);
Указатели
Паскаль поддерживает использование указателей (типизированные ^тип и нетипизированные pointer):
type
a = ^b;
b = record
x: Integer;
y: Char;
z: a;
end;
var
pointer_to_b:a;
Здесь переменная pointer_to_b — указатель на тип данных b, являющийся записью. Типизированный указатель может быть определён (опережающее определение) перед объявлением типа, на который он ссылается. Это одно из исключений к правилу, которое гласит: любой элемент (константа, тип, переменная, процедура, функция) должен быть объявлен перед тем, как используется.
Введение этого исключения позволяет организовывать рекуррентные определения структур данных, в том числе такие, как линейные списки, стеки, очереди, деревья, включая указатель на запись в описание этой записи.
Для типизированного указателя определена операция разыменования (её синтаксис: указатель^).
Чтобы создать новую запись и присвоить значение 10 и символ A полям x и y в ней, необходимы следующие операторы:
new(pointer_to_b); {выделение памяти указателю}
pointer_to_b^.x := 10; {разыменовывание указателя и обращение к полю записи}
pointer_to_b^.y := 'A';
pointer_to_b^.z := nil;
...
dispose(pointer_to_b); {освобождение памяти из-под указателя}
Для целей обращения к полям записей и объектов можно также использовать оператор with, как показано в примере:
new(pointer_to_b);
with pointer_to_b^ do
begin
x := 10;
y := 'A';
z := nil
end;
...
dispose(pointer_to_b);
Процедурный тип
В оригинальном языке Паскаль Йенсен и Вирта процедурный тип использовался только при описании формального параметра. Уже в TP существовал полноправный процедурный тип. В объявлении типа ставится
заголовок процедуры либо функции (без имени), обобщённо описывающий интерфейс подпрограммы.
Значение этого типа содержит указатель на подпрограмму с заголовком, соответствующую описанному в объявлении типа. С помощью идентификатора переменной может происходить вызов соответствующей
процедуры или функции.
Пример:
type myfunc=function:string;
function func1:string;
begin
func1:='func N 1'
end;
function func2:string;
begin
func2:='func N 2'
end;
var fun:myfunc;
begin
fun:=@func1;
writeln(fun) {происходит вызов функции func1}
end.
Операторы управления
Паскаль — язык структурного программирования, что означает, что программа состоит из выполняющихся
последовательно отдельных стандартных операторов, в идеале — без использования команды GOTO.
Пример:
while a <> b do {цикл с предусловием}
writeln('Ожидание');
if a > b then { условный оператор }
writeln('Условие выполнилось')
else { else-секция - может отсутствовать}
writeln('Условие не выполнилось');
for i := 1 to 10 do { итерационный цикл }
writeln('Итерация №', i:1);
for i in [1..10] do { итерационный цикл по множеству }
writeln('Итерация №', i:1); { появился в версии 2.4.0 }
with a do {Оператор With - метод ускорения доступа к полям записи}
begin
l:=1;
k:=2;
p:=-3;
end;
repeat { цикл с постусловием }
a := a + 1
until a = 10;
case i of { условный оператор множественного выбора }
0: write('ноль');
1: write('один');
2: write('два')
else write('неизвестное число') { else-секция - может отсутствовать}
end;
В операторах while, for, if, case в качестве выполняемого оператора может использоваться блок. Такая конструкция, представляющая собой обычный оператор или блок, называется сложным оператором.
В Turbo Pascal для управления процессом компиляции существуют директивы, которые помещаются в комментарии и позволяют переключать режимы работы компилятора — например, включать и отключать проверку операций ввода-вывода, переполнения.
Пример:
assign(inp,'text.txt');
{$I-} { отключение режима IO checking- генерации кода завершения программы в случае ошибки ввода-вывода }
{ (для случая, если файл не найден)}
reset(inp);
{$I+} { включение режима IO checking }
if IOresult=0 then begin { проверяем значение переменой ioresult(<>0 в случае ошибки ввода-вывода) }
...
close(inp);
end else writeln('file not found')
Существуют директивы, аналогичные директивам препроцессора C/C++ ($ifdef, $define, $include), они
обрабатываются компилятором в процессе компиляции.
Процедуры и функции
В Паскале подпрограммы делятся на процедуры и функции. При этом, функции явно возвращают значение (результат) определённого типа, а процедуры явно ничего не возвращают.
Синтаксически описание процедуры или функции состоит из заголовка, содержащего ключевое слово procedure или function, имени, за которым может следовать описание передаваемых (формальных) параметров в скобках. Для функции через символ «двоеточие»: указывается тип возвращаемого значения. Заголовок заканчивается символом «точка с запятой» ;. После заголовка следует тело, (возможно) содержащее секции описания локальных констант, типов, переменных, процедур, функций и (обязательно) содержащее блок операторов, после которого ставится символ «точка с запятой» ;.
Пример:
program mine(output);
var i : integer;
procedure print(var j: integer);
function next(k: integer): integer;
begin
next := k + 1
end;
begin
writeln('Всего: ', j);
j := next(j)
end;
begin
i := 1;
while i <= 10 do
print(i)
end.
Тело процедуры, как и программы, в свою очередь может содержать описания процедур и функций. Таким образом, процедуры и функции могут быть вложены друг в друга как угодно глубоко, при этом тело программы — самое верхнее в цепочке.
Причём содержимое секций описания переменных, типов, констант, внешнего тела (процедуры, функции, программы), расположенных перед описанием процедуры/функции, доступны внутри неё. Также, в большинстве диалектов из процедуры можно обращаться к параметрам внешней процедуры.