CFA LogoCFA Logo Computer
Новости Статьи Магазин Драйвера Контакты
Новости
RSS канал новостей
В конце марта компания ASRock анонсировала фирменную линейку графических ускорителей Phantom Gaming. ...
Компания Huawei продолжает заниматься расширением фирменной линейки смартфонов Y Series. Очередное ...
Компания Antec в своем очередном пресс-релизе анонсировала поставки фирменной серии блоков питания ...
Компания Thermalright отчиталась о готовности нового высокопроизводительного процессорного кулера ...
Компания Biostar сообщает в официальном пресс-релизе о готовности флагманской материнской платы ...
Самое интересное
Программаторы 25 SPI FLASH Адаптеры Optibay HDD Caddy Драйвера nVidia GeForce Драйвера AMD Radeon HD Игры на DVD Сравнение видеокарт Сравнение процессоров

АРХИВ СТАТЕЙ ЖУРНАЛА «МОЙ КОМПЬЮТЕР» ЗА 2002 ГОД

Мысли о Паскале

Владислав ДЕМЬЯНИШИН nitromanit@mail.ru

(Продолжение, начало см. МК № 46, 51—52, 4, 6—7, 10, 12—13, 16—18, 22, 24 (165, 170—171, 175, 177—178, 181, 183—184, 187—189, 193, 195))

Оператор цикла с параметром

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

Для упрощения решения таких задач существует оператор for-цикла с параметром. Предположим, что необходимо перебросить значения элементов M1[100]..M1[150] массива в элементы с соответствующими номерами другого массива M2. Тогда решение может выглядеть так:

Таким образом, переменная j будет изменять свое значение согласно последовательности 100,101,102,..,149,150, что обеспечит 51 выполнение тела цикла.

Аналогичную задачу можно решить, задав выполнение цикла в обратном порядке:

т. е. переменная j последовательно примет значения 150,149,..,101,100. Итак, теперь уже ясно, что переменная j используется для ведения отсчета итераций, и в дальнейшем я буду называть ее переменной-счетчиком.

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

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

• переменная-счетчик должна быть описана в текущем блоке;

• переменная-счетчик должна иметь дискретный тип;

• значения границ диапазона должны иметь тип, совместимый с типом переменной-счетчика;

• категорически запрещается изменять значение переменной-счетчика в теле цикла, например, при помощи оператора присваивания.

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

Служебное слово downto указывает обратное — на необходимость формировать цикл с убыванием (декрементом) значения переменной-счетчика. Перед началом выполнения первой итерации проводится проверка, и если начальное значение меньше, чем конечное, то цикл не производит ни единой итерации.

Если же обе границы диапазона равны, то тело цикла выполняется один единственный раз, независимо от направления изменения значения переменной-счетчика.

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

в итоге получим на экране строчку прописных букв латинского алфавита.

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

Оператор над записями

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

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

На это еще можно закрыть глаза, если такая конструкция единична и не находится в теле цикла и не выполняется многократно. А что делать, если она все-таки выполняется многократно?

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

можно заменить на эквивалентную ей, но более эффективную и компактную:

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

Могут возникать случаи, когда нужно манипулировать полями нескольких записей, — тогда в with-операторе можно перечислить имена записей через запятую:

что абсолютно аналогично конструкции:

Таким образом, действует правило: если в обеих записях имеется поле с именем, например, Field, то компилятор подразумевает, что это поле принадлежит записи Rec2.

Аналогичным образом, если в объемлющем блоке описана переменная с именем, совпадающим с именем одного из полей записи, указанной в with-операторе, то в пределах with-оператора идентификатор такой переменной будет считаться именем поля записи. Пример:

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

Чтобы добиться высокой производительности при использовании динамических переменных типа массив записей следует применять with-оператор.

Пустой оператор

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

В данном примере зарезервированы пустые операторы для реагирования на нажатия клавиш Tab, Enter и Space соответственно.

Еще пустой оператор может помочь в осуществлении ожидания нажатия на клавишу клавиатуры или мыши:

В данном примере считается, что repeat-цикл содержит в своем теле пустой оператор, а функция Ms_Click(mbLeft) возвращает true, если указанная клавиша мыши была нажата и отпущена.

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

А поскольку синтаксис языка Turbo Pascal версии 6.0 требует оформлять вызов функции в виде оператора присваивания или, как в следующем примере, условного оператора:

то достаточно в строке if SetTextMode (0) then; указать пустой оператор сразу за служебным словом then, образованный точкой с запятой, — и проблема будет решена.

Хочу заметить, что в версии Turbo Pascal 7.0 имеется директива {$X+}, которая включает расширенный синтаксис языка, при котором вызов любой функции можно оформлять как вызов процедуры, например:

Если эту директиву отключить {$X–}, то придется вызывать функции в соответствии со старым синтаксисом:

Только хочу предупредить, что функции SetTextMode и Ms_Click, упомянутые здесь, не являются стандартными, а взяты из моих модулей, о которых постараюсь рассказать в дальнейшем.

(Продолжение следует)

Рекомендуем ещё прочитать:






Данную страницу никто не комментировал. Вы можете стать первым.

Ваше имя:
Ваша почта:

RSS
Комментарий:
Введите символы или вычислите пример: *
captcha
Обновить





Хостинг на серверах в Украине, США и Германии. © sector.biz.ua 2006-2015 design by Vadim Popov