http://sulfurzona.ru/
News
Service
Magazine
Software (Battle City Game, Wallpaper manager, Superpad, VG-NOW, Puzzle Game, Netler Internet Browser, ..)
Wing-Thunder Game (fly simulator)
Dune Game (Dune III, Dune IV, Cheats, Forum, ..)
Games free
Turbo Pascal (Assembler, Docs, Sources, Debbugers, ..)
Books (Docs for developers)
Guest book
Компьютерная диагностика двигателя автомобиля (адаптер К-линии)Компьютерная диагностика двигателя автомобиля (адаптер К-линии)
 
 
Скачать игру Крыло-Гром (Wing-Thunder) бесплатно
 
 

Паскаль для новичков (часть 4)

 

Типизированные константы

 
Автор: Владислав Демьянишин
 
Паскаль для новичковДополнительно к обычным константам Turbo Pascal допускает использование качественно новых объектов – типизированных констант. Типизированные константы – это просто переменные, которые описываются вместе с обычными константами и, как обычные константы, получают начальное значение. Аналогично переменным, типизированные константы имеют тип, который задается при их описании, а также могут принимать НОВЫЕ значения (например, посредством оператора присваивания).
 
Таким образом, название “константа” в данном случае является достаточно условным. Такие константы можно использовать точно так же, как и обычные переменные таких же типов.
Прежде, чем привести Вам пример, хочу сказать пару слов о стандартной функции WriteLn. В Turbo Pascal есть функция Write,
которая выводит на экран значение аргумента, указанного в ней, т.е.
строка
 
write(‘Привет!’);
 
выдаст в текущей позиции экрана строку “Привет!” или строка
 
write(MyVar);
 
выдаст в текущей позиции экрана строку с числовым значением переменной MyVar. Так вот, функция WriteLn выполняет то же самое что и функция Write, но после вывода строки на экран переводит текущую позицию экрана (курсор, каретку) на следующую строку. Я буду использовать в примерах функцию WriteLn, чтобы выводить результаты примеров на экран.
 
Примеры описания типизированных констант:
 
const
Max : integer = 10000;
Min = 0; { Обычные и типизированные константы могут
описываться вместе}
MySet : set of char = [‘a’..’z’];
MyArray : array [1..3] of color = ( Red, Yellow, Yellow );
 
Типизированные константы инициализируются ТОЛЬКО ОДИН раз – в начале выполнения всей программы. Таким образом, при каждом новом вызове в какую-либо подпрограмму (процедуру, функцию) описанные в ней типизированные константы заново не инициализируются. Простой пример для демонстрации выше сказанного:
 
Program Example;
 
procedure MyFirst;
const Max : integer = 1000;
begin
writeln(‘Max = ’,Max);
Max := 2010;
writeln(‘Max = ’,Max);
end;
 
begin
MyFirst;
MyFirst;
end.
 
Когда текст программы набран в окне редактирования, его можно сохранить на диск. Для этого надо нажать F2 и в появившемся окне “Save File as” набрать имя, под которым следует сохранить данную программу, например “example”, и нажать Enter. В результате мы увидим в заглавии окна редактирования название нашей программы “example.pas”.
 
Теперь нам нужно запустить эту программу на выполнение, нажав клавиши Ctrl+F9. Но что получается. При запуске программы Example экран едва погас и снова мы видим на экране все то же окно редактирования программы. А где же результаты выполнения? Чтобы увидеть результат выполнения этой программы, следует нажать клавиши Alt+F5, и вот что мы увидим на экране:
 
Max = 1000;
Max = 2010;
Max = 2010;
Max = 2010;
 
Рассмотрим полученный результат. В первой строке значение константы Max равно ее начальному (инициализированному) значению. Во второй строке значение уже другое, так как в процедуре MyFirst в типизированную константу заносится значение 2010. В третьей строке значение константы Max не изменилось, хотя наверно кто-то из читателей, затаив дыхание, все же надеялся что при повторном вызове подпрограммы MyFirst константа Max будет вновь инициализирована значением 1000. И в последней строке естественно значение 2010. Ну, что я Вам говорил, т.е. константы, описанные в подпрограммах, при повторном вызове подпрограммы заново не инициализируются. А кто сомневался – выходи по одному :o)
Чтобы вернуть окно редактирования на экран следует повторно нажать клавиши Alt+F5.
 
1) Константы простых, строковых, ссылочных и процедурных типов. Описание типизированных констант с простым типом достаточно очевидно, например:
 
