Главная страница

Практикум по Visual Basic for Applications. 3 Глава Алгоритмы и программы Понятие алгоритма


Скачать 1.74 Mb.
НазваниеПрактикум по Visual Basic for Applications. 3 Глава Алгоритмы и программы Понятие алгоритма
АнкорVBA.pdf
Дата23.09.2017
Размер1.74 Mb.
Формат файлаpdf
Имя файлаVBA.pdf
ТипПрактикум
#8936
страница2 из 8
1   2   3   4   5   6   7   8
Do, он имеет вид Exit Do. Например, программа a = 7
Do
a = a – 1
If a = 5 Then
Exit Do
End If

13
Loop Until a < 0
даст на выходе значение 5, т. к. цикл принудительно прервался, когда значение переменной а стало равным пяти. Того же результата можно достичь и в про- грамме с циклом For: k = 2
m = 4
For i = k + 1 To m * 2 + 1 Step 0.5
k = k + i
If k = 5 Then
Exit For
End If
Next
Вложенные циклы. Тело любого оператора цикла может содержать дру- гие циклы. Такие конструкции называют вложенными циклами. Вложенные циклы (цикл в цикле) применяют обычно в задачах, когда требуется связать или сравнить каждый элемент одного множества с каждым элементом другого множества. Блок схема вложенных циклов для, например, циклов с предусло- вием выглядит так:
+
-
Условие 2
+
-
Тело цикла 2
Условие 1
Здесь тело внешнего цикла (цикла 1) состоит из оператора внутреннего цикла (цикла 2). Условие выхода из всей конструкции – это условие внешнего цикла. На каждом шаге внешнего цикла полностью «отрабатывает» внутренний цикл. Таким образом, если внешний цикл перечисляет элементы некоторого множества X, а внутренний цикл – элементы множества Y, то за i-й шаг работы первого цикла для i-го элемента x
i
из X могут быть проверены все элементы y
j

14
из Y, т.к. второй цикл не завершит работу, пока истинно его условие (Условие
2 на схеме).
Пример программы с вложенными циклами в VBA:
For i = 1 To 7
For j = 1 To 5
If i <= j Then
Cells(i, j) = 1
End If
Next
Next
Здесь Cells(i, j) – имя ячейки листа Excel, расположенной в строке i и столбце j. Эта программа «рисует» единицами треугольник на листе Excel: пе- ребираются все строки листа от первой до седьмой и для каждой строки прове- ряются все пять столбцов: они заполняются единицами, если текущий номер строки меньше или равен текущему номеру столбца, и не заполняются ничем в противном случае.
Циклы в теле другого цикла имеют точно такой же статус при исполне- нии, как и любой другой оператор, поэтому «вкладывать» один в другой можно циклы любого типа и глубина вложения (количество вложенных друг в друга циклов) может ограничиваться лишь реализацией языка программирования.
1.2.5. Операторы ввода-вывода
Эти действия выполняют ввод и вывод информации (значений перемен- ных) в ходе работы программ. Операторы ввода-вывода с точки зрения вырази- мости алгоритма не имеют самостоятельного значения, т.к. могут быть замене- ны набором соответствующих присваиваний, но для написания программ они существенны, т.к. исполняются особым образом, с привлечением дополнитель- ных устройств. Для более точного представления алгоритмов в блок-схемах эти операторы имеют специальное изображение, например,
Ввод x, y или
Вывод x, y
Кроме того, для обозначения начала и конца алгоритма используют фигу- ры
Начало
Конец и

15
В языке VBA ввод значения переменной x можно осуществить с помо- щью функции InputBox, например: x = InputBox(“Введи значение x”)
Вывод в специальное окно экрана можно реализовать оператором
MsgBox, например:
MsgBox (x)
в итоге на экран выведется только значение переменной x, например, 5. Опера- тор
MsgBox “x =”&x выведет на экран фразу: x = 5.
Можно осуществить ввод и вывод, используя лист Excel. Ячейки листа имеют имена Cells(i,j), где i – номер строки, j – номер столбца. Напри- мер, ввод значения переменной x из ячейки А1 выглядит в программе так: x = Cells(1,1), а вывод результата – значения x в ячейку, например, С2 (третий столбец) реа- лизуется так:
Cells(2,3) = x
1.3. Структуры и типы данных
Понятие «данные» обычно связывают с информацией, перерабатываемой алгоритмом. Эта информация может быть неоднородной, данные могут иметь различную структуру, которая зависит от решаемой задачи. Соответственно, размещение таких данных в памяти компьютера и доступ к ним будет различ- ным. Языки программирования должны иметь средства для представления и обработки данных различной природы.
Например, программы анализа анкет служащих работают с таблицами, содержащими сведения о сотрудниках, поэтому языки представления алгорит- мов обработки таких данных должны иметь операции, позволяющие извлекать из ячеек таблицы их содержимое, компоновать части таблиц, связывать табли- цы друг с другом. Программы, вычисляющие физические параметры производ- ственного цикла, работают с последовательностями действительных чисел. Над числовыми значениями должны быть определены, по крайней мере, арифмети- ческие операции сложения, умножения, вычитания, деления. Алгоритмы пере- работки текстов имеют дело с наборами символов, над которыми возможны другие операции: конкатенация («склеивание») символов в слова, вырезка час- ти слова или предложения, замена части слов и т.п. Сами программы также

