Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Информатика

.pdf
Скачиваний:
24
Добавлен:
03.05.2015
Размер:
3.59 Mб
Скачать

21

1.4. ФУНКЦИИ И ПОДПРОГРАММЫ

Функция – это отдельная самостоятельная программа, возвращающая результат в виде значения определенного типа. Поэтому имя функции может содержаться в любом арифмерическом операторе и операторе присваивания наравне с любыми другими переменными и константами. В VBA функция определяется заголовком

Function ‹имя›([аргументы]) As ‹возвращаемый тип›,

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

End Function.

Таким образом, рабочая часть (тело функции) должна быть заключена между "операторными скобками" Function - End Function. Аргументы функции (если они есть) должны быть указаны вместе со своим типом (в противном случае они будут иметь тип Variant), тип возвращаемого значения тоже должен быть указан. В теле функции (т.е. в ее программной части) должно быть хоть одно присваивание переменной с именем функции, иначе она будет возвращать нулевое значение.

При описании функции имена аргументов – формальные, при использовании функции они заменяются фактическими. Здесь возможны два способа замены формальных параметров фактическими. Первый – вместо формальных параметров подставляются копии значений фактических параметров, так что любые их изменения внутри функции не отражаются на фактических параметрах. Второй – формальным параметрам ставится в соответствие ссылка на фактические параметры, так что изменение значений параметров внутри функции изменит значения и фактических параметров. Поэтому полезно в первом случае указывать при определении функции параметры со служебными словами ByVal (по значению), во втором случае – ByRef (по ссылке). По умолчанию (если явно не указано) имеется в виду второй способ – ссылка на фактические параметры (ByRef).

Пример. Как известно, наибольшее значение чисел х и у можно вычислить по формуле: max(x, y) = 0.5∙(x + y + |x - y|). Рассмотрим следующий код:

Dim a As Single, b As Single

'*** определение функции

Function Max(x As Single, y As Single) As Single

y = 0.5*(x + y + Abs(x - y)) '*** изменение второго аргумента

Max = y

End Function

'*** ввод чисел а и b

а = Val(InputBox("введите значение а", "", 0))

22

b = Val(InputBox("введите значение b", "", 0))

'*** вывод Max(a, b), a, b

MsgBox "max=" & Format(Max(a, b)) & ", a=" & Format(a) _ & ", b=" & Format(b) .

Введя a = 15, b = 7, получим результат:

max=15, a=15, b=15.

Значение b изменилось, так как оно было введено по ссылке (умолчание). Если бы в определении функции явно сослались на значение аргумента

Function Max(ByVal x As Single, ByVal y As Single) As Single,

то получили бы результат: max=15, a=15, b=7 (заметим, что в действительности в теле функции можно было бы сразу выполнить присваивание Max = 0.5*(x + y + Abs(x - y)), приведенный вариант имеет чисто демонстрационное значение).

Переменные, определенные вне функции, являются определенными и внутри функции (если они не переопределены), определенные внутри функции оказываются недоступны вне ее (локальное определение). Здесь применяется правило наследования: "что снаружи, то и внутри", но не наоборот. Если желательно сделать переменные (или функции) доступными всюду, то их необходимо сделать как можно более "внешними" и вместо инструкции Dim использовать инструкцию Public. Принудительный выход из функции – Exit Function.

Mcd не требует определения типов (их всего два и они легко различаются: строка всегда заключена в кавычки). Кроме того, функции могут возвращать любой вычислимый объект, будь то число, вектор, матрица, и т.д. Имени функции не нужно присваивать возвращаемое выражение, оно обычно указывается самостоятельно в конце блока определения функции, либо после служебного слова "return". Параметры функции вводятся (по умолчанию) как значения фактических параметров (т.е. ByVal), а сама функция определяется с помощью оператора присваивания. Функцию последнего примера в Mcd можно определить совсем просто:

Max(x,y) :– 0.5∙(x + y + |x - y|).

Подпрограмма не допускает присваивания ее имени какого-либо значения, она ничего не возвращают, она является методом реализации какого-то процесса. В отличие от функции она определяется "операторными скобками" Sub ‹имя› ([параметры]) ... End Sub.

Запускать подпрограмму самостоятельно можно так же, как любую программу (Run, F5, и т.д.). Внутри другой программы ее можно вызвать, указав ее имя и параметры (в VBA – без скобок). Подпрограммы без параметров (но со скобками) иногда называются макросами.

23

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

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

1.5.РАЗВЕТВЛЕНИЕ И АЛЬТЕРНАТИВА

