Порядковые типы данных в паскале. Учебник по программированию

24.06.2019

Простые типы

Порядковые

Вещественные

Дата-время

Логические

Символьный

Перечисляемый

Тип-диапазон

Рисунок 1 – Простые типы данных

Порядковые типы

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

Функции, предназначенные для работы с порядковыми типами, приведены в таблице 1.

Таблица 1 – Функции для работы с порядковыми типами.

Целые типы

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

Таблица 2 – Целочисленные типы

Наименование

Длина, байт

Диапазон значений

2147483648 … +2147483647

0 … 2147483647

0 … 4294967295

263 … 263 -1

Обратите внимание на то, чтоObject Pascal осуществляет автоматическое приведение типов. Например, там, где в качестве аргумента допустимо использовать переменную типа Word, допускается использовать переменную типа Byte, но не наоборот. Общее правило таково вместо одного типа целочисленной переменной можно использовать другой тип целочисленной переменной если их диапазоны значений вкладываются друг

в друга.

В таблице 3 приведены некоторые функции для работы с целочисленными переменными.

Таблица 3 – Функции для работы с целыми числами

При действиях с целыми числами тип результата будет соответствовать типу операндов, а если операнды относятся к различным целым типам, – общему типу, который включает в себя оба операнда. Например, для типов ShortInt и Word общим типом будет Integer.

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

Листинг 1

{$IFDEF FPC} {$MODE DELPHI}

{$APPTYPE CONSOLE} program InOutPrg; var x: Word; begin

Для того чтобы включить контроль переполнения, необходимо указать директиву компилятора {$Q+} для отключения контроля – {$Q-}.

Вместо {$Q+} можно использовать{$OVERFLOWCHECKS ON} , а вместо {$Q-} {$OVERFLOWCHECKS OFF}

Измените программу, приведенную в листинге 1, поместив в нее директиву{$Q+} первой строкой. Запустите ее на выполнение, программа должна аварийно завершиться.

Для целочисленных переменных безопаснее всего применять тип Integer, т. к. диапазон

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

Логические типы

Переменная логического типа может принимать только два значения True (истина) и False (ложь). Логические типы приведены в таблице 4.

Таблица 4 – Логические типы

Для работы с логическими типами используйте тип Boolean, остальные типы были добавлены в Object Pascal для совместимости с программами написанными на других языках программирования.

Символьный тип

Символьный тип, как следует из его названия, предназначен для хранения кода символа. Внутренняя структура типа совпадает с внутренней структурой беззнаковых целых чисел. Object Pascal поддерживает два символьных типаAnsiChar иWideChar. Характеристики этих типов приведены в таблице5.

Таблица 5 – Символьные типы

Описание

Код символа в кодировке ANSI. Таблица символов этого стандарта

состоит из 256 символов, причем первые 128 символов жестко

определены стандартом, а остальные 128 могут содержать любые

символы. Во вторую часть кодовой таблицы обычно помещают

символы национальных алфавитов. Недостатком данного

представления символов является то, что невозможно отображение

сразу символов более

чем 2-х алфавитов.

Символ в формате UNICODE. Таблица символов содержит 65536

символов. В данной таблице находятся символы всех алфавитов.

Char1

Является псевдонимом типа AnsiChar

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

function chr(X:byte):char

Для обратного преобразования используется функция

1 В Object Pascal тип Char является основным. В следующих версиях тип Char может стать псевдонимом для типа WideChar.

function ord(X:char):byte;

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

ch:="A" ;

ch:=#97; //97 – код символа "A".

Например

var ch:char; code: byte;

begin ch:="A" ;

ch:=chr(32); //32 - соответствует коду клавиши пробел

end.

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

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

<имя типа> = (id, id, id,...);

Здесь «имя типа» – идентификатор Object Pascal , «id» – идентификаторObject Pascal .

Например, тип описывающий некоторый фиксированный набор цветов

Применение перечисляемых типов делает программы более наглядными и повышает надежность программ. Пусть определены следующие типы:

type TColors = (red, green, white, yellow);

TDays=(monday, tuesday, wednesday);

Определены переменные

var col:TColors;

то допустимы следующие операторы

col:=Succ(green);

day:=Pred(tuesday);

но не допустимы

Максимальное количество перечисляемых значений зависит от реализации. В настоящее время размер переменной перечисляемого типа равен 4 байта, что соответствует 232 различных значений, т. е. во внутреннем представлении перечисляемый тип представляет собой тип LongWord.

Как говорилось выше , можно поместить определение типа сразу, после двоеточия, например

var col: (red, green, white, yellow); day: (monday, tuesday, wednesday);

Тип-диапазон

Тип диапазон представляет собой подмножество некоторого базового порядкового типа. Типдиапазон задается границами своих значений.

<мин. зн.> .. <макс. зн.>

Глава II. Типы данных.

§7. Типы данных. Порядковые типы языка Pascal.

Типы данных.

Во втором параграфе мы немного узнали о типах данных. Это было необходимо, что бы начать программировать. В данном параграфе мы подробно рассмотрим все типы данных существующие в Pascal.

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

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