16
можно рассматривать как данные, имеющие свою структуру и свойства и до- пускающие определенные операции, например, вызов одной программы из дру- гой.
Из этих соображений возникло понимание типа данных как множества
значений, характеризуемое множеством операций над ними. Например, тип целых чисел (Integer в VBA) включает все целые числа и арифметические операции (хотя деление может вывести из этого типа данных). Символьный тип
(String) включает символьные значения и операции склейки символов и спе- циальные операции обработки строк. Логический тип (Boolean) состоит из двух значений True (истина) и False (ложь) и допускает все логические опе- рации – отрицание (Not), конъюнкцию (And), дизъюнкцию (Or), импликацию
(Imp).
Дальнейшее развитие концепции типа данных привело к понятию объ- ектно-ориентированного программирования, в котором решение задач (как и весь «окружающий мир») представлено совокупностью взаимодействующих друг с другом объектов разных типов. Здесь тип – это множество объектов,
имеющих общее поведение и общую структуру (свойства).
Например, людей можно считать объектами типа «Человек». Этот тип обладает определенной структурой, воплощенной в его свойствах: вес, рост, количество рук, объем мозга и т.п. К человеку можно применять операции (ме-
тоды), определяющие его поведение – ходить, спать, говорить, учиться и т.п.
Какие именно свойства и методы рассматривать, зависит от задачи. Например, в задаче «определить, кто придет первым в стометровке, если известно, что толстый бегает медленнее худого», важны такие свойства, как вес, и метод бе- гать, но не важны устройство скелета и операция хлопать в ладоши, которые в другой задаче могли играть главную роль. Таким образом, разработчик про- граммы (приложения) решает, какие типы данных ему нужны, и может само-
стоятельно их определить, задав соответствующие свойства и операции, при- менимые к объектам этих типов. Современные языки программирования пре- доставляют средства для задания собственных, пользовательских, типов дан- ных.
Объекты некоторого типа Т – это конкретные представители этого типа данных. Например, Сидоров А.А., Иванов Б.Б – объекты типа Человек, ВАЗ
2109 с номером У 3040 – объект типа Автомобиль, соседский кот Барсик – объект типа Коты. Именно к объектам можно применять методы (операции) соответствующего типа данных. Также и свойства типа: только применительно к конкретному объекту свойство может получить определенное значение. Если использовать принятый в языках программирования синтаксис обращений к методам и свойствам: объект.метод и объект.свойство = значение, то допус- тимы, например, такие конструкции в программах: Сидоров.Бегать, Бар- сик.Кусаться, Барсик.Вес=3. Применение операции копирования к объ- екту – диапазону A1:A3 листа Excel в VBA будет выглядеть так:
Range("A1:A3").Copy. Метод Copy применим к любому объекту типа дан- ных Диапазон. Этот тип задан в программе приложения Excel (описан разра-

17
ботчиками этого приложения), для пользователей же Excel он является встро-
енным, стандартным, как, например, тип Integer.
Типы данных в языках программирования можно условно разбить на сле- дующие группы:
 примитивные типы (целые, вещественные числа, логические и сим- вольные значения);
 конечные последовательности однотипных элементов (линейные мас- сивы, матрицы, многомерные массивы);
 конечные последовательности разнотипных элементов (записи, струк- туры);
 динамические последовательности со специальными операциями дос- тупа (очереди, стеки, списки);
 сложные типы, ориентированные на специальные предметные области
(электронные таблицы, листы Excel, диапазоны ячеек листов, базы данных и т.п.);
 произвольные типы, определяемые пользователем (например, самолет, автомобиль, животное, собаки, студенты).
