В.Г. Абрамов, Н.П. Трифонов, Г.Н. Трифонова - Введение в язык Паскаль (1107618), страница 30
Текст из файла (страница 30)
При этом важно лишь, чтобы значения, присваиваемые переменной ограниченного типа, принадлежали соответствующему диапазону — в противном случае будет зафиксирована ошибка. Например, приналичии в программе приведенных выше разделов типов и переменныхдопустимы операторы присваиванияi:=200; j:=5; l:=2*j-2:деньотдыха:=сб;деньработы: =pred(деньотдыха);При попытке же выполнить последовательность операторовi:=200; j:=5; l:=i*j-2;будет зафиксирована ошибка, поскольку при выполнении последнего изэтих операторов делается попытка присвоить переменной 1 недопустимоезначение.В выражении, задающем правила вычисления значения некоторого типа,могут использоваться переменные как ограниченного типа, так и соответствующего ему базового типа — принадлежность переменной ограниченному типу учитывается лишь при присваивании значения этой переменной.Например, допустим оператор присваивания1:=l+i-25Использование ограниченных типов позволяет формулировать алгоритмрешения задачи в более понятной и наглядной форме.
Например, из приведенных выше описаний сразу видно, что переменная деньотдыха представляет не любой день недели а один из нерабочих дней — субботу шщвоскресенье. Кроме того, дополнительная информация, содержащаяся7заданиях ограниченного типа, позволяет транслятору в ряде случаев болееэкономно использовать память при представлении значений переменных,особенно при байтовой структуре памяти. Транслятор также имеет возможность предусмотреть контроль KJTK на этапе трансляции, так и во времявыполнения программы за корректностью присваиваний, что позволяетсвоевременно выявлять допущенные ошибки и избегать непроизводительного расходования машинного времени на получение заведомо неверныхрезультатов. Поэтому программисту следует стремиться зафиксироватьв своей программе ту информацию, которой он располагает из рассмотрения существа решаемой задачи относительно диапазонов изменения значений тех или иных переменных.Более содержательные примеры использования ограниченных типовбудут приведены при рассмотрении производных типов, в частности —регулярных типов, которым посвящена следующая глава.ГЛАВА7РЕГУЛЯРНЫЕ ТИПЫ (МАССИВЫ)7.1.
Производные типыДо сих пор мы рассматривали лишь п р о с т ы е (а именно — скалярные)типы значений в паскале: каждым значением любого из этих типов являетсяотдельное данное, т.е. тривиальная структура.Сейчас мы приступаем к изучениюп р о и з в о д н ы хтипов.Каждое значение любого из этих типов в общем случае представляет собойуже нетривиальную структуру, т.е. обычно это значение имеет более чемодну компоненту. При этом каждая компонента структуры может бытькак отдельным данным, так и в свою очередь нетривиальной структурой,т.е.
значением любого из производных типов. Таким образом, значенияпроизводных типов в общем случае имеют иерархическую структуру,на самом нижнем уровне которой фигурируют только отдельные данные."Этим компонентам нижнего уровня могут присваиваться значения и онимогут присутствовать в выражениях, как и значения переменных скалярного типа.Данные, являющиеся значениями скалярных типов, занимают сравнительно мало места в памяти ЭВМ.
Отдельная литера, например, обычнопредставляется одним байтом (8 двоичных разрядов). Для чисел различных типов в зависимости от реализации отводят несколько байтов.Данные же, составляющие значение производного типа, обычно занимаютзначительный объем памяти ЭВМ. В связи с этим при написании программдля ЭВМ, имеющих сравнительно небольшой объем памяти, встает проблема экономного ее использования.
В паскале предусмотрена возможностьуказания транслятору на необходимость экономного представления значений производных типов. Для этого задание производного типа необходимоначать со служебного слова packed, что означает упакованный. Но введя требование на упакованность данных, необходимо четко представлять себе,что, с одной стороны, это требование не всегда может быть выполненотранслятором (если, например, более экономного представления, чемобычное неупакованное представление для данных этого типа, в ЭВМ простоне существует).
А с другой стороны, если оно выполнимо, то приводитк увеличению времени исполнения программы.Поясним на примере, за счет чего это происходит. Как уже указывалосьранее, одна литера занимает один байт. Машинная ячейка памяти, с которойработают команды ЭВМ, в общем случае состоит из нескольких байтов.Поэтому, если в ячейку поместить одну литеру, то большая ее частьне будет использована.
На самом деле в одну ячейку /можно поместитьнесколько литер (упакованное представление). Но тогда каждый раз,когда необходимо выполнить действие над отдельной литерой, придетсяпроизводить выделение этой литеры из ячейки (распаковку литеры изячейки). Аналогично, при записи отдельной литеры в память машины придется определять то место в ячейке, куда ее необходимо поместить,и заносить литеру именно туда, не изменяя содержимое остальных разрядов(запаковка литеры в ячейку). Такие дополнительные действия могут занимать значительную часть общего времени работы программы.
Поэтому принимать решение об использовании упаковкнного представления данныхдолжен всегда программист, в зависимости от конкретных условий и целей,которые он преследует.Итак, значения производных типов могут быть представлены в памяти ЭВМ в упакованном и неупакованном виде. Упакованное представлениетребует, вообще говоря, меньшего объема памяти, но замедляет процессвыполнения программы.В данной главе мы рассмотрим наиболее употребительный производныйтип, а именно — регулярный тип.
Значение регулярного типа обычно называют массивом.7.2. Одномерные массивыПрежде всего попытаемся понять природу возникновения значенийрегулярного типа. Необходимость в массивах возникает всякий раз, когдапри решении задачи приходится иметь дело с большим, но конечным количеством однотипных упорядоченных данных. В главе 3 был приведенпример с суммированием ста вещественных чисел, в котором показаноудобство использования структуры данных - массива вещественных чисел,вместо ста переменных типа real. Эта структура представляет собой упорядоченный набор перенумерованных компонент, причем индивидуальноеи м я получает только весь набор (вся структура данных), а для компонентэтого набора определяется лишь порядок следования и общее их количество.
Дадим упорядоченному набору из ста вещественных компонент имя v.Тогда для указания той или иной компоненты этого набора в качестве ее"имени" можно использовать имя самого набора и номер нужной компоненты в этом наборе. В обычной математической символике такие именатак и записываются: имя набора, справа от которого в нижней позицииуказывается номер компоненты: v L , v 2 , ..., v 1 0 0 . Такие наборы иназываются массивами. Здесь можно увидеть полную аналогию с обычнымпонятием одномерного числового вектора. Числовой вектор, как единыйобъект, имеет индивидуальное имя, и структурно состоит из фиксированного числа упорядоченных однотипных компонент — чисел.Итак, массив — это упорядоченный набор фиксированного количестванекоторых значений (компонент массива).
Все компоненты должны бытьодного и того же типа, который называют типом компонент или базовым(для массива) типом. Так, в примере с суммированием можно ввестив употребление вещественный массив — вектор, компонентами которогоявляются вещественные числа. Массив, компонентами которого являютсяотдельные литеры, может интерпретироваться как строчка текста;120целочисленная матрица может быть представлена как массив, компонентами которого являются целочисленные вёкторы и т.д.Как обычно, каждому используемому в программе конкретному массиву должно быть дано свое имя. Это имя будем называть полной перемен- •ной, поскольку ее значение есть весь массив.
Каждая компонента массиваможет быть явно обозначена путем указания имени массива, за которымследует селектор компоненты — взятый в квадратные скобки индекс,задающий правило вычисления номера нужной компоненты. Это отличиеот привычной записи индекса в математике, когда он указывается справав нижней позиции, объясняется необходимостью использования линейнойзаписи программы, так что многоуровневая запись должна быть исключена.При ссылке на компоненты массива индекс записывается на одном уровнес именем и заключается в квадратные скобки.Таким образом, для ссылки на отдельные компоненты используетсязапись вида< имя массива > [ < индекс > ]которую будем называть частичной переменной (поскольку ее значениемявляется не весь массив, а отдельная его компонента, номер которойзадается индексом) — применительно к массивам она называется переменнойс индексом.
В нашем примере массив получит имя v, а ссылки на отдельные его компоненты производятся с помощью частичных переменныхV [ 1 ], v [ 2 ], . . . , v [ 100 ].В общем случае в качестве индекса может быть использовано выражение,значение которого и определяет номер компоненты массива. При этом важно, что в индексное выражение могут входить переменные, так что при изменении их значений меняется и значение индекса, которое определяетномер компоненты массива. Таким образом, одна и та же переменнаяс индексом в процессе выполнения программы может обозначать различныекомпоненты массива. Тип значения индексного выражения называюттипом индекса.
Множество значений типа индекса должно быть перенумерованным множеством, тем самым определяя количество компонент и ихупорядоченность.При задании регулярного типа кроме типа индекса необходимо задатьтип компонент. Задание такого регулярного типа, как одномерный массив,т.е. вектор, имеет вид:array [ < тип индекса ) ] of < тип компонент >где (тип компонент } — имя или задание типа.7.2.1.
Типы индексаЗначением индексного выражения всегда является конкретное данное,по которому однозначно можно установить номер компоненты массива.Поэтому, очевидно, тип индекса может быть только скалярным.Рассмотрим последовательно скалярные типы и укажем, какие из них могут использоваться как типы индекса, а какие не могут и почему.В первую очередь мы должны отвергнуть тип integer, так как множествозначений этого типа в самом языке неограничено, а также тип real, у которого множество значений тоже неограничено (более того, в паскале оно инеупорядочено).Наиболее часто в качестве типа индекса используется ограниченный тип,причем в большинстве случаев — это ограниченный целый тип. Действительно, множество значений ограниченного типа конечно, оно упорядоченои является перенумерованным.
Так, массив из 100 компонент вещественного типа может быть задан следующим образом:a r r a y С 1. .1003 of realОграниченный целый тип 1 .. 100 определяет количество компонент(сто) и их упорядоченность (от первой до сотой). Во многих задачахнумерация компонент начинается с 1 и ограничивается положительнымцелым числом.