1.5.1.Безусловный выбор

Обычное разветвление программы осуществляется с помощью оператора GoTo ‹метка›, либо оператором перехода с выбором:

On ‹арифм. выражение› GoTo ‹метка1›, ‹метка2›, ...

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

Sub Roots(a As single, b As Single, c As single) Dim i As Integer, d As Single

d = b*b – 4*a*c: i = 2 + Sgn(d) On i GoTo Zero, One, Two

Ex: MsgBox "Задача решена": End

Zero: MsgBox "Действительных корней нет": End

One: MsgBox "Один корень х=" & Format(-0.5*b/a): GoTo Ex Two: d = Sqr(d)

MsgBox "Два корня: " & Format(0.5*(d-b)/a) & _ "и " & Format(-0.5*(d+b)/a): GoTo Ex

End Sub .

Полезно отметить, что безусловный переход не популярен в программировании, это своего рода анахронизм. В Mcd он вообще отсутствует.

1.5.2.Условный выбор

ВVBA используются три вида операторов. 1) Простое условие реализуется оператором

If ‹условие› Then ‹оператор1›.

Оператор1 выполняется, если указанное условие удовлетворено, в противном случае программа переходит к выполнению следующей за условным оператором строки.

2) Условие с альтернативой реализуется оператором

If ‹условие› Then ‹оператор1Else ‹оператор2›,

24

при этом оператор1 и (или) оператор2 сами могут быть условными операторами. Здесь условие должно быть логическим выражением, возможно с использованием логических связок: Or = "или", And = "и", Xor = "разделенное или", Not = "не" в соответствии со следующей таблицей истинности (см. табл. 5):

Таблица 5

x

y

x Or y

x Xor y

x And y

True

True

True

False

True

True

False

True

True

False

False

True

True

True

False

False

False

False

False

False

Любые другие логические формулы получаются из приведенных в таблице. При логических сравнениях используются символы: =, <, >. Сравнения ≤, ≥, ≠ записываются соответственно как <=, >=, <>.

В качестве условия может быть использована также функция MsgBox с диалоговым окном, содержащим кнопки выбора: "Yes", "No", "Cancel", и другие. Например, код:

If MsgBox("Продолжить вычисления?", vbYesNo, "АЛЬТЕРНАТИВА") _ = vbNo Then End

заканчивает работу программы, если на панели окна выбрана кнопка

"No", в противном случае работа продолжается.

 

 

Пусть

требуется

при заданных значениях х и у

вычислить

 

 

0 при x = y,

 

 

 

 

x

 

y

 

 

 

 

1 +

2

+

6

при ху и х+2 ≠ у,

 

 

выражение

f =

 

 

2

 

Запишем

условный

 

 

 

 

1 + x-y

1 при y = x+ 2,

-1 в ост. случаях.

оператор (присвоение должно быть при каждом условии):

If x = y Then f = 0 Else If (x<>y) And (y<>x+2) Then _

f = (1 + x/2 + y/6) / (1 + 2/(x – y)) Else If y = x+2 Then f = 1 _ Else f = -1

(внимание! Условный оператор должен быть записан в одной строке, здесь использовано продолжение строки: пробел + подчеркивание).

В Mcd есть специальная функция, возвращающая значение с условием (ее можно найти в общем списке функций, см рис. 3) вида if(▪, ▪, ▪), в которой на первом месте стоит условие, на втором – арифметический оператор1, на третьем – арифметический оператор2. Функция допускает многократные вложения, так, предыдущий пример можно записать в Mcd следующим образом:

Рис. 5

25

.

Как показывает пример, Mcd использует иные обозначения для записи логических условий: неравенство записывается привычным знаком, сравнение записыается "утолщенным" знаком

равенства, связка And записывается как " ",

Or – как " ", Xor – как " ", Not – как "|"

(см. рис. 4).

3) Условный блок записывается в форме:

Рис. 4

If ‹условие› Then ‹блок операторов

Else

‹блок операторов›

End If.

При этом блок Else (который может отсутствовать, если нет альтернативы) может сам обрабатывать условие в виде блока

ElseIf ‹условие› Then

‹блок операторов›.

В этом случае (в отличие от простого или альтернативного условия) каждый элемент условного оператора (т.е. If – Then, ElseIf - Then, Else, End If) должен быть записан в отдельной строке.

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

Вертикальную черту, как и другие операторы программирования, можно ввести из меню программирования, щелкнув мышкой по иконке и выбрав из раскрывающегося меню (рис. 5) необходимый оператор. Здесь "Add Line" – вставка вертикальной черты, "If" – условный оператор (исполняемая часть стоит перед If, условие – после), альтернативе Else соответствует оператор "otherwise". Присваивание в