Программы обращаются к данным, хранящимся в памяти компьютера с помощью имен, реализуемых в понятии переменной. Переменная имеет тип, указывающий на то, какого сорта (типа) значения она может обозначать (гово- рят, хранить), и значение – конкретный объект. В компьютере каждой объяв- ленной в программе переменной отводится область памяти, которую эта пере- менная будет именовать. Размер этой памяти зависит от типа переменной. На- пример, для переменной типа Integer это два байта, для переменной типа
Double (число с плавающей точкой удвоенной точности) – восемь байтов, для массива из десяти целых чисел – блок памяти объемом 2
10 = 20 байтов.
Таким образом, каждое хранимое значение имеет в компьютере физиче- ский адрес памяти, которая в данный момент его содержит и (в программе) имя переменной, которая им обладает (ссылается на этот адрес). Например, при присваивании a=b значение переменной b пересылается по адресу, отведен- ному для переменной a. Чтобы компьютер правильно выполнил эту пересылку, необходимо, чтобы значение, «сидящее» в b «поместилось» в память, отведен- ную для значений переменной a. Это означает, что типы этих переменных должны совпадать или быть совместимыми. Совместимость означает, что можно разместить данное без потери его значения или смысла. Например, при- сваивание a=b для a типа Integer и b типа Double невозможно реализовать без существенной потери значения b.
Ошибки, возникающие при таких присваиваниях, называют типовыми
ошибками. Если типы используемых переменных объявлены в программе зара- нее, то эти ошибки можно выловить на этапе компиляции (перевода программы в машинный код). Такой контроль типов называют статическим, в отличие от динамического, когда типовые «разборки» начинаются при исполнении про- грамм (исполнении готового машинного кода). Статический контроль типов повышает эффективность программ, поэтому большинство языков программи-

18
рования требует описания типов переменных в программах до того, как эти пе- ременные будут использованы в операторах. В VBA описание переменных со- провождается ключевым словом Dim и выглядит так:
Dim <имя переменной> As <тип переменной>.
Например, Dim a As Double, b As Boolean, c As Integer. Эти описания помещаются в начале программы, до первого оператора.
Для реализации возможности совмещения типов используются так назы- ваемые операции приведения типов. Приведение, если оно возможно, означает преобразование значения одного типа в значение другого типа. Преобразуется именно значение, типы же переменных остаются прежними. Как правило, мо- гут «приводиться» типы меньшего или равного физического размера к больше- му. В противном случае, если приведение допускается, то заранее оговаривает- ся, каким образом большее значение будет урезано. В языках программирова- ния существуют специальные операции (функции) приведения типов. Напри- мер, в VBA к таким функциям относятся CStr (преобразование к символьному типу String), CInt (преобразование к целочисленному типу Integer).
Применять функцию CInt(x) можно к числовому аргументу x (значение x
тогда округляется до целого) или к числовой строке x (значение строки, напри- мер, x=”123” преобразуется в число 123). Нечисловые строки, например, x=”abcd” не могут быть приведены к целому числу, и выражение CInt(x) даст типовую ошибку. Функция CStr(x), примененная к числовому аргумен- ту x, например, x=35.4 преобразует это число в строку ”35.4”, и к ней тогда можно применять любые строковые операции, например, склейку – конкатена- цию (&) строк: результат выражения CStr(x)&"abcd" будет 35.4abcd.
Доступ к данным. Для каждого типа данных должны быть определены специальные операции (говорят, функции) доступа к значениям этого типа.
Создавая программу, разработчик должен знать, каким образом можно извлечь нужное значение. Для встроенных, стандартных типов языка функции доступа
(программы, реализующие извлечение значения) также встроены, их синтаксис дается в описании языка программирования. Для пользовательских типов реа- лизация (программа) функций доступа является неотъемлемой частью описания типа.
Доступ к значениям примитивных типов осуществляется просто указа- нием имени переменной, содержащей значение, или указанием самого значения непосредственно. Например, в выражении b+7*(d-c) для b, d, c, имеющих числовой тип, значения переменных извлекаются из ячеек памяти, именуемой этими переменными.
Для более сложных, структурированных, типов часто требуется иметь доступ к отдельным компонентам (элементам) этих структур. В зависимости от

19
«устройства» типа доступ может быть осуществлен по имени элемента, по его порядковому номеру в последовательности.
Доступ к значениям элементов массивов. Массивы – это упорядоченные конечные последовательности элементов одного и того же типа. Например, массив целых чисел, массив символов, массив котов. Массив может быть одно- мерным (линейным) или многомерным. Двумерные массивы называют обычно матрицами. В памяти компьютера массиву отводят блок памяти, в котором элементы массива располагаются друг за другом. Переменная, содержащая массив, ссылается на адрес начала этого блока. Доступ к элементу массива осуществляется по его порядковому номеру в последовательности. Таким обра- зом, чтобы получить значение, например, третьего элемента некоторого масси- ва нужно указать имя переменной, содержащей массив, и номер (говорят, ин-
декс) три. Например, в VBA: А(3) – третий элемент массива А.
Пусть переменная В содержит массив пяти целых чисел: 24, 8, 6, 77, 3.
Тогда В(3) – имя, назвав которое можно получить значение 6, т.е. В(3) = 6. Этот массив можно изобразить так:
В

