Длинное Вступление
Здраствуйте! Да, возвращаясь к предыдущему выпуску. Читая книгу Мартина Гарднера - Математические головоломки и развлечения, нашёл одну интересную историю про задачу о Ханойских башнях, программку для решения которой мы написали в прошлый раз: Число необходимых перекладываний колец выражается формулой: 2n - 1 (n - число колец)Кстати ещё одна новость для любителей статистики - так как мы перешли в нумерации на Hex числа, то сегодняшний выпуск опять юбилейный - 10 :) |
ТеорияЯ уже наверное вбил в вам в голову, что Паскаль - строготипизированный язык. Вы уже знакомы с довольно большим количеством типов. Однако мы можем и создавать свои типы! Например нам надо создать тип, значение которого будут меняться от 0 до 5. Для описаний типов отведён ещё один отдел программы - type. Он должен находится в самом начале программы, где-то среди var, const и label. Хотя желательно размещать этот раздел первым. Новый тип объявить очень просто, как константу: Имя = типНу не нравится мне, например, каждый раз писать длинное слово integer, а хочется чего-то покороче - int. Пожалуйста:
Естественно, что наш "новый" тип int сохранит все свойства типа integer - максимальное и минимальное значение, допустимые операции. Мы просто обозвали integer как int, по этому теперь эти переменные имеют одинаковый тип:
Однако раздел описаний не создан для того, что бы переименовывать существующие типы. Он создан для создания новых (вот каламбур получился:) Перечисляемый тип. Этот тип задаётся перечислением всех возможных значений. Каждому значению присваивается некоторый индетификатор и распологается в списке, обрамлённым круглыми скобками. Например:
Теперь мы можем присваивать переменной color значения red, или green или blue вот так: color := red;Для численного представления элементов перечисляемого типа используется уже известная функция ORD. Причём первому элементу соответствует 0, второму 1 и так далее... Т.е. ord (red) = 0, ord (green) = 1, ord (blue) = 2. Допускается и обратное преобразование типов из целых в перечисляемые. Делается с помощью указаня имени типа и в скобках целого значения: color := tcolor (1); - равносильно color := green;Функции преобразования создаются автоматически. Давайте познакомимся ещё с несколькими функциями языка Паскаль: function Pred(X): - возвращает предшественник аргументат.е. предыдущее значение типа. Например pred (1) = 0 function Succ(X): - возвращает следующее значение типаНапример: succ (0) = 1Кстати переменную перечисляемого типа можно объявлять без объявления типа, сразу разделе var: varПеречисляемый тип это конечно хорошо, а если нужно содать тип в котором будет больше 100 значений (!) тут он явно не подойдёт. Тут нам поможет тип-диапазон. Тип-диапазон - это подтип (подмножество) базового типа, которым может быть любой целый тип, кроме типа-диапозона (логично, не правда ли :). Тип-диапазон задаётся своими границами: мин_значение .. макс_значение. Две точки .. рассматриваются как один символ и неотделимы! Например создадим тип-диапазон, который будет менять значения от -25 до 32:
При этом -25 <= c >= 32 Присвоение с := 33 вызовет ошибку.Можно создавать и такие типы-диапозоны:
тип Tabc является под-типом char, поэтому над ним разрешаются только операци допустимые типом. Такое неправильно: buka := 66 !!!
Рассмотрим ещё один пример:
Напомню, что в Паскале есть ещё две функции, которые работают с типами: function High(X) - возвращает максимальное значение типа-диапозона, к которому принадлежит переменная Х |
ПрограммаВозиожно это и неочивидно, но ведь мы можем создать тип функции или тип процедуры. Делается это так же, как и для типа нужно объявить таким образом: Имя = function (параметры) : тип_возвращаемого_значения;естественно параметры не обязательны. Так же, для простоты можно создать тип массива: имя = array [диапозон] of тип;Рассмотрим такой пример:
Итак пусть нам надо написать процедуру для заполнения массива, каждый элемент массива - это значение, возвращенное некоторой функцией, которые в свою очередь разные. Вот блин загнул :)Этим у нас и займётся процедура procedure fill (var res : tarray; f : Tfunc); - первый параметр - это массив, второй - функция, с помощью которой мы этот массив и заполним. Что бы передать в качестве параметра функцию, нужно просто указать её имя. А при описании функции использовать директиву far. Что это такое я раскажу позже. Пока, что запомните, что эта директива позволяет выступать функции в качестве параметра. В процедуре fill мы объявляем параметр f, как тип-функцию. Теперь внутри процедуры fill мы можем обращаться с ней так, как будто бы такая функция действительно есть, т.е. мы можем вызвать её, указав имя - f. Если бы были и параметры, то можно было бы передать их как то так: f (par1, par2); Мы как бы создаём виртуальную функцию, которая потом замещается настоящей. Такие сложности на самом деле окупаются. Техника передачи параметров функций поможет создавать различные варианты для программы - от примитивного заполнения массива, до расчёта сложных физических процессов.
|
Факториал
В прошлый раз (эх давно это было :( было предложено написать программу для вычисления факториала, с использованием рекурсии. Выглядит это как-то так:
n! = (n - 1)! * nСоответственно мы и останавливаемся при n = 0 (или 1) : 0! = 1 (1! = 1) Решения, присланные читателями можно посмотреть тут: http://www.ibp7.narod.ru/index.html?dz4.html |
Короткое послесловие
Ну вот и состоялось второе пришествие :) Следующий выпуск ждите в среду. |