У вас должен возникнуть уместный вопрос: почему в одном килобайте 1024 байта. Дело в том, что приставка, например, кило в обычной жизни обозначает, что число надо помножить на тысячу. Например, 5 километров – это 5000 метров. А вот при обозначении количества памяти приставка кило обозначает, что число надо помножить на 1024. Такое число возникло не просто случайно, оно равно двум в степени десять . В своё время первые программисты договорились и решили объём памяти в 1024 байта называть одним килобайтом. Соответственно 1 килобайт, помноженный на один килобайт, будет равен одному мегабайту. А один мегабайт, помноженный на один мегабайт, будет равен одному гигабайту. И так далее.

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

Для примера можем посчитать, сколько элементарных ячеек содержится в оперативной памяти в один гигабайт. Один гигабайт – это 1024 мегабайта. Один мегабайт это 1024 килобайта. Соответственно в одном гигабайте содержится 1024 х 1024 = 1048576 килобайт. Ещё раз помножим на 1024 и получим 1073741824 байта. Помножим это число на 8 получим 8589934592 бит. Вот столько элементарных ячеек памяти содержится в оперативной памяти объёмом в один гигабайт.

Двигаемся дальше. Представим себе, что нам необходимо обработать 24 элементарных ячейки памяти, или говоря другими словами 24 бита. Содержание этих ячеек можно представить в виде списка. Например, он может быть таким:

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

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

00000001 00000010 00010100 00001101

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

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

Именно такая договорённость и есть типы данных. Т.е. используя определённый тип мы «договариваемся с компьютером», что определённое количество бит, будут обозначать определённое число или букву, или ещё что-то другое.

О двоичных цифрах сейчас мы говорить не будем, потому что на данном этапе в этом нет необходимости. Главное вы должны усвоить, что если вы хотите использовать, допустим, целое число, то вы должны выбрать тип целых чисел, если какое-либо дробное число, то тип real, если символ, то тип char и так далее.

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

Данной схемой вы можете пользоваться на первый порах, для выбора нужного типа, в дальнейшем она запомниться сама собой. А так же логика объединения типов в группы так же станет вам понятна.

Порядковые типы.

Особенностью порядковых типов является то, что переменная любого порядкового типа имеет конечное число возможных значений и то, что несколько переменных какого-либо порядкового типа можно расположить в порядке убывания или возрастания, т.е. упорядочить (отсюда и название). А так же то, что только переменные порядковых типов могут быть параметром цикла For to do.

Целые типы.

Как уже было сказано, переменная целого типа содержит в себе целое число. Мы изучили уже тип целых чисел Byte. Переменная такого типа может содержать в себе целое число от 0 до 255 включительно. Занимает оно в памяти компьютера 1 байт. Если нам понадобиться отрицательное число или число больше 255, тогда мы можем использовать тип Integer. Переменная такого типа может содержать в себе целые числа от -32768 до +32767 включительно. Однако такая переменная будет занимать в памяти 2 байта.

Название

Перевод

названия на русский

Размер

занимаемой

памяти в байтах

Диапазон

значений

от

до

Byte

Байт

ShortInt

Короткое целое

Word

Слово

65 535

Integer

Целое

32 768

32 767

LongInt

Длинное целое

2 147 483 648

2 147 483 647

Для удобства запоминания в таблице приведён перевод названий типов. В столбце диапазон значений приведённые числа входят в этот диапазон. Например, переменная типа Integer может содержать в себе число 32 767, а вот число 32768 уже не может.

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

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

Конечно в небольшой программе, которая будет работать на мощном современном компьютере, выбор не соответствующего типа (большего по размеру), ни как не скажется на работе этой программы, однако в больших программах эта оплошность может сказаться на быстродействии программы в целом. Например, пользователь будет ждать результата не 3 секунды, а 10. Конечно, если он его ждёт один раз в день то особо он не расстроится, а если он в течение всего дня должен получать результаты, то представьте, на сколько больше результатов он получить, если вы правильно выберите тип данных. То же самое относится и к типам данных, которые будут изучены позже.

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

Вместо операции деления, с целыми числами можно осуществлять следующие две операции:

div – целочисленное деление. (Получаем значение от деления как бы без дробной части);

mod – получение остатка от целочисленного деления.

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

Если использовать запись как в обычной математике, то:

9 div 4 = 2;

i,f: Integer ;

begin

Writeln("Введите два целых числа" );

Read(i,f);

Writeln(i, "/" ,f, "=" ,i div f, " остаток " ,i mod f);

end .

____________________________________________________

Введите два целых числа

13/5=2 остаток 3

Так же есть ещё одна функция для работы с целыми типами – Odd, которая возвращает True, если число нечётное и False, если число чётное. Пример:

var i: integer ;

begin

i:= 10 ;

If odd(i) then writeln("Число " ,i, " - нечётное." )

else writeln("Число " ,i, " - чётное." );

end .

___________________________________________________

Число 10 - чётное.