const
Pi : real = 3.1415;
StopChar : char = #13;
Diap : 0..100 = 1;
 
Следует иметь в виду, что типизированные константы не являются взаимозаменяемыми с обычными константами. Так например, если обычные константы можно использовать в описании других констант или типов:
 
const
Max = 100;
type
Diapason = 0..Max;
 
то аналогичное использование типизированных констант не допускается. Так, НЕКОРРЕКТНЫМ является следующее описание массива:
 
const
Min : integer = 0;
Max : integer = 100;
var
M : array [Min..Max] of byte;
 
В подобных случаях следует помнить, что типизированные константы фактически являются переменными с заданными начальными значениями.
Описания констант строкового типа также достаточно очевидны:
 
const
Title : string = ‘Заголовок’;
EndOfLine : string[2] = #13#10;
Answer : string[3] = ‘No’;
 
Для констант указательных (ссылочных) типов допустима инициализация заданием константного выражения ссылочного типа (“адресного выражения”), т.е. такого выражения, которое может быть вычислено при компиляции программы и значение которого имеет ссылочный тип, например:
 
var
X : real;
const
PtrX : ^real = @X;
 
Т.е. мы описываем константу-указатель на переменную, которая уже существует.
Аналогично, типизированные константы процедурных типов должны инициализироваться идентификаторами подпрограмм, совместимых по присваиванию с типом константы, например:
 
type
TMyCode = procedure ( Code : integer );
 
procedure MyCode ( Code : integer ); far;
begin
writeln(‘Код = ’, Code);
end;
 
const
CodeOutPut : TMyCode = MyCode;
 
2) Константы типа массив. Для типизированных констант регулярных типов в качестве начального значения необходимо задать изображение массива, которое строится из списка изображений элементов массива, разделяемых запятыми. Весь список заключается в круглые скобки, например:
 
type
Status = ( Active, Passive, Waiting );
TaskStatus = array [Status] of string[7];
const
StrStatus : TaskStatus = ( ‘Active’, ‘Passive’, ‘Waiting’ );
 
или
 
const
Vota : array [1..3] of string[7] = ( ‘Да’, ‘Нет’, ‘Не знаю’ );
Row : array [1..9] of byte = ( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
 
Допускается определение типизированной константы как многомерного массива. В этом случае подмассивы-элементы многомерного массива заключаются в отдельные круглые скобки.
Например, описание
 
type
Cube = array [1..2, 1..2, 1..2] of byte;
const
MyCube : Cube = ((( 1, 2 ), ( 3, 4 )), (( 5, 6 ), ( 7, 8 )));
 
var j,k,p:integer;
 
begin
for j:=1 to 2 do
     for k:=1 to 2 do
          for p:=1 to 2 do
               writeln('MyCube [', j, ',', k, ',', p,'] = ',MyCube[j,k,p]);
end.
 
С оператором For я немного забежал вперед. Таким образом попытаемся вывести на экран содержимое инициализированного массива-константы, перебирая все элементы этого массива. После запуска этой программы-примера (клавиши Ctrl+F9) получим на экране результат (клавиши Alt+F5):
 
MyCube[1,1,1] = 1
MyCube[1,1,2] = 2
MyCube[1,2,1] = 3
MyCube[1,2,2] = 4
MyCube[2,1,1] = 5
MyCube[2,1,2] = 6
MyCube[2,2,1] = 7
MyCube[2,2,2] = 8
 
Помните, что массив должен быть проинициализирован целиком, т.е. число элементов изображения массива и количество элементов в описании типа массива должны быть равны.
 
3) Константы типа запись. Начальные значения для констант комбинированных типов задаются в виде списка пар вида “идентификатор поля записи – значение поля записи”. Элементы пар разделяются двоеточием, пары отделяются друг от друга точкой с запятой, а весь список пар заключается в круглые скобки:
 
type
TPoint = record
             X, Y : real;
             end;
const
Center : TPoint = (X:10.0 ; Y:10.0);
 
или
 
type
TLine = array [1..2] of TPoint;
const
MyLine : TLine = (( X:1; Y:2 ), ( X:10; Y:10 ));
 
или
 
type
TDate = record
             Name : ( Mon, Tue, Wed, Thu, Fri, Sat, Sun );
             Num : 1..31;
             Month : 1..12;
             end;
const
SomeDate : Tdate = ( Name:Mon; Num:11; Month:3 );
 
