Программирование на visual basic
Скачать 1.19 Mb.
|
4.1.4. Произвольное число параметров При использовании атрибута ParamArray в фактические параметры можно включать произвольное число данных разделенных запятыми. Фор- мальный параметр с атрибутом ParamArray должен быть последним в спи- ске. При этом такой формальный параметр в функции используется как мас- сив типа Variant. В качестве примера напишем функцию, которая вычисляет среднеарифметическое знвачение всех своих аргументов. Function Среднеарифметическое(ParamArray a() As Variant) As Double Dim s As Double s = 0 'Цикл по всем формальным параметрам 'LBound - нижняя граница массива (0 или 1. Зависит от настройки ‘ Option Base) 'UBound - верхняя граница массива For i = LBound(a) To UBound(a) s = s + a(i) Next i 'UBound(a) - LBound(a) + 1 - количество элементов в массиве Среднеарифметическое = s / (UBound(a) - LBound(a) + 1) End Function Sub ТестParamArray() Debug.Print "Пять параметров типа Integer "; _ Среднеарифметическое(1, 2, 3, 4, 5);”.” Debug.Print "Четыре параметра типа Double "; _ Среднеарифметическое(3.57, 94.23, 10.22, 11);”.” End Sub Результаты работы программы: Пять параметров типа Integer 3. Четыре параметра типа Double 29,755. Рассмотрим еще один пример на использование атрибута ParamArray. Напишем функцию, которая вычисляет сумму всех фактических аргумен- тов произвольного типа . Function СуммаПеременногоЧислаСлагаемыхРазличныхТипов (ParamArray a() As Variant) As Variant Dim s As Variant 48 For i = LBound(a) To UBound(a) s = s + a(i) Next i СуммаПеременногоЧислаСлагаемыхРазличныхТипов = s End Function Sub ТестParamArray1() Debug.Print СуммаПеременногоЧислаСлагаемыхРазличныхТипов ("Петров", " ", "Иван", " ", "Леонидович");”.” Debug.Print СуммаПеременногоЧислаСлагаемыхРазличныхТипов (1, 2, 3);”.” Debug.Print СуммаПеременногоЧислаСлагаемыхРазличныхТипов _ (3.57, 94.23, 10.22, 11);”.” End Sub Результаты работы программы: Петров Иван Леонидович. 6 . 119,02. 4.1.5. Оператор Exit Function Если подпрограмму-функцию необходимо по каким-то причинам преры- вать внутри, то можно использовать оператор Exit Function. При встрече этого оператора происходит завершение работы функции и передача управ- ления в то место программы, откуда была вызвана функция. При отсутствии оператора Exit Function функция выполняется до оператора End Function. 4.1.6. Особенности использования в качестве формальных па- раметров массивов Память для формальных параметров определяется компилятором в вы- зывающих функцию программных модулях (основной программе, другой функции или подпрограмме), а в функцию передается только адрес начала массива. Поэтому при описании массивов в функциях есть некоторые осо- бенности. Пример1. Написать функцию, которая вычисляет среднее значение эле- ментов одномерного массива. Для отладки функции напишем основную программу, в которой с кла- виатуры введем размерность n динамического массива a ; заполним массив случайными числами в диапазоне от 0 до 100; напечатаем его в окне отладки и вызовем функцию funs(a, n), в которой будет подсчитано среднее значение элементов массива a . В качестве первого формального параметра указывает- ся имя массива, но без размерности. Sub ОдномерныеМассивыВКачествеФормальныхПараметров() Dim n As Long, a() As Long, i As Long n = Val(InputBox("Введите размерность массива")) Randomize Timer ' Генерация ряда случайных чисел 49 ReDim a(1 To n) ' Создание динамического массива Debug.Print " Массив a="; For i = 1 To n ' Заполнение массива случайными числами a(i) = Rnd * 100 Debug.Print a(i); Next i Debug.Print Debug.Print "Среднее значение="; funs(a, n) End Sub ' Функция, вычисляющая среднеарифметическое значение массива Function funs(a() As Long, n As Long) As Double Dim s As Long, i As Long s = 0 For i = 1 To n s = s + a(i) Next i funs = s / n End Function Пример 2. Написать функцию, которая вычисляет среднее значение эле- ментов двухмерного массива, состоящего из n строк и m столбцов. Sub ДвухМерныеМассивыВКачествеФормальныхПараметров() Dim n As Long, a() As Long, i As Long, j As Long, m As Long n = Val(InputBox("Введите число строк")) m = Val(InputBox("Введите число столбцов")) Randomize Timer ‘ Построение ряда псевдослучайных чисел ReDim a(1 To n, 1 To m) ‘ Двухмерный динамический массив Debug.Print " Массив a=";: Debug.Print For i = 1 To n For j = 1 To m a(i, j) = Rnd * 100: Debug.Print a(i, j); Next j: Debug.Print ‘ Перейти на следующую строку Next i Debug.Print: Debug.Print "Среднее значение="; funs2(a, n, m): Debug.Print End Sub ' Функция, вычисляющая среднеарифметическое значение массива Function funs2(a() As Long, n As Long, m As Long) As Double Dim s As Long, i As Long, j As Long ‘В этой переменной накапливаем сумму всех элементов матрицы s = 0 For i = 1 To n ‘ Обход по всем элементам матрицы For j = 1 To m s = s + a(i, j) ‘ Накапливаем сумму элемента a i,j Next j, I ‘Вычисляем среднее значение элементов матрицы a funs2 = s / (n * m) End Function 50 4.2. Подпрограммы Подпрограммой называется поименованная часть программы, имеющая формальные параметры и которую можно вызвать на выполнение с любой точки основной программы, а также других подпрограмм или функций. Подпрограмма является расширением функции, и ее можно рассматривать как математическое отображение n-мерного пространства множества значе- ний аргументов на m-мерное пространство множества значений отображе- ния. Обычно подпрограмма имеет входные и выходные параметры. Входные параметры ⎯ это такие параметры, которые остаются без изменения в под- программе. Выходные параметры — это параметры, которые при вызове подпрограммы имеют неопределенное значения, а в ходе выполнения про- граммы получают определенное значение, зависящее от входных парамет- ров. Правда, часто параметры бывают одновременно и входными, и выход- ными. Входные параметры должны иметь атрибуты ByVal. 4.2.1. Оператор описания подпрограммы SUB Подпрограмма определяется ключевым словом SUB. Общая форма под- программы почти такая же, как и подпрограммы-функции: SUB имя( a1 ,a2, …, an ) неисполняемые операторы (операторы описания) исполняемые операторы, среди которых могут быть операторы [Exit Sub] END где имя - имя подпрограммы; ai - формальные параметры (аргументы). Формальный параметр ai имеет синтаксис такой же, как и для функций: [Optional] [ByVal | ByRef] [ParamArray] имяПеременной [() ] [As тип] [=значениеПоУмолчанию] При вызове программа выполняется от первого выполняемого оператора до первого встреченного оператора Exit Sub или до оператора End Sub, кото- рый является последним оператором в подпрограмме. В подпрограмме имя подпрограммы не несет на себе числовую информацию. 4.2.2. Оператор вызова подпрограммы CALL В отличие от функции подпрограмма вызывается отдельным оператором вызова CALL следующим образом: CALL ИМЯ(y1,y2,….,yn) где y1,y2,…,yn - фактические параметры, которые могут быть констан- тами (если формальные параметры являются только входными параметра- ми), простыми переменными любого типа, элементами массивов, массивами, элементами пользовательского типа, арифметическими выражениями, име- нами подпрограмм или подпрограмм-функций, именами встроенных функ- ций или подпрограмм. Естественно, между формальными и фактическими переменными должно быть соответствие типов. 51 4.2.3. Примеры подпрограмм Пример 1. Три матрицы A, B и C порядка N заполняются случайными числами в диапазоне от -5 до 5. Вычислить нормы произведения матриц AB, AC и BC. Норма матрицы равна корню квадратному от суммы квадратов всех элементов матрицы. Option Explicit Option Base 1 Sub НормаМатриц() Const n = 3 ' Порядок матриц Dim a(n, n) As Long, b(n, n) As Long, c(n, n) As Long, Dim d(n, n) As Long, i As Long, j As Long Randomize Timer For i = 1 To n ' Заполнение всех массивов случайными числами For j = 1 To n a(i, j) = Rnd * 10 - 5 b(i, j) = Rnd * 10 - 5 c(i, j) = Rnd * 10 - 5 Next j, i ' Вывод в окно отладки полученных матриц Call printMatr(a, n, "матрица a=") Call printMatr(b, n, "матрица b=") Call printMatr(c, n, "матрица c=") ' Умножение матриц a на b, результат записать в d Call MultMatr(a, b, d, n) Call printMatr(d, n, "матрица ab") ' Вычисление и вывод нормы матрицы d Debug.Print "Норма матрицы AB="; NormaMatr(d, n) ' Умножение матриц a на c, результат записать в d Call MultMatr(a, c, d, n) Call printMatr(d, n, "матрица ac") ' Вычисление и вывод нормы матрицы d Debug.Print "Норма матрицы AC=", NormaMatr(d, n) ' Умножение матриц b на c, результат записать в d Call MultMatr(b, c, d, n) Call printMatr(d, n, "матрица bc") Debug.Print "Норма матрицы BC=", NormaMatr(d, n) End Sub 'Подпрограмма для вычисления произведения двух матриц C=AB Sub MultMatr(a() As Long, b() As Long, c() As Long, n) Dim s As Double, i As Long, j As Long, k As Long For i = 1 To n For j = 1 To n s = 0 ' Скалярное произведение i-той строки на k-тый столбец For k = 1 To n s = s + a(i, k) * b(k, j) Next k 52 c(i, j) = s Next j, i End Sub ' Функция для вычисления нормы матрицы a Function NormaMatr(a() As Long, n) As Double Dim s As Double, i As Long, j As Long s = 0 ' Вычисление суммы квадратов всех n^2 элементов матрицы For i = 1 To n For j = 1 To n s = s + a(i, j) ^ 2 Next j, i NormaMatr = Sqr(s) ' Норма матрицы a End Function Sub printMatr(a() As Long, n, s As String) ' Вывести на экран массив Dim i As Long, j As Long Debug.Print s ' Вывести заглавие For i = 1 To n For j = 1 To n ' Вывод i - той строки матрицы a Debug.Print a(i, j); Next j Debug.Print ' Перейти на новую строку Next i End Sub В данном примере приведены две подпрограммы MultMatr и printMatr и одна функция NormaMatr, которые вызываются несколько раз с различ- ными фактическими параметрами. В подпрограмме MultMatr четыре фор- мальных параметра a, b, c и n. Первые три параметра являются двухмер- ными массивами. При этом a, b и n — только входные параметры, так как внутри подпрограммы они не изменяются, а массив d является выходным параметром, поскольку он получается внутри подпрограммы. Умножение двух матриц A на B производится по формуле где c ij - элементы результирующей матрицы. В подпрограмме printMatr — два формальных параметра a и s. Эта про- грамма печатает на одной строке заглавие содержащейся в строковой пе- ременной s, а на следующих n строках построчно печатает матрицу A. Необходимо отметить, что для перехода к решению задачи с матрица- ми другого порядка необходимо всего лишь изменить одну цифру 3 в опе- раторе Const n = 3 Правилом хорошего тона считается стремление к ра- зумному универсализму программы. ∑ = = n k kj ik ij b a c 1 , 53 4.2.4. Способы передачи формальных параметров По умолчанию формальные параметры, используемые в подпрограм- мах, передаются по ссылке или адресу. Это означает, что для переменных не создается копия внутри подпрограммы или подпрограммы-функции, а все вычисления происходят в ячейках, отведенных компиляторам для формального аргумента. После выхода из подпрограммы или подпрограм- мы-функции значения фактических параметров соответствуют значению в подпрограмме. Для передачи формальных параметров по значению необходимо таким параметрам присваивать атрибут ByVal. Пример. Рассмотрим простейшую подпрограмму с двумя формальны- ми параметрами a и b. Подпрограмма должна переставлять значения фор- мальных параметров местами. В программе, представленной ниже, приве- дены три подпрограммы: Swap и SwapByRef, SwapByVal. Первые две пе- редают оба параметра по ссылке, а третья — по значению. Ниже приведены результаты работы программы. Перед вызовом всех подпрограмм задаются значения фактических параметров a=1, b=2. Внутри подпрограмм парамет- ры правильно обменивают свои значения. После возвращения в вызываю- щую программу подпрограмма SwapByVal не изменяет значения фактиче- ских параметров, а остальные подпрограммы инвертируют параметры. Sub swap(a As Long, b As Long) Dim c As Long c = a: a = b: b = c Debug.Print "Внутри подпрограммы Swap a="; a; " b= "; b End Sub Sub SwapByRef(ByRef a As Long, ByRef b As Long) Dim c As Long c = a: a = b: b = c Debug.Print "Внутри подпрограммы SwapByRef a="; a; " b="; b End Sub Sub SwapByVal(ByVal a As Long, ByVal b As Long) Dim c As Long c = a: a = b: b = c Debug.Print "Внутри подпрограммы SwapByVal a="; a; " b="; b End Sub Sub ОсновнаяПрограмммаТестирующаяТипыПередачиАргументов() Dim a As Long, b As Long Call swap(a, b) Debug.Print "После подпрограммы Swap a="; a; " b="; b a = 1: b = 2 Call SwapByRef(a, b) Debug.Print "После подпрограммы SwapByRef a="; a; " b="; b a = 1: b = 2 Call SwapByVal(a, b) 54 Debug.Print "После подпрограммы SwapByVal a="; a; " b="; b End Sub Вывод программы Внутри подпрограммы Swap a = 2 b = 1 После подпрограммы Swap a = 2 b = 1 Внутри подпрограммы SwapByRef a = 2 b = 1 После подпрограммы SwapByRef a = 2 b = 1 Внутри подпрограммы SwapByVal a = 2 b = 1 После подпрограммы SwapByVal a = 1 b = 2 5. Ввод-вывод данных Для работы программ часто необходимо вводить в оперативную память исходные данные с клавиатуры, рабочего листа или текстовых файлов. Ос- новные и промежуточные результаты работы программ выводятся из опе- ративной памяти на экран монитора, в ячейки рабочего листа таблицы Excel, окно отладки программы или в файлы на внешних носителях. Рас- смотрим функции и операторы, реализующие ввод-вывод. 5.1. Функция MsgBox Выводит на экран диалоговое окно, содержащее сообщение, устанав- ливает режим ожидания нажатия кнопки пользователем, а затем возвраща- ет значение типа Integer, указывающее, какая кнопка была нажата. Синтаксис MsgBox(prompt[, buttons] [, title] [, helpfile, context]) Функция MsgBox содержит один обязательный аргумент (prompt) и четыре необязательных. prompt. Строковое выражение, отображаемое как сообщение в диало- говом окне. Максимальная длина строки prompt составляет приблизитель- но 1024 символов и зависит от ширины используемых символов. Строко- вое значение prompt может содержать нескольких физических строк. Для разделения строк допускается использование символа возврата каретки (Chr(13)), символа перевода строки (Chr(10)) или комбинации этих симво- лов (Chr(13) & Chr(10)). buttons. Необязательный параметр целого типа, указывающий число и тип отображаемых кнопок, тип используемого значка, основную кнопку и модальность окна сообщения. Значение по умолчанию этого аргумента равняется 0. title. Необязательный параметр являющийся заглавием диалогового ок- на. Если этот аргумент опущен, в строку заголовка помещается имя при- ложения. 55 helpfile . Необязательный параметр являющийся строковым выражени- ем, определяющим имя файла справки, содержащего справочные сведения о данном диалоговом окне. Если этот аргумент указан, необходимо ука- зать также аргумент context. context . Необязательный параметр, являющийся номером соответст- вующего раздела справочной системы. Если этот аргумент указан, необхо- димо указать также аргумент helpfile. Значения переменной buttons можно задавать в виде целого числа, име- нованной константы или арифметического выражения. Ниже перечислены допустимые значения аргумента buttons и имена всех поименованных кон- стант и в скобках ─ их значение: vbOKOnly (0) — отображается только кнопка "OK". vbOKCancel (1) — отображаются кнопки "OK" и "Отмена" (Cancel). vbAbortRetryIgnore(2) — отображаются кнопки "Прервать" (Abort), "По- вторить" (Retry) и "Пропустить" (Ignore). vbYesNoCancel (3) — отображаются кнопки "Да" (Yes), "Нет" (No) и "Отмена" (Cancel). vbYesNo (4) — отображаются кнопки "Да" (Yes) и "Нет" (No). vbRetryCancel (5) — отображаются кнопки "Повторить" (Retry) и "Отме- на" (Cancel). vbCritical (16) — используется значок "Критическое сообщение". vbQuestion (32) — используется значок "Предупреждающий запрос". vbExclamation (48) — используется значок "Предупреждение". vbInformation (64) — используется значок "Информационное сообщение". vbDefaultButton1 (0) — основной является первая кнопка. vbDefaultButton2 (256) — основной является вторая кнопка. vbDefaultButton3 (512) — основной является третья кнопка. vbDefaultButton4 (768) — основной является четвертая кнопка. vbApplicationModal (0) — модальное окно на уровне приложения: чтобы продолжить работу с текущим приложением, необходимо ответить на дан- ное сообщение. vbSystemModal (4096) — модальное окно на уровне системы: все прило- жения будут недоступны до тех пор, пока пользователь не ответит на дан- ное сообщение. Первая группа значений (0–5) указывает число и тип кнопок, отобра- жаемых в окне диалога, вторая группа (16, 32, 48, 64) задает тип исполь- зуемого значка, третья (0, 256, 512) определяет кнопку, которая является основной, а четвертая (0, 4096) — модальность окна сообщения. При опре- делении значения аргумента buttons следует суммировать не более одного значения из каждой группы. |