Стоит отметить следующий нюанс: если переменная целого типа имеет последнее значение диапазона, то при увеличении этой переменной на единицу она примет первое значение диапазона. И наоборот – если первое значение, то при уменьшении на единицу последнее. Например, если переменная А типа Byte имеет значение 255, тогда А+1 будет равно 0. Или если увеличить на два, то А+2=1. Ещё пример: если А=250, то А+20=14. Ещё пример, если А=0, то А-1=255. В таких ситуациях компилятор ошибку не выдаёт. При выполнении программы ошибки тоже не будет. Просто вы получите не правильное значение. Это обстоятельство так же должно быть критерием выбора правильного типа.

Как уже было сказано, в цикле For to do можно использовать переменную любого порядкового типа. Однако есть один нюанс. Если вы укажете после слова to число, выходящее за рамки возможных значений типа переменной, стоящей после слова For, то этот цикло не будет выполнен ни разу вообще. В данной ситуации только будет выполнен оператор присваивания находящийся после слова For, причём никаких сообщений об ошибках вы не получите. Например:

b: byte ;

begin

b:= 2 ;

Writeln(b);

For b:=- 5 to 5 do Writeln(b);

Writeln(b);

end.

______________________________

Обратите внимание, что код цикла выполнен не был, а переменной b было присвоено значение 251. Что произошло? В цикле For to do мы попытались присвоить переменной b значение, выходящее за рамки «рабочего» диапазона типа byte. Что сделал компьютер? Он, как бы, выполнил следующее арифметическое выражение: b=0-5. И произошло то, что было описано в предыдущем абзаце. Т.е. b стало равно 251, как это видно из результата работы программы.

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

Вывод целых чисел в виде таблицы.

Рассмотрим задачу, которая сформулирована следующим образом: необходимо вывести на экран таблицу чисел от 1 до 100. В каждой строчке должно находиться по 10 чисел, соответственно должно получиться 10 столбиков.

Для решения задачи будем рассуждать следующим образом: мы можем с помощью процедур write и writeln вывести каждое число в отдельности в нужной последовательности. Однако нам необходимо, автоматизировать этот процесс, и что бы код занимал, как можно меньше строчек. Поэтому нам необходимо использовать цикл. В данной ситуации, при работе с целыми числами, наилучшим образом подходит цикл For to do.

Попробуем с помощью этого цикла вывести десять чисел от 1 до 10 в одну строчку:

var i: integer ;

begin

For i:= 1 to 10 do

write(i: 4 );

end .

________________________________________

1 2 3 4 5 6 7 8 9 10

Обратите внимание, что для вывода переменной i на экран задано 4 символа. Это для того, что бы последнее число 100 было отделено от предыдущего 99 одним пробелом.

Мы организовали автоматический вывод 10 чисел в одну строчку. Теперь надо подумать, как вывести все 100 чисел. Для этого нам необходимо после вывода каждых новых десяти чисел переходить на новую строчку. Сделаем это по следующему условию: если число делиться без остатка на 10, то вызываем процедуру Writeln:

var i: integer ;

begin

For i:= 1 to 100 do

Begin

write(i: 4 );

if (i mod 10 ) = 0 then writeln;

end ;

end .

_________________________________________

1 2 3 4 5 6 7 8 9 10

11 12 13 14 15 16 17 18 19 20

21 22 23 24 25 26 27 28 29 30

31 32 33 34 35 36 37 38 39 40

41 42 43 44 45 46 47 48 49 50

51 52 53 54 55 56 57 58 59 60

61 62 63 64 65 66 67 68 69 70

71 72 73 74 75 76 77 78 79 80

81 82 83 84 85 86 87 88 89 90

91 92 93 94 95 96 97 98 99 100

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

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

Задачи.

1. Пользователь вводит целое число, не используя функцию Odd, определить, является число чётным или нет.

2. Имеем 4 числа. В первой строчке вывести числа, которые делятся на 3 без остатка, во второй – которые делятся на три с остатком. Если чисел, которые делятся без остатка или делятся с остатком, нет, то вывести соответствующее сообщение. В третьей строчке под числом, которое делится с остатком вывести остаток от деления на 3.

3. Составьте свою функцию определения чётное число или нет на основе операции mod, а так же программу, демонстрирующую пример использования этой функции.

4. Вывести на экран только чётные числа от 1 до 100 в виде таблицы. В таблице должно быть 9 столбиков.

Решение.

var i: integer ;

begin

writeln("Введите целое число." );

Read(i);

if (i mod 2 )= 0 then writeln("Число " ,i, " - чётное." )

end .

______________________________________________________

Введите целое число.

Число 57 - нечётное.

var i,k,l,m: integer ;

S1,s2: longint ;

begin

i:= 3 ;k:= 45 ;l:= 21 ;m:= 1 ;

Writeln("Имеем следующие числа: " ,i, " " ,k, " " ,l, " " ,m);

S1:= 0 ;s2:= 0 ;

if (i mod 3 ) = 0 then s1:=s1+ 1 else s2:=s2+ 1 ;

if (k mod 3 ) = 0 then s1:=s1+ 1 else s2:=s2+ 1 ;