программах и блоках всегда записывается левой стрелкой. Оператор "return" возвращает указанное значение.

26

Разберем в качестве примера рассмотренную выше задачу (см. п. 1.5.1): выяснить все возможные случаи наличия или отсутствия действительных корней квадратного трехчлена ax2 + bx + c в зависимости от значений его коэффициентов. Здесь возможно следующее.

1.Коэффициент а = 0.

2.Если при этом и b = 0, то приходим к равенству с = 0, которое

невозможно при с0 3. Но если и с = 0, то трехчлен тождественно равен нулю

при любом значении аргумента х.

4.Если же b0 (при а = 0), то решение очевидно: единственный действительный корень x = - bc , конец задачи.

5.Если а0, то можно вычислить дискриминант d = b2 - 4ac.

6.Если он отрицательный, то действительных корней нет, задача закончена.

7.В противном случае вычисляем корень из дискриминанта, полагая d :– d.

8.Если значение d мало по абсолютной величине, то его можно считать равным нулю и указать действительный

корень x = - 2ab , решение закончено.

9. Иначе указываем два корня

-b-d

и

d-b

. Анализ закончен.

2a

2a

Упражнение. Постройте блок-схему приведенного анализа. Здесь почти каждое условие имеет свою альтернативу If – Then –

Else и обработка некоторых условий требует больше одного оператора. Поэтому код программы следует организовать в виде условного блока. В VBA реализуем его в виде подпрограммы:

Sub TrinomRoots(a As Single, b As single, c As Single) Dim d As Single, x1 As Single, x2 As Single

Const eps As Single = 1E-6 '*** константа для разделения корней

If a = 0 Then

If b = 0 Then

If c = 0 Then MsgBox "корень – любое число" _ Else MsgBox "корней нет"

Else

MsgBox "корень= " & Format(-c/b) End If

Else

d = b^2 – 4*a*c If d < 0 Then

MsgBox "действительных корней нет"

Else

d = Sqr(d)

If d < eps Then

27

MsgBox "один корень= " & Format(-b/(2*a))

Else

x1 = -(b + d)/(2*a): x2 = (d – b)/(2*a)

MsgBox "два корня: " & Format(x1) & "и " & Format(x2) End If

End If End If

End Sub .

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

ссамого начала приучать себя к "культуре" записи кодов.

ВMcd пример можно реализовать в виде функции:

TrinomRoots(a, b, c) :–

 

ε 0.000001

 

 

 

 

 

if a = 0

 

 

 

 

if b = 0

 

 

 

 

 

 

 

 

 

 

return "любое число" if c = 0

 

 

 

 

 

return "нет корней" otherwise

 

 

 

 

 

 

-c

 

 

 

 

return

otherwise

 

 

 

 

 

 

 

b

 

 

 

otherwise

 

 

 

 

d ← b2 – 4∙a∙c

 

 

 

 

 

 

 

 

return "действительных корней нет" if d < 0

 

 

 

otherwise

 

 

 

 

 

 

return

-b

if

d < ε

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2∙a

 

 

 

 

 

 

 

 

-b-d

 

 

 

 

 

return 2∙a

otherwise

 

 

 

 

 

 

 

 

d-b

 

 

 

 

 

 

 

 

 

2∙a

 

 

 

 

 

 

 

 

 

 

 

 

 

Записав теперь TrinomRoots(3, 2, -1) = -3 , получим значения кор-

2.333

ней трехчлена 3х2 + 2х - 1. Для вывода значений обоих корней (последняя строка функции) можно, щелкнув мышкой по иконке меню, вызвать меню матричных операторов (рис. 6), щелчок по иконке матрицы вызывает меню вставки матрицы, где можно выбрать нужный размер (в нашем случае две строки и один столбец). Это

можно сделать и с клавиату- Рис. 6 ры, набрав Ctr +"M".

28

Сравнивая эти две программы, легко заметить почти полную их идентичность: конструкция If Then Else VBA однозначно соот-

ветствует паре if otherwise Mcd, MsgBox return, а блок операторов наглядно представлен вертикальной чертой. Кроме того, если операторы вводить из соответствующего меню, то они вставляются вместе с указанием мест (в виде черных квадратиков) для помещения объектов действия. Например, условный оператор вводится как ▪ if ▪ - в место левого квадратика вводится оператор, в место правого – условие. Если необходимо построить условный блок, то в позицию левого квадратика вводится "Add Line". Аналогично, альтернатива вводится как ▪ otherwise, вывод – как return ▪, и т.д., так что все становится достаточно прозрачным.