В(1)
В(2)
В(3)
В(4)
В(5)





24 8
6 77 3
Если выполнить присваивание, например, В(3) = В(5), то значением эле- мента В(3), как и В(5), будет число 3, прежнее значение 6 «сотрется». Обозна- чение В(i) можно считать именем i-го элемента массива В.
Для двумерного массива – матрицы - доступ к элементу можно получить, указав номер строки и номер столбца, на пересечении которых он находится, например, M(4,3) – имя элемента четвертой строки и третьего столбца матрицы
M.
Чтобы можно было правильно реализовать присваивания элементам мас- сивов, нужно знать тип этих элементов. Так, если В – массив целых чисел, то недопустимо присваивание В(2) = “Маша ела кашу”. Для того, чтобы обеспе- чить правильную работу программы и распределение памяти, компьютер дол- жен знать «размер» каждого элемента массива и их количество. Поэтому мини- мум того, что необходимо сообщить при описании массива, это – имя перемен- ной массива, количество и тип элементов. Например, описание в VBA линей- ного массива А, состоящего из десяти элементов – целых чисел выглядит так:
Dim A(10) As Integer, а описание матрицы М из пяти строк и семи столбцов символьных значений – так:
Dim M(5,7) As String

20
Таким образом, слово «массив» не имеет статуса типа данных, это скорее способ конструирования «массивоподобных» типов. Тип массива определяется количеством и типом его элементов (иногда, если в языке программирования разрешается нумеровать элементы не целыми числами, а, например, константа- ми или буквами, то и типом индексов). Так, переменные А и В, описанные как массивы из десяти целых чисел: Dim A(10) As Integer, Dim В(10) As
Integer имеют один и тот же тип, поэтому для любого i = 1, 2, …, 10 допус- тимо присваивание А(i)=В(i). В некоторых языках программирования до- пустимо и присваивание содержимого массива «целиком»: A = B. Если же пе- ременная В описана как массив действительных чисел: Dim В(10) As Sin­
gle, то теперь переменные А и В имеют разные типы, и присваивание
А(i)=В(i) недопустимо из-за типовой ошибки. Если описать переменную В как массив целых чисел, но другой длины, например, Dim В(20) As In­
teger, то А и В также будут иметь разные типы, но присваивания компонент
А(i)=В(j), В(j)=А(i) для i 10, j  20 допустимы, т.к. элементы этих массивов имеют один и тот же тип (Integer). Присваивание же значения элемен- ту А(i) для i > 10 приведет к ошибке, т.к. такого элемента у массива А нет.
Доступ к значениям элементов записей. Записи (структуры) – это конеч- ные наборы элементов разного типа. Каждый элемент имеет свое собственное имя, по которому можно извлечь его значение. Подобно массиву слово «за- пись» само по себе не является типом данных, тип записи определяется имена- ми и типами ее элементов (говорят, полей). Например, набор полей для значе- ний записи: Фамилия (символьная строка), Курс (целое число), Стипендия (ве- щественное число) определяет один тип данных (назовем его S), а набор: Де-
таль (символьная строка), Материал (символьная строка), Количество (целое число), Цена (вещественное число) определяет другой тип данных (назовем его
D). На языке VBA такое описание типов выглядит так:
Type S
Type D
Фамилия As String
Деталь As String
Курс As Integer
Материал As String
Стипендия As Single
Количество As Integer
End Type
Цена As Single
End Type
Переменные А и В, описанные как Dim А As S, Dim B As D, являются переменными разных типов.
Доступ к полям переменных-записей осуществляется с указанием имени переменной и имени поля (через точку), например, А.Фамилия. Пусть, напри- мер, поле Фамилия переменной А имеет значение «Сидоров», поле Курс – значение 2 , поле Стипендия – значение 300. Запись А тогда можно изобра- зить так:

21
А

А.Фамилия А.Курс А.Стипендия



Сидоров
2 300
Допустимые присваивания, например:
А.Фамилия = «Петров»
А.Курс = 3
А.Стипендия = А.Стипендия + 200
изменят значение этой переменной:
А

А.Фамилия А.Курс А.Стипендия



Петров
3 500
Переменная С, описанная как запись типа S, может иметь другое значе- ние, но его структура будет той же:
С

С.Фамилия С.Курс С.Стипендия



Ким
4 600
Поэтому допустимы присваивания: А.Курс = С.Курс, А.Фамилия =
С.Фамилия или даже А=С.
Переменную В рассмотренного типа D можно представить как:
В

В.Деталь В.Материал В.Количество В.Цена