if (l mod 3 ) = 0 then s1:=s1+ 1 else s2:=s2+ 1 ;

if (m mod 3 ) = 0 then s1:=s1+ 1 else s2:=s2+ 1 ;

if s1 = 0 then write("Чисел, которые делятся на 3 без остатка нет." )

else write("Делятся на 3 без остатка: " );

if (i mod 3 ) = 0 then write(i, " " );

if (k mod 3 ) = 0 then write(k, " " );

if (l mod 3 ) = 0 then write(l, " " );

if (m mod 3 ) = 0 then write(m, " " );

Writeln;

if s2 = 0 then write("Чисел, которые делятся на 3 с остатком нет." )

else write("Делятся на 3 с остатком: " );

if (i mod 3 ) <> 0 then write(i: 4 );

if (k mod 3 ) <> 0 then write(k: 4 );

if (l mod 3 ) <> 0 then write(l: 4 );

if (m mod 3 ) <> 0 then write(m: 4 );

Writeln;

Write(" остаток: " );

if (i mod 3 ) <> 0 then write((i mod 3 ): 4 );

if (k mod 3 ) <> 0 then write((k mod 3 ): 4 );

if (l mod 3 ) <> 0 then write((l mod 3 ): 4 );

if (m mod 3 ) <> 0 then write((m mod 3 ): 4 );

end .

_________________________________________________________________________

Имеем следующие числа: 3 45 21 1

Делятся на 3 без остатка: 3 45 21

Делятся на 3 с остатком: 1

Остаток: 1

Function chetnost(i: integer ): boolean ;

begin

If (i mod 2 )= 0 then chetnost:= True

else chetnost:= False ;

end ;

Var i: integer ; b: boolean ;

begin

writeln("Введите целое число" );

Read(i);

B:=chetnost(i);

if b then writeln("Число " ,i, " - чётное." )

else writeln("Число " ,i, " - нечётное." );

end .

_____________________________________________

Введите целое число

Число 3 - нечётное.

var i: integer ;

Порядковыми (ordinal) называются типы, которым соответствуют данные, поддерживающие понятия «предшествующее значение» и «последующее значение». Например, для целого числа 5 можно определенно сказать, что ему предшествует число 4, а следующее за ним - число 6. С другой стороны невозможно сказать, какое число непосредственно предшествует вещественному числу 5.0.

В Object Pascal определены следующие порядковые типы:

– целые типы;

– символьные типы;

– булевы типы;

– ограниченные типы.

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

Таблица 6.1 – Функции для порядковых типов данных

Продолжение таблицы 6.1

6.1.1.1 Целые типы данных

Целые типы данных используются для представления целых чисел. Типами, обеспечивающими максимальную производительность, являются Integer и Cardinal . Оба типа занимают в памяти 4 байта и принимают значения в дапазоне: для Integer -2147483648..2147483647, для Cardina l 0..4294967295. В тех случаях, когда нужен больший диапазон чисел, можно использовать тип int64 .

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

Для целочисленных данных можно использовать и логические операции, такие как and, or, xor . Результат будет определяться применением соответствующей операции к каждой паре соответствующих бит двоичного представления чисел. При выполнении таких операций часто используют 16-ричное представление чисел. Признаком 16-ричного числа является знак $ перед числом, например $FF соответствует десятичному числу 255, а $100 соответствует десятичному числу 256.

Можно применять и операции сдвигов двоичных кодов числа влево (shl ) или вправо (shr ) на заданное число разрядов. Сдвиг вправо на один разряд соответствует целочисленному делению числа на 2. Сдвиг влево на один разряд соответствует умножению на 2. Например, в результате выполнения инструкции $FF shr 4, получим результат $0F.

6.1.1.2 Символьные типы данных

Символьные типы предназначены для представления символов. В Object Pascal можно использовать две разновидности символов:

– Типу Char соответствует множество из 256 символов, в котором символы упорядочены в соответствии с таблицей кодировки ANSI (American National Standard Code for Information Interchange). Каждый символ этого типа занимает 1 байт. Соответствие между кодом и соответствующим ему символом задается так называемой таблицей кодировки символов. Первая половина таблицы (коды от 0 до 127) используется для управляющих символов, цифр, латинских букв и наиболее распространенных символов, таких, как знаки препинания, знаки математических операций и т.п. Вторая половина таблицы (коды от 128 до 255) используется для национальных алфавитов и других символов.

– Типу WideChar соответствует множество символов Unicode, в котором каждый символ занимает 2 байта, и естественно, эта таблица символов может содержать очень большой список символов. Им соответствуют коды в диапазоне от 0 до 65535. Первые 256 символов в этом множестве соответствуют символам ANSI с соответствующими кодами.

В наших лабораторных работах мы будем использовать только типChar. Фрагмент таблицы кодировки символов представлен ниже, в таблице 6.2.

Таблица 6.2 – Кодировка некоторых символов ANSI