Поля должны указываться в том же порядке, как они следуют в определении типа записи. Должны быть проинициализированы все поля.
 
4) Константы типа множество. Типизированные константы множественных типов инициализируются изображениями множеств, с той лишь разницей, что в данном случае это изображение должно строиться только из константных значений.
Примеры:
 
type
Digits = set of 0..9;
const
MyDigits : Digits = [0, 2, 4, 6, 8];
 
или
 
const
Indexes : set of byte = [1..10, 20, 88, 100..200];
 
5) Константы объектового типа. Начальные значения для констант объектовых типов задаются точно так же, как и начальные значения для комбинированных типов. При этом методы объектовой константы инициализировать не надо. Кроме того, если тип объектовой константы содержит виртуальные методы, то для такой константы не нужно вызывать метод ее конструктора (что является обязательным для объектовых переменных с виртуальными методами), так как компилятор обеспечит автоматическое выполнение конструктора. Подробнее об объектовых типах будет сказано в главе “Средства объектно-ориентированного программирования”;
 

Преобразование типов. Совместимость типов

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

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

 
Pascal содержит группу стандартных функций, специально предназначенных для преобразования типов(см. таблицу 1).
Пример:
 
type
TDay = (Mon, Tue, Wed, Thu, Fri, Sat, Sun);
var
MyDay : TDay;
 
begin
writeln(odd(5));
writeln(odd(6));
writeln(trunc(112.327));
writeln(trunc(52));
writeln(round(112.327));
writeln(round(112.727));
MyDay := Mon;
writeln(Ord(MyDay));
MyDay := Fri;
writeln(Ord(MyDay));
writeln(Ord(Tue));
writeln(Ord('A'));
writeln(Chr(65));
writeln(Ord(true));
writeln(Ord(false));
end.
 
выдаст на экран такой результат:
 
TRUE
FALSE
112
52
112
113
0
4
1
65
A
1
0
 
И так, число 5 нечетное и в первой строке имеем True, а во второй строке соответственно False, так как число 6 четное. Затем 112 как результат округления числа 112.327 методом отсечения дробной части. Ну округление числа 52 в комментариях не нуждается, чего его округлять, когда оно целое, но пускай для примера будет :o). Потом 112 как результат округления 112.327 до ближайшего целого,
 
тут ничего интересного, а вот 113 от числа 112.727 – совсем другое дело. В следующей строке результат 0 так как в переменную MyDay было занесено значение Mon (понедельник), которое соответствует нулю, так как идет первым в описании типа TDay, а все элементы перечислимых типов нумеруются начиная с нуля. Дальше стоит число 4, ведь в переменную MyDay было записано значение Fri (пятница), которое соответствует числу 4. В следующей строке аналогично число 1 соответствующее Tue (вторник). Число 65 соответствует коду ASCII латинского символа “A” и, естественно наоборот, символ “A” можно получить с помощью конструкции Chr(65). Ну и для полной ясности выясним каким числам соответствуют идентификаторы-константы True (1) и False (0) и, исходя из этого, при сравнении двух булевских выражений True всегда будет больше чем False.
 

Явные преобразования

 
Существует специальная конструкция явного преобразования типа. Эта конструкция носит название приведения типа переменной. Приведение не осуществляет никаких операций с переменной (как, например, операции Round и Trunc), а просто позволяет трактовать переменную одного типа, как переменную некоторого другого типа.
Общий вид приведения типа следующий:
 
тип ( переменная )
 
Пример, пусть имеется целая переменная Simb со следующим описанием:
 
var
Simb : 0..255;
 
Если необходимо присвоить этой переменной значение символьного типа, то присвоение вида
 
Simb := ’A’;
 
будет недопустимо из-за несоответствия типов в левой и правой частях. Однако, употребив приведение типа, мы можем достичь цели:
 
char(Simb) := ‘A’;
 
Здесь мы трактуем переменную Simb как переменную символьного значения, т.е. в данном выражении левая и правая части могут быть приравнены.
Конструкция приведения типа может находиться во всех позициях, в которых допускается вхождение переменной. При этом нужно помнить, что тип данной конструкции всегда определяется идентификатором типа перед скобками. Кроме того, следует учитывать, что размер переменной (число байтов, занимаемых этой переменной) ДОЛЖЕН БЫТЬ РАВЕН размеру типа, идентификатор которого указан в приведении.
Приведу еще один пример. Пусть имеются следующие описания:
 