1.5.3. Альтернативный выбор

Это – выбор по значению. Он реализуется блоком Select Case, который имеет структуру:

Select Case ‹идентификатор›

 

Case ‹выражение›

'***конкретное значение

‹блок операторов›

 

Case ‹выр.›, ‹выр.› Is ‹сравнение› ‹выражение› '***сравнение

‹блок операторов›

 

Case ‹выр.› To ‹выр.›

'***перечисление

‹блок операторов›

 

Case Else

'***все остальное

End Select

 

(Select Case – End Select – своеобразные "операторные скобки").

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

Пусть, например, необходимо знать, есть ли в предлагаемом тексте цифры, буквы латинского алфавита, буквы кириллицы. Это можно сделать с помощью программы:

Sub Analysis(txt As String)

Dim n As Integer, i As Integer, s As String*1, Cyf As Byte, Lat As Byte

Dim Cir As Byte, Rest As Integer

 

 

n = Len(txt): txt = LCase(txt)

'***перевод в нижний регистр

Start: i = i + 1: t = Mid(txt, i, 1)

 

 

Select Case t

 

 

Case "0" To "9": Cyf = Cyf + 1

'***считаем цифры

Case "a" To "z": Lat = Lat + 1

'***считаем буквы латинницы

Case "а" To "я": Cir = Cir + 1

'***считаем буквы кириллицы

Case Else: Rest = Rest + 1

 

'***считаем все остальное

End select

 

 

If i < n Then GoTo Start

 

 

29

MsgBox "В данном тексте:" & Chr(13) & _ '***переход на новую строку

"цифр -" & Format(Cyf) & Chr(13) & _ "латинских букв -" & Format(Lat) & Chr(13) & _ "букв кириллицы -" & Format(Cir) & Chr(13) & _ "прочих символов -" & Format(Rest)

End Sub .

Участок программы Start – GoTo Start лучше выполнять с помощью конструкции цикла (см. следующий пункт).

1.6. ЦИКЛЫ

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

Цикл

заголовок

 

тело цикла

 

конец

цикла

 

группа операторов

 

цикла

 

 

 

 

 

 

 

 

 

Заголовок цикла и конец цикла образуют своеобразные "операторные скобки", которые, собственно, и определяют тип цикла. В VBA используются, в основном, следующие типы циклов.

1) Безусловный цикл: заголовок

 

DO

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

конец

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

LOOP

 

 

 

 

 

 

2) Цикл пересчета имеет сложный заголовок.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

стартовое

конечное

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Заголовок:

 

For

‹счетчик› =

 

 

 

 

 

To

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

значение

 

значение

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

шаг изменения

 

 

 

 

 

 

 

 

 

 

 

 

 

Step

 

счетчика

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Конец:

 

 

NEXT

 

 

 

 

 

 

 

 

 

 

 

 

 

3) Цикл с предусловием

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

заголовок

While ‹ усл. ›

 

Do While ‹ усл. ›

 

Do

 

конец

 

Wend

 

 

 

Loop

Loop While ‹ усл. ›

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

4) Цикл с постусловием

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

заголовок

 

 

Do Until ‹ усл.›

 

Do

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

30

конец

Loop

Loop Until ‹ усл. ›

 

 

 

Выход из цикла можно осуществить с помощью оператора Exit

суказателем типа цикла, т.е. Exit Do или Exit For.

ВMcd применяются лишь два типа циклов: цикл пересчета For ...

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

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

min{x : |sin(x)| < 0.0001}. Здесь достаточно перебирать последовательно все натуральные числа и остановить перебор, когда выполнится требуемое условие. Для этой цели подойдет любой тип цикла. Посмотрим, как это будет выглядеть в VBA.

Безусловный цикл:

Цикл пересчета:

Цикл с предусловием:

или

Цикл с постусловием:

Dim n As Integer

Do: n = n + 1

If Abs(Sin(n)) < 0.0001 Then Exit Do

Loop

Dim n As Long

For n = 1 To 1000000000

If Abs(Sin(n)) < 0.0001 Then Exit For

Next

Dim n As integer n = 1

While Abs(Sin(n)) >= 0.0001 n = n + 1

Wend

Do While Abs(Sin(n)) >= 0.0001 n = n + 1

Loop

Dim n As Integer

Do: n = n + 1

Loop Until Abs(Sin(n)) < 0.0001

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