Символ Код Двоичное представление 16-ричное представление
Отсутствие символа 0000 0000 $00
Пробел 0010 0000 $20
! 0010 0001 $21
0011 0000 $30
0011 0001 $31
0011 0010 $32
0011 0011 $33
A 0100 0001 $41
B 0100 0010 $42
C 0100 0011 $43
a 0110 0001 $61
b 0110 0010 $62
А $C0
Б $C1
а 1110 0000 $E0
б 1110 0001 $E1
я 1111 1111 $FF

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

Символьные константы можно записывать разными способами. Для большинства символов можно использовать изображение этого символа, заключенное в одинарные кавычки. Например, ‘1’, ‘z’, ‘*’. Специальные символы удобно представлять с помощью их кода, в виде целого числа, которому предшествует знак #. Например, #0, #8, #13. Кроме того, любой символ может быть получен с помощью функции chr(), которой в качестве аргумента передается код символа. Например, chr(65) возвращает прописную латинскую букву ‘A’, а chr(255) – строчную букву ‘я’ кириллицы.

Обратное преобразование, то есть преобразование символа в код можно выполнить с помощью функции ord(). Например, ord(‘0’) вернет 48.

При вводе отдельных символов из компонентов класса TEdit, необходимо иметь в виду, что свойство text этих компонентов возвращает не символ, а строку символов. Чтобы получить отдельный символ этой строки следует использовать порядковый номер символа в строке, записывая его в квадратных скобках после имени строки символов. Например, Edit1.text.

Для символов применимы все операции сравнения. При этом сравниваются коды символов. Поэтому ‘б’ > ’Б’, и ‘а’ кириллицы больше, чем латинское ’a’.

Группы символов, которые соответствуют буквам, расположены таким образом, чтобы упростить преобразование больших букв в маленькие и наоборот. Разница в кодировке больших и маленьких букв и латинского и русского алфавита равна $20 или 32. Следовательно, чтобы превратить строчную букву в прописную, достаточно из ее кода вычесть 32. Число 32 можно и не помнить, так как его можно получить в результате вычитания кода прописной буквы из кода соответствующей строчной. Например, ord (z) – ord (Z), или оrd (a) – ord (A).

Особенность кодировки цифр состоит в том, что младший полубайт символа цифры соответствует ее числовому значению в двоичном представлении. Это позволяет легко преобразовывать код символа цифр в соответствующие числа с помощью логической операции and и маски $0F. Например, в результате операции ord (‘5’) and $0F получится число 5.

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

Ниже приведено два варианта такого преобразования.

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

var c: char; n: integer;

n:= ord(c)- 48; // что равносильно ord(c) –ord(‘0’);

Второй вариант такого преобразования использует операцию and $0F с маской $0F.

const maska = $0F; // константа равная двоичному числу 00001111

var c: char; n: integer;

n:= ord (c) and maska; // маска удаляет старший полубайт

6.1.1.3 Ограниченный тип данных.

Для порядковых типов можно задать поддиапазон их возможных значений – это и будет ограниченный тип.

Диапазон значений ограниченного типа задается выражением вида: <минимальное значение>..<максимальное значение>.

Например:

type TCaps = ‘A’..‘Z’;

var bigLetter: TCaps; month: 1..12;

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

Ограниченные типы используются, например, при объявлении массивов.

В компиляторе Object Pascal имеется опция, позволяющая включить проверку диапазона при присваивании значения переменной ограниченного типа – {$R+} . Её можно включить в том месте вашей программы, где нужно начать проверку диапазона, и выключить в любом месте опцией {$R-} . При попытке присвоить переменной ограниченного типа значение, выходящее за пределы заданного поддиапазона, сгенерируется исключение с сообщением “Range check error”.

Интервальный тип можно использовать для задания множества данных этого типа путем заключения интервала в квадратные скобки. Например, множество сточных русских букв можно задать таким образом ["а".."я"]. Для определения принадлежности некоторого символа к определенному таким образом множеству можно использовать операцию in , которая возвращает true, если символ принадлежит множеству и false – если не принадлежит. Например, результатом вычисления выражения ‘5’ in [‘0’..’9’], будет true.

К порядковым типам относятся (см. рис.4.1) целые, логический, символьный, перечисляемый и тип-диапазон. К любому из них применима функция ORD(X), которая возвращает порядковый номер значения выражения X. Для целых типов функция ORD(X) возвращает само значение X, т.е. ORD(X) = X для X, принадлежащего любому шелому типу. Применение ORD(X) к логическому, символьному и перечисляемому типам дает положительное целое число в диапазоне от 0 до 1 (логический тип), от 0 до 155 (символьный), от 0 до 65535 (перечисляемый). Тип-диапазон сохраняет все свойства базового порядкового типа, поэтому результат применения к нему функции ORD(X) зависит от свойств этого типа.

К порядковым типам можно также применять функции:

PRED (X) - возвращает предыдущее значение порядкового типа (значение, которое соответствует порядковому номеру ORD(X)- 1), т.е.

ORD(PRED(X)) = ORD(X) - 1;

SUCC (X) - возвращает следующее значение порядкового типа, которое соответствует порядковому номеру ORD(X) +1, т.е.