type
TDays = ( Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday );
var
aDay : TDays;
Num : byte;
 
Тогда допустимы такие действия:
 
TDays(Num) := Monday; { Num = 0 }
aDay := TDays(Num); { aDay = Monday }
Num := byte(Friday); { Num = 4 }
 
Обратите внимание, что эквивалентом последнего присваивания будет следующее:
 
Num := Ord(Friday);
 
Можно приводить тип не только переменных но и произвольных выражений:
 
aDay := TDays(Num+1);
Num := byte(Pred(Friday));
 
Тип выражения в скобках и идентификатор типа перед скобками должны являться либо оба дискретными типами, либо оба ссылочными типами. Если один дискретный тип преобразуется к другому, то такое преобразование может привести к усечению или увеличению размера памяти, по сравнению с исходным значением. При этом возможна проверка на нахождение значения в допустимых границах. Например, выполнение следующей программы:
 
var
Long : longint;
Int : integer;
 
begin
Long := 1234567;
Int := integer(Long+1);
writeln(Int);
end.
 
приведет к выводу на экран значения –10616 (т.е. значение типа longint (размер 4 байта) в процессе приведения к типу integer (размер 2 байта) будет “урезано” с 4 байт до 2 байт).
В том случае, если значение расширяется (т.е. приводится к большему по размерам типу), его знак всегда сохраняется.
 

Эквивалентность типов

 
Развитая система типов языка Pascal, возможность определения новых типов, а также принцип строгой типизации требует точного определения, какие типы описывают идентичные множества значений, т.е. эквивалентны. В языке Pascal принят принцип именной эквивалентности, который можно сформулировать так:
Два типа T1 и T2 являются эквивалентными, если выполняется одно из двух условий:
 
1) T1 и T2 представляют собой ОДИН И ТОТ ЖЕ идентификатор типа, например:
 
type
T1 = integer;
T2 = integer;
 
2) Тип T2 описан с использованием типа T1 с помощью непосредственного равенства вида
 
type
T1 = integer;
T2 = T1;
 
или посредством цепочки таких равенств
 
type
T1 = integer;
T2 = T1;
T3 = T2;
 
Типы T1 и T2 являются эквивалентными, так как T2 описан непосредственно через T1; тип T3 эквивалентен T1, так как он описан через T1 посредством цепочки равенств.
Данное определение налагает достаточно жесткие ограничения. Так например, для следующих описаний
 
type
A1 = array [1..10] of integer;
A2 = array [1..10] of integer;
 
Типы A1 и A2 НЕ ЯВЛЯЮТСЯ эквивалентными, так как они не удовлетворяют приведенному определению (один тип не описан через другой). Две переменные, описанные так:
 
var
V1, V2 : array [1..10] of integer;
 
Имеют эквивалентные типы, поскольку их описания нераздельны. С другой стороны, описания:
 
var
V1 = array [1..10] of integer;
V2 = array [1..10] of integer;
V3, V4 : A1;
 
означают, что типы переменных V3 и V4 эквивалентны, а типы переменных V1 и V2 не эквивалентны ни друг другу, ни типу переменных V3 и V4.
 
Дополнения к статье для вставки на этапе верстки:
(Стандартные функции преобразования типов) Таблица 1.
Имя функции Тип аргумента
Преобразование и тип результата
Odd Целый
Выдает true, если аргумент нечетный и false, если аргумент четный
Trunc Вещественный
Выдает целую часть аргумента (дробная часть отбрасывается)
Round Вещественный
Выдает аргумент, округленный до ближайшего целого
Ord Дискретный
Результат – целый порядковый номер (нумерация от 0) значения аргумента в данном дискретном типе
Chr 0..255
Выдает символьное значение (символ) с заданным в аргументе порядковым номером
 
Продолжение следует…
 
© Владислав Демьянишин
 
На нашем сайте можно не только бесплатно скачать игры, но и документацию и книги по программированию на MIDLetPascal, Turbo Pascal 6, Turbo Pascal 7, Borland Pascal, по программированию устройств Sound Blaster, Adlib, VESA BIOS, справочник Norton Guide и много другой полезной информации для программистов, включая примеры решения реальных задач по созданию резидентных программ.
 

Журнал > Программирование > Паскаль для новичков (Turbo Pascal, Assembler) > Паскаль для новичков (часть 4). Типизированные константы. Преобразование типов. Совместимость типов
 
 
 
 
 
 
На главную страницу На предыдущую страницу На начало страницы