Гайка
Железо
48 150.5
Несмотря на то, что переменная В имеет другой тип, присваивания одно-
типным элементам, например, А.Фамилия = В.Деталь допустимы в боль- шинстве языков программирования, но недопустимо присваивание «целиком»:
А = В.
Из однотипных записей можно образовать массив, например: Dim
M(10)As S. Тогда доступ к полю Фамилия i-го элемента массива будет осу-

22
ществлен по имени: M(i).Фамилия. Фактически массив записей – это табли- ца, заголовки столбцов которой - имена полей, а строки – значения записей. В свою очередь поле записи может быть составным: иметь тип массива или тип записи, таким образом можно создавать достаточно сложные структуры дан- ных.
Доступ к значениям очередей, стеков, списков. Очереди, стеки, списки – это чаще всего динамически создаваемые наборы не известного заранее коли- чества элементов не обязательно одного типа. Динамическое создание элемента означает появление значения во время исполнения программы, в зависимости от реализации какого-либо условия или события, которого могло и не случить- ся. Новый элемент с таким значением может быть включен в набор. Обычно программисту, использующему подобные типы данных, доступны две опера- ции: взять элемент и добавить элемент. Различие (для пользователя) между указанными типами данных состоит в том, какое именно значение из набора будет выдано, и куда будет помещен добавляемый элемент.
Очередь – последовательность, в которой выделены начальный элемент
(«голова») и конечный элемент («хвост»). Пополнение очереди происходит до- бавлением элемента к «хвосту» (пришедший становится «хвостом»), а извле- чение значения возможно только для первого элемента очереди (элемент «ухо- дит», и следующий в очереди становится «головой»). Очереди характеризуются в соответствии с этой процедурой обработки как «последним пришел - послед- ним ушел».
Стек – последовательность, в которой выделен первый элемент (говорят,
«верхушка»). Пополнение стека происходит добавлением элемента сверху
(пришедший становится «верхушкой»), извлечение значения возможно тоже только для верхнего элемента (элемент «уходит», «верхушкой» становится сле- дующий за ним). Стеки характеризуются способом обработки «последним пришел – первым ушел».
Для работы со значениями переменных-очередей или переменных-стеков задаются две операции: добавить элемент: put(elem) или set(elem) и взять эле- мент get(). Функция get «выдает» очередной или верхний элемент. Так, если пе- ременная Q имеет тип очереди, то результатом обращения Q.get будет значение первого элемента очереди, при этом очередь укоротится. Аналогично для пере- менной S типа стека результатом обращения S.get будет значение верхушки стека, при этом стек также сократится. Доступа к другим элементам нет.
Список – последовательность, в которой известно местоположение перво- го элемента, возможно, последнего и каждый элемент хранит (помимо какой­
либо информации) указатель (адрес) следующего за ним элемента списка. Та- ким образом, элементы списка могут быть «разбросаны» по памяти компьюте- ра. Доступ возможен к любому элементу, удовлетворяющему некоторому усло- вию, например: «первый в списке», «последний», «следующий», «пятый», «та- кой, у которого значение поля d равно 20» и т.п. Применение операции get к переменной-списку G даст то значение, которое определено программой этой операции.

23
Рассмотренные типы – очереди, стеки, списки, как правило, не входят в состав встроенных типов языков программирования, а моделируются разработ- чиками приложений. Использование этих типов данных удобно при создании таких структур, как деревья, графы, потоки, рекурсивные вызовы программ, вызовы процедур с параметрами-процедурами – всего «джентльменского на- бора» разработчиков операционных систем, компиляторов, on-line систем.
1.4. Программы и программные единицы
Структуру программы и системные действия по ее обработке можно изо- бразить схемой:
Структура программы:
Описание переменных – ука- зание их имен и типов данных
Ввод данных и начальные при- сваивания
Операторы, представляющие алгоритм
Вывод результата и/или метка конца программы
Операционная система +
компилятор
Отводится память (
ℛ) под переменные
Эта память частично запол- няется значениями
Машинные команды, взаи- модействуют с памятью

Визуализация данных из

(печать, экран, специальные носители)
При написании программы стоит помнить некоторые технологические
правила:
1. При составлении алгоритма сразу определите его вход и выход: исход- ный набор данных и тот, который требуется получить.
2. Если задача сложная, попытайтесь разбить ее на несколько более про- стых задач. Для каждой части также определите ее вход и выход.
3. При обнаружении в алгоритме циклических конструкций четко опре- делите условие выхода из цикла и набор повторяющихся операторов – тело цикла. Проверьте, не приводит ли условие к зацикливанию. Проверьте также, не приводит ли приращение счетчика к выходу за пределы массивов, если они используются в цикле.
4. Все переменные, используемые в программе, следует описать в начале программы, до их использования. Тогда компилятор будет следить за соответ- ствием типов.
5. Имена для переменных лучше выбирать так, чтобы они «говорили» о назначении этих переменных или, хотя бы, о типе их значений. Удобнее читать программу (и исправлять в ней ошибки), в которой вместо «всеядных» x, y, z