ORD(SUCC(X)) = ORD(X) + 1.

Например, если в программе определена переменная

то функция PRED(C) вернет значение "4", а функция SUCC(C) - значение "6".

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

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

Таблица 4.1

При использовании процедур и функций с целочисленными параметрами следует руководствоваться «вложенностью» типов, т.е. везде, где может использоваться WORD, допускается использование BYTE (но не наоборот), в LONGINT «входит» INTEGER, который, в свою очередь, включает в себя SHORTINT.

Перечень процедур и функций, применимых к целочисленным типам, приведен в табл.4.2. Буквами b, s, w, i, l обозначены выражения соответственно типа BYTE, SHORTINT, WORD, INTEGER и LONGINT, x - выражение любого из этих типов; буквы vb, vs, vw, vi, vl, vx обозначают переменные соответствующих типов. В квадратных скобках указывается необязательный параметр.

Таблица 4.2

Стандартные процедуры и функции, применимые к целым типам
Обращение Тип результата Действие
abs (x) x Возвращает модуль х
chr(b) Char Возвращает символ по его коду
dec (vx[, i]) - Уменьшает значение vx на i, а при отсутствии i -на 1
inc(vx[, i]) - Увеличивает значение vx на i, а при отсутствии i - на 1
Hi(i) Byte Возвращает старший байт аргумента
Hi(w) To же То же
Lo(i) " Возвращает младший байт аргумента
Lo (w) " То же
odd(l) Boolean Возвращает True, если аргумент - нечетное число
Random (w) Как у параметра Возвращает псевдослучайное число, равномерно распределенное в диапазоне 0...(w-l)
sgr (x) X Возвращает квадрат аргумента
swap (i) Integer Меняет местами байты в слове
swap (w) Word

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

а:= 32767; {Максимально возможное значение типа INTEGER}

х:= а + 2; {Переполнение при вычислении этого выражения!}

у:= LongInt(а)+2; {Переполнения нет после приведения переменной к более мощному типу}

WriteLn(x:10:0, у:10:0)

В результате прогона программы получим

Логический тип . Значениями логического типа может быть одна из предварительно объявленных констант FALSE (ложь) или TRUE (истина). Для них справедливы правила:

False < True;

succ(False)= True;

pred(True) = False.

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

for 1:= False to True do ....

Символьный тип. Значением символьного типа является множество всех символов ПК. Каждому символу приписывается целое число в диапазоне 0...255. Это число служит кодом внутреннего представления символа, его возвращает функция ORD.

Для кодировки используется код ASCII (American Standard Code for Information Interchange - американский стандартный код для обмена информацией). Это 7-битный код, т.е. с его помощью можно закодировать лишь 128 символов в диапазоне от 0 до 127. В то же время в 8-битном байте, отведенном для хранения символа в Турбо Паскале, можно закодировать в два раза больше символов в диапазоне от 0 до 255. Первая половина символов ПК с кодами 0...127 соответствует стандарту ASCII (табл. 4.3). Вторая половина символов с кодами 128...255 не ограничена жесткими рамками стандарта и может меняться на ПК разных типов (в прил.2 приведены некоторые распространенные варианты кодировки этих символов).

Таблица 4.3

Кодировка символов в соответствии со стандартом ASCII
Код Символ Код Символ Код Символ Код Символ
NUL BL ® "
ЗОН ! A a
STX " В b
ЕТХ # С с
EOT $ D d
ENQ % E e
АСК & F f
BEL " G g
BS ( H h
НТ ) I i
LF * J j
VT + k k
FF , L i
CR - M m
SO . N n
SI / О
DEL p P
DC1 Q q
DC2 R r
DC3 S s
DC4 T t
NAK U u
SYN V V
ETB w w
CAN X X
EM У У
SUB : z z
ESC / [ {
FS < \ l
GS = ] }
RS > ^ ~
US ? - n

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

Символ Код Значение
BEL Звонок; вывод на экран этого символа сопровождается звуковым сигналом
НТ Горизонтальная табуляция; при выводе на экран смещает курсор в позицию, кратную 8, плюс 1 (9, 17, 25 и т.д.)
LF Перевод строки; при выводе его на экран все последующие символы будут выводиться, начиная с той же позиции, но на следующей строке
VT Вертикальная табуляция; при выводе на экран заменяется специальным знаком
FF Прогон страницы; при выводе на принтер формирует страницу, при выводе на экран заменяется специальным знаком
CR Возврат каретки; вводится нажатием на клавишу Enter (при вводе с помощью READ или READLN означает команду «Ввод» и в буфер ввода не помещается; при выводе означает команду «Продолжить вывод с начала текущей строки»)
SUB Конец файла; вводится с клавиатуры нажатием Ctrl-Z; при выводе заменяется специальным знаком
SSC Конец работы; вводится с клавиатуры нажатием на клавишу ESC; при выводе заменяется специальным знаком

К типу CHAR применимы операции отношения, а также встроенные функции: СНR(В) - функция типа CHAR; преобразует выражение В типа BYTE в символ и возвращает его своим значением;

UPCASE(CH) - функция типа CHAR; возвращает прописную букву, если СН -строчная латинская буква, в противном случае возвращает сам символ СН, например:

cl:= UpCase("s") ;

c2:= UpCase ("Ф") ;

WriteLn(cl," ",c2)

Так как функция UPCASE не обрабатывает кириллицу, в результате прогона этой

программы на экран будет выдано

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

colors =(red, white, blue);

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

ТипМесяц=(янв,фев,мар,апр,май,июн,июл,авг,сен,окт,ноя,дек);

месяц: ТипМесяц;

if месяц = авг then WriteLn("Хорошо бы поехать к морю!");

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

TypeMonth=(jan,feb,mar,may,jun,jul,aug,sep,oct,nov,dec);

month: TypeMonth;

if month = aug then WriteLn("Хорошо бы поехать к морю!");

Соответствие между значениями перечисляемого типа и порядковыми номерами этих значений устанавливается порядком перечисления: первое значение в списке получает порядковый номер 0, второе - 1 и т.д. Максимальная мощность перечисляемого типа составляет 65536 значений, поэтому фактически перечисляемый тип задает некоторое подмножество целого типа WORD и может рассматриваться как компактное объявление сразу группы целочисленных констант со значениями О, 1 и т.д.

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

colors = (black, red, white);

ordenal= (one, two, three);

days = (monday, tuesday, Wednesday);

С точки зрения мощности и внутреннего представления все три типа эквивалентны:

ord(black)=0, ..., ord(white)=2,

ord(one)=0, ...ord(three)=2,

ord(monday)=0, ...ord(Wednesday)=2.

Однако, если определены переменные

col:colors; num:ordenal;

то допустимы операторы

num:= succ(two);

day:= pred(tuesday);

но недопустимы

Как уже упоминалось, между значениями перечисляемого типа и множеством целых чисел существует однозначное соответствие, задаваемое функцией ORD(X). В Турбо Паскале допускается и обратное преобразование: любое выражение типа WORD можно преобразовать в значение перечисляемого типа, если только значение целочисленного выражения не превышает мощное1™ перечисляемого типа. Такое преобразование достигается применением автоматически объявляемой функции с именем перечисляемого типа (см. п. 4.4). Например, для рассмотренного выше объявления типов эквивалентны следующие присваивания:

col:= colors(0);

Разумеется, присваивание

будет недопустимым.

Переменные любого перечисляемого типа можно объявлять без предварительного описания этого типа, например:

col: (black, white, green);

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

<мин.знач.>..<макс.знач.>

Здесь <мин.знач. > - минимальное значение типа-диапазона;

<макс.знач.> - максимальное его значение.

Например:

digit = "0".."9";

Тип-диапазон необязательно описывать в разделе TYPE, а можно указывать непосредственно при объявлении переменной, например:

Ichr: "A".."Z";.

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

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

days = (mo,tu,we,th,fr,sa,su);

WeekEnd = sa .. su;

то ORD(W) вернет значение 5 , в то время как PRED(W) приведет к ошибке.

В стандартную библиотеку Турбо Паскаля включены две функции, поддерживающие работу с типами-диапазонами:

НIGН(Х) - возвращает максимальное значение типа-диапазона, к которому принадлежит переменная X;

LOW(X) -возвращает минимальное значение типа-диапазона.

Следующая короткая программа выведет на экран строку

WriteLn(Low(k),"..",High(k))

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

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

Математически это записывается так:

(-1) s × M × B E , где s - знак, B-основание, E - порядок, а M - мантисса.

Основание определяет систему счисления разрядов. Математически доказано, что числа с плавающей запятой с базой B=2 (двоичное представление) наиболее устойчивы к ошибкам округления, поэтому на практике встречаются только базы 2 и, реже, 10. Для дальнейшего изложения будем всегда полагать B=2, и формула числа с плавающей запятой будет иметь вид:

(-1) s × M × 2 E

Что такое мантисса и порядок? Мантисса – это целое число фиксированной длины, которое представляет старшие разряды действительного числа. Допустим наша мантисса состоит из трех бит (|M|=3). Возьмем, например, число «5», которое в двоичной системе будет равно 101 2 . Старший бит соответствует 2 2 =4, средний (который у нас равен нулю) 2 1 =2, а младший 2 0 =1. Порядок – это степень базы (двойки) старшего разряда. В нашем случае E=2. Такие числа удобно записывать в так называемом «научном» стандартном виде, например «1.01e+2». Сразу видно, что мантисса состоит из трех знаков, а порядок равен двум.

Допустим мы хотим получить дробное число, используя те же 3 бита мантиссы. Мы можем это сделать, если возьмем, скажем, E=1. Тогда наше число будет равно

1.01e+1 = 1×2 1 +0×2 0 +1×2 -1 =2+0,5=2,5

Очевидно, что таким образом одно и то же число можно представить по-разному. Рассмотрим пример с длиной мантиссы |M|=4. Число «2» можно представить в следующем виде:

2 = 10 (в двоичной системе) = 1.000e+1 = 0.100e+2 = 0.010e+3.

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