24
используются информативные имена «цена», «среднее», «температура» или их понятные сокращения.
6. Переменные, используемые в правых частях операторов присваивания, в частности, переменные для накопления значений - счетчики, суммы, произве- дения - должны предварительно получить какое-то начальное значение. В про- тивном случае результат такого присваивания может быть непредсказуем – па- мять, отведенная под переменную, заполнена неизвестно чем. Не всякий ком- пилятор предупредит о не определенном в программе значении переменной.
7. Типы левой и правой частей любого оператора присваивания должны быть совместимы. Следя за этим самостоятельно, вы застрахуетесь от «изуро- дованных» значений, полученных при автоматическом, «по умолчанию», при- ведении типов.
8. Проверьте «выходы за пределы»: если в задаче предусматриваются ка- кие-либо предельные, граничные значения счетчиков, индексов, интервалов, отдельных величин, проанализируйте (самостоятельно, с помощью оператора If или дополнительной печати промежуточного результата), не превзойдены ли эти границы. Ошибки «пограничных ситуаций» наиболее типичны и трудно уловимы при просмотре текста программы.
9. Проверяйте ситуации «дурака»: всегда может найтись пользователь вашей программы, не выполнивший «очевидных» действий. Например, вы про- сите ввести ненулевое число и надеетесь поэтому, что ввели не ноль. Все на- дежные программы имеют «защиту от дурака» - операции проверки правильно- сти ввода, предупреждения о возможном неверном ходе выполнения и т.п.
1.4.1. Сборка программ
Большие, сложные программы трудно писать без ошибок. Даже автор программы часто не может оценить, что же именно происходит в его творении, и малейшее исправление уже работающей программы может привести к пол- ному краху всей системы. История программирования показывает все большее стремление к модульности в технологиях создания программ. Языки програм- мирования и поддерживающие их системы включают средства разбиения про- грамм на части (модули), отдельной компиляции этих частей и последующей сборки. При сборке программы могут сообщить друг другу свои результаты и эти результаты могут стать входом других программ. Такую связь по входу и
выходу обеспечивает механизм входных и выходных параметров, которые можно указать в заголовке программы. Так, если программа Р работает для входных данных Х и выдает результат – данные Y, а программа G использует эти данные, вычисляя результат Z, который в свою очередь принимает на вход программа R, то образуется цепочка P(X)
Y
⇨ G(Y)Z ⇨ R(Z)  … Оче- видно, чтобы такие последовательности вызовов программ работали правильно, необходимо, чтобы типы входных и выходных данных соответствовали друг другу, т.е. были совместимы. Так, если, например, Y на выходе P имеет цело- численный тип, а данные, воспринимаемые программой G должны быть сим-

25
вольными, то G(Y) работать не будет, либо будет работать с непредсказуемым результатом. Поэтому сборщику программ для каждой включаемой программы необходимо знать имя программы, тип ее входных данных (говорят, входных, input- параметров) и тип результата (говорят, выходных, output- параметров).
Такого рода рассуждения приводят к пониманию программы как данного особого типа, который характеризуется типами входных параметров и типом результата программы. Имя программы в таком случае может рассматриваться как имя переменной соответствующего типа. Например, программа с именем Р, имеющая два входных параметра, один из которых типа Integer, а другой – типа
String, и выдающая результат типа Single, может рассматриваться как перемен- ная Р типа (Integer, String)
 Single. Другая программа R с таким же типом входа и выхода будет другой переменной того же типа. Структура программы в таком случае не учитывается, программа рассматривается (с точки зрения сборщика) как «черный ящик». Значениями таких переменных можно считать состояния памяти, изменяемые при исполнении программы. Поэтому перемен- ные-программы имеют особый статус: им нельзя присваивать значений в про-
граммах, которые их используют.
Однако многие языки программирования допускают присваивания этим переменным внутри их тел, т.е., например, в программе P может (иногда, дол- жен) встретиться оператор Р = <значение>. Таким значением обычно является
результат ее работы, т.е. значение переменной-программы отождествляется с результатом ее выполнения. Это бывает удобно при определении программы как функции, т.е. Р(x,y) рассматривается как функция от аргументов x и y. Тогда вызов этой программы для заданных данных a и b может участвовать в выра- жениях другой программы, например, допустимо выражение 0.15 + P(a,b) -2.
При исполнении выражения вместо P(a,b) будет подставлен результат работы программы P на входных данных a и b.
Для использования в программе других программ, нужно отличать опи- сание программы от ее вызова.
1.4.2. Описание программ
Описание программы P(x,y,z) – это текст программы P, в котором x, y, z являются обозначениями входных (и, возможно, выходных) данных. Эти обо- значения называют формальными параметрами программы P. Описание обыч- но делят на заголовок и тело.
В заголовке указываются типы входных данных и результата (выходных данных). Если программа не вычисляет конкретное значение, например, просто печатает текст или производит различные действия со своими собственными переменными, не сообщая результаты в качестве выходных данных, то считает- ся, что результат имеет неопределенный тип (например, тип void в языке C++).
Такие программы называют часто процедурами. В отличие от них программы, вычисляющие определенное значение (некоторое число, текст, массив данных и т.п.), называют функциями. Говорят тогда, что функция возвращает значение.
Синтаксис заголовка программ в VBA:

26
Function <имя функции> (<список формальных параметров>)
<тип результата> или
Procedure <имя процедуры> (<список формальных параметров>).
Список формальных параметров – это последовательность пар: <имя формального параметра> <тип формального параметра>, разделенных запятой.
Например, функция, вычисляющая n! – факториал числа n, будет иметь в языке VBA заголовок: Function fact(n As Integer) As Integer.
Заголовок процедуры, вычисляющей сумму любых двух чисел и печатающей результат в диалоговом окне, может быть таким: Procedure Sum(x As
Single, y As Single).
Тело программы – это сама программа, описание ее собственных пере- менных и операторы, реализующие алгоритм. Так, полное описание функции fact:
Function fact(n As Integer) As Integer
fact = 1
If n > 1 Then
For i = 1 To n fact = fact * i
Next
End If
End Function
Полное описание процедуры Sum:
Sub Sum(x As Integer, y As Integer)
Dim S As Integer
S = x + y
MsgBox S
End Sub
Программа, используемая другой программой, может иметь статус под-
программы, и тогда ее описание может быть помещено внутри использующей программы, среди других ее описаний. Такая возможность предусмотрена, на- пример, в языках Pascal, Modula, Modula 2, Algol. Эти языки разрешают вло- женные описания подпрограмм (описание одной программы содержит описа- ние другой, оно, в свою очередь, содержит описание третьей и т. д.). В языках
С++, VBA программы имеют независимый статус, т.е. описываются отдельно от использующей программы, вложения описаний недопустимы. По описанию программы компилятор выделяет память, содержащую команды программы, память для переменных программы и память для ее формальных параметров
(пока пустую).
Для того, чтобы программа, содержащая параметры, заработала, нужно ее
вызвать, т.е. использующая программа должна содержать оператор вызова.

27
Вызов программы должен включать имя программы и набор конкретных значений, подставляемых вместо ее формальных параметров. Синтаксис вызова процедуры в VBA такой:
<имя процедуры> <список фактических параметров> или
Call <имя процедуры>(<список фактических параметров>).
Вызов функции имеет вид:
<имя функции> <список фактических параметров>.
Список фактических параметров – это последовательность фактических параметров, разделенных запятой. В качестве фактического параметра может выступать значение, переменная, выражение, вызов функции.
Вызов процедуры – это независимый оператор, он не может стоять в пра- вой части присваиваний, поскольку не возвращает значения.
Вызов функции, напротив, должен стоять в правых частях присваиваний, он может быть операндом выражения, т.к. возвращает значение, которое и ис- пользуется при вычислении выражения.
Механизм реализации вызова таков. В точке вызова управление передает- ся указанной программе; переменные, указанные в качестве имен формальных параметров получают конкретные значения, заданные через фактические пара- метры (говорят, фактические параметры подставляются вместо формальных).
Программа исполняется с этими фактическими значениями параметров. Если программа является функцией, то ее значение (результат работы) возвращается в точку вызова и может быть использовано, например, в выражении. Если про- грамма – процедура, то после ее исполнения просто происходит возврат управ- ления в точку вызова, следующему за вызовом оператору.
Например, программа, содержащая вызовы процедуры Sum и функции fact, может быть такой (после знака ‘ идет однострочный комментарий):
Sub vysov()
Dim k As Integer
k = fact(5) ‘функция fact вызвана с фактическим параметром
5, результат 120
k = fact(4)+10+k
функция fact вызвана с фактическим
параметром 4, ее результат 64
MsgBox k
Sum 5, 10
процедура Sum вызвана с фактическими параметрами
5 и 10
Call Sum(10,20)
другой способ вызова Sum с фактическими
параметрами 10 и 20
Sum k, 2
процедура Sum вызвана с фактическими параметрами
k и 2
End Sub