Это экономит один бит (так как неявную единицу не нужно хранить в памяти) и обеспечивает уникальность представления числа. В нашем примере «2» имеет единственное представление («1.000e+1»), а мантисса хранится в памяти как «000», т.к. старшая единица подразумевается неявно. Но в нормализованном представлении чисел возникает новая проблема - в такой форме невозможно представить ноль.

  • Анализ данных с помощью команд Подбор параметра и Поиск решения
  • Анализ и интерпретация данных экспериментально-психологического исследования.
  • Анализ исходных данных. Технические нормативы городской дороги.
  • АНАЛИЗ ПОЛУЧЕННЫХ ДАННЫХ. ПРИНЯТИЕ РЕШЕНИЯ О ДОСТАТОЧНОСТИ ИЛИ НЕДОСТАТОЧНОСТИ ХАРАКТЕРИСТИК ВОДОСНАБЖЕНИЯ ДЛЯ НУЖД СИСТЕМЫ ПОЛИВА.
  • Аппаратура линии связи: аппаратура передачи данных, оконечное оборудование, промежуточная аппаратура.

  • D Pascal существенно расширяет CF Pascal добавлением новых типов данных к символам и файлам. Порядковые типы данных описывают простые, неделимые объекты. Перечислимый тип содержит фиксированный набор именованных объектов. Логический тип имеет только два объекта – TRUE и FALSE. Целый тип реализует положительные и отрицательные целые числа. Наконец, часть типа также в свою очередь может быть типом, типом диапазон. Конечно, типы включают операции, которые определяют, что может быть сделано с объектами. Для логического, целого и т.д. эти операции хорошо понятны интуитивно.

    Типы данных описывают множества значений и операции, которые могут быть применены к ним. Типы данных введенные CF Pascal это CHAR и TEXT. Значениями типа CHAR являются множество допустимых символов Паскаль-машины и операциями над этими значениями являются операторы сравнения:

    = < > <= >= <>

    значениями которых являются соответствующие математические операции, отражающие различное положение символов в алфавитной последовательности. Значения типа данных TEXT – последовательности строк, каждая строка является последовательностью символов. Операции над такими данными:

    RESET REWRITE READ WRITE WRITELN OEF EOLN

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

    Типы данных абстрагируют важные свойства данных. Например, для понимания сравнения

    ‘A’ < ‘B’

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

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

    Контекст операнда в программе подразумевает тип операнда, этот подразумеваемый тип – избыточная информация, которая может быть проверена на соответствие объявленному типу операнда для предотвращения операций над значениями неверного типа. Рассмотрим следующий фрагмент программы:

    PROGRAM Typex(INPUT, OUTPUT);

    Поскольку операция = определена в CF Pascal только для символьных операндов, появление Ch и F в качестве операндов подразумевает, что оба они типа CHAR. У Ch тип корректен, а F объявлена как TEXT, поэтому будет выявлено несоответствие.


    В D Pascal существует две разновидности типов данных: простые типы данных и составные (aggregate) типы данных. Значения простых типов не могут состоять из более мелких частей, с которыми можно работать по отдельности. CHAR – простой тип. Значения сложных типов данных образованы объединением значений простых типов. TEXT – составной тип, потому что строки фалов состоят из символов.

    Значения простых типов упорядочены, то есть для каждой пары значений этого типа x, y возможен только один из вариантов: x < y, x = y, x > y. Поэтому эти типы называются порядковыми.

    Паскаль содержит три предопределенных порядковых типа, которые задаются идентификаторами CHAR, INTEGER и BOOLEAN. Дополнительно к предопределенным порядковым типам, в Паскале предусмотрено два метода для программиста для определения новых порядковых типов, а именно:

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

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

    <обозначение типа> ::= <идентификатор типа> | <новый тип>

    <идентификатор типа> ::= <идентификатор>

    <новый тип> ::= <перечислимый тип> | <тип диапазон>

    Способы описания для <перечислимый тип> и <тип диапазон> будут даны в соответствующих разделах ниже.

    Когда определяется новый тип, ему может быть дано имя в объявлении типов. Это объявление должно предшествовать объявлению переменных блока.

    <блок> ::= <раздел объявлений типов> <раздел объявлений переменных>

    <раздел объявлений процедур> <раздел операторов>

    <раздел объявлений типов> ::= TYPE <объявления типов> |

    Это правило показывает что <раздел объявлений типов> может быть пустым (как это было во всех программах до данного места)

    <объявления типов> ::= <объявления типов> <объявление типа> | <объявление типа>

    <объявление типа> ::=<идентификатор > = <обозначение типа>

    Контекстное правило, которое сопровождает эти синтаксические правила, говорит о том, что только некоторые идентификаторы являются <объявлением типа>:

    CR Чтобы быть использованным как <идентификатор типа>, <идентификатор> должен ранее появиться в <объявлениях типов>.

    Таким образом для

    и T1 и T2 являются идентификаторами типа и могут быть использованы в текущем блоке для объявления переменных и формальных параметров, как ранее использовался CHAR.

    Похожие статьи