28
Поскольку при вызове фактические значения замещают формальные, ис- пользуя отведенную для формальных параметров память, типы формальных и
фактических параметров должны совпадать или быть совместимыми. Так, вызов Call Sum(2.5, 4) не осуществится из-за типовой ошибки – число 2.5 не является целым.
Программы – процедуры и функции могут быть собраны в автономно существующие, например, в рамках проекта, более «крупные» единицы – мо- дули. Такое понимание модуля характерно для VBA. В других языках про- граммирования модулем часто называют программу, имеющую автономный статус: она может быть откомпилирована независимо от других программ. Для обеспечения этой возможности программе сообщаются только типы входных данных, в том числе – типы других программ, используемых в теле. Эти типы оформляются синтаксически специальным образом и называют «интерфей- сом». Таким образом, для компиляции модуля необходимо описание его про- граммы и интерфейсов используемых в нем других программ.
Видимость переменных. При всякой сборке возникает вопрос: могут ли программы использовать имена и значения переменных из других программ?
Этот вопрос решается для каждого языка программирования в разделе, назы- ваемом правилами видимости переменных. Если «чужую» (не описанную в данной программе) переменную можно использовать, то, говорят, что эта пере- менная видна в программе.
Считается хорошим стилем, если программа достаточно автономна: все, что ей требуется извне, должно быть передано через ее фактические параметры.
Но соблюдение этого принципа может привести к необозримому разрастанию списка параметров. Поэтому большинство языков программирования допускает использование так называемых глобальных данных, переданных через глобаль- ные, внешние (extern-), общие (common-) переменные. Такие переменные вид- ны всем программам модуля или приложения. В VBA переменные, описанные в модуле отдельно от всех его программ, делают их доступными в теле любой программы модуля. Например, описание:
Dim a As Integer, b As Integer
Sub P1 (x As Single, y As String) As Single
……….
a = 7
……….
End Sub
Sub P2 ( x As Integer) As Boolean
……….
b = a*3 + x
……….
End Sub
позволяет использовать глобальные переменные a и b в любом операторе про- грамм P1 и P2 и изменять их первоначальные значения. Описание этих же пе-

29
ременных с ключевым словом Public, т.е. Public a As Integer, b As Integer де- лает их видимыми (доступными для использования и изменения) в любом мо- дуле проекта.
Слова Public и Private, называемые иногда спецификаторами доступа
регламентируют возможность использования переменных и объектов, к кото- рым они приписаны, в других программных единицах: модулях, классах, про- ектах. Как правило, Public означает общедоступность объекта, Private – доступ- ность только в конкретном модуле или классе. Если спецификатор не указан, то тип доступа считается Private.
Для VBA действуют следующие правила видимости:
 Переменные, описанные в процедуре или функции, видны только в ней. Они объявляются с помощью ключевого слова Dim или Static и называют- ся локальными.
 Переменные, описанные в модуле вне описаний программ модуля с ключевыми словами Dim или Private, видны во всех программах этого модуля.
В других модулях они не видны.
 Переменные, описанные в модуле вне описаний программ модуля с ключевым словом Public, видны во всех модулях (процедурах, функциях) про- екта.
Декомпозиция
программ.
Разбиение программы на части

(под)программы имеет смысл, когда программа слишком объемна или содер- жит группы операторов, которые реализуют одну и ту же цель, но с разными данными или в разных местах исходной программы. Например, требуется най- ти максимальный элемент в массиве, значения которого в программе периоди- чески меняются или необходимо определить истинность формулы для разных сочетаний значений ее переменных. В этом случае удобно группу операторов, выполняющую эту задачу, оформить в отдельную программу – процедуру или функцию. Данные, для которых эти операторы выполняли свою работу, могут передаваться в эту программу в качестве параметров. Тогда в исходной про- грамме вместо группы операторов будет стоять вызов соответствующей проце- дуры. Например, «некрасивая» исходная программа вычисляет значение истин- ности формулы x&y
 x   (x  y) для значений переменных x=1, y=0; x=0, y=1; x=1, y=1:
Sub P ( )
Dim x As Boolean, y As Boolean, res As Boolean
x=1
y=0
res = x And y Or x Or Not( x Imp y)
MsgBox res x=0
y=1
res = x And y Or x Or Not( x Imp y)
MsgBox res

30
x=1
y=1
res = x And y Or x Or Not( x Imp y)
MsgBox res
End Sub
Эта программа может быть преобразована в две программы более просто- го вида:
Sub P ( )
MsgBox F(1,0)
MsgBox F(0,1)
MsgBox F(1,1)
End Sub
Function F (x As Boolean, y As Boolean) As Boolean
F = x And y Or x Or Not( x Imp y)
End Function
Помимо более простого (а, значит, и более понимаемого и легче тести- руемого) вида программ такая декомпозиция дает возможность использовать функцию F в других программах и модулях. Все это позволяет делать приложе- ния более технологичными, менее «кустарными», хорошо «вписываемыми» в другие программные комплексы.
1   2   3   4   5   6   7   8


написать администратору сайта