Программирование на visual basic
Скачать 1.19 Mb.
|
Пример . Ввести 10 действительных чисел и подсчитать количество чи- сел меньших среднеарифметического значения этих чисел. 38 Рассмотрим все 6 вариантов задания исходных данных массиву. Пусть для первых четырех вариантов начальными значениями элементов массива будут члены арифметической последовательности 1,5; 11,5; 21,5 ; …Для пятого варианта начальные условия зададим в виде ряда случайных чисел в диапазоне от 1,5 до 91,5. Для шестого варианта на этапе выполнения про- граммы пользователь вводит в массив произвольные числа. Для вычисления количества элементов больше среднеарифметического значения используется функция NumberEl, которая затем вызывается во всех пяти основных программах. Оператор Option Base, который надо вставлять в начале модуля, сообщает, что нумерация элементов массива по умолчанию начинается с первого, а не с нулевого элемента. Оператор Option Explicit запрещает использовать неописанные переменные величины. Option Explicit ' Не разрешать использование неописанные ‘ переменные Option Base 1 ' Нумерация элементов массивов (по умолчанию) с 1 ‘ Функция, возвращающая число элементов массива Mas больших ‘среднеарифметического значения Function NumberEl(Mas As Variant, N As Long) As Long Dim s As Double, numb As Long, i As Long For i = 1 To N ‘ Подсчитать сумму элементов массива Mas s = s + Mas(i) Next i s = s / N ‘ Это среднеарифметическое значение элементов MsgBox (s) ‘ Вывести его в стандартное окно ‘ Подсчитать количество элементов > среднеарифметического For i = 1 To N If Mas(i) > s Then numb = numb + 1 Next i NumberEl = numb End Function Sub ЗаданиеНачальныхЗначенийЭлементовМассива1() Const N = 10 Dim Mas(N) As Double ‘ Первый вариант задания начальных значений Mas(1) = 1.5: Mas(2) = 11.5: Mas(3) = 21.5: Mas(4) = 31.5: Mas(5) = 41.5 Mas(6) = 51.5: Mas(7) = 61.5: Mas(8) = 71.5: Mas(9) = 81.5 Mas(10) = 91.5 MsgBox (NumberEl(Mas, N)) End Sub Sub ЗаданиеНачальныхЗначенийЭлементовМассива2() Const N = 10 Dim Mas(N) As Double, i As Long ‘ Второй вариант задания начальных значений Sheets("Лист1").Select ' В момент выполнения программы, N ячеек 1-го столбца должны ' быть заполнены необходимыми значениями 39 For i = 1 To N Mas(i) = Cells(i, 1) Next i MsgBox (NumberEl(Mas, N)) End Sub Sub ЗаданиеНачальныхЗначенийЭлементовМассива3() Const N = 10 Dim Mas(N) As Double, i As Long ‘ Третий вариант задания начальных значений For i = 1 To N Mas(i) = 1.5 + (i - 1) * 10 Next i MsgBox (NumberEl(Mas, N)) End Sub Sub ЗаданиеНачальныхЗначенийЭлементовМассива4() Const N = 10 Dim Mas As Variant, i As Long, s As Double, numb As Long ‘ Четвертый вариант задания начальных значений Mas = Array(1.5, 11.5, 21.5, 31.5, 41.5, 51.5, 61.5, 71.5, 81.5, 91.5) MsgBox (NumberEl(Mas, N)) End Sub Sub ЗаданиеНачальныхЗначенийЭлементовМассива5() Const N = 10 Dim Mas(N) As Double, i As Long, s As Double, numb As Long ‘ Пятый вариант задания начальных значений For i = 1 To N Mas(i) = Rnd * 90 + 1.5 Next i MsgBox (NumberEl(Mas, N)) End Sub Sub ЗаданиеНачальныхЗначенийЭлементовМассива6() Const N = 10 Dim Mas(N) As Double, i As Long ‘ Шестой вариант задания начальных значений For i = 1 To N Mas(i) = CDbl(InputBox("Введите " & i & " -тый элемент массива")) Next i MsgBox (NumberEl(Mas, N)) End Sub 40 3.2. Динамические массивы Довольно часто при написании программы программист не знает коли- чества элементов в массиве, который будет использоваться в программе на этапе выполнения. Для выхода из этой ситуации возможны несколько пу- тей. Первый путь - описать массив с максимально возможной размерностью и предусмотреть останов программы и сообщение о причинах останова в случае превышения размерности массива. Для сложных программ, тре- бующих большого объема памяти, этот путь неприемлем. При этом на эта- пе компиляции для каждого такого массива (такие массивы называются статические) отводится оперативная память, соответствующая размеру массива. Второй более оптимальный путь - использование динамических масси- вов. Массивы, для которых память отводится на этапе выполнения про- граммы, называются динамическими . Для динамических массивов размер каждого измерения может устанавливаться на этапе исполнения, а не во время компиляции программы. При необходимости размер динамических массивов можно изменять. Для любого динамического массива необходимо в начале программы описать его оператором описания типов переменных с пустым значением размерности: Dim Name() as тип . Затем перед использованием при помо- щи оператора ReDim задать фактическое количество значений по всем размерностям. Пример . Ввести N случайных целых трехзначных чисел и подсчитать среднее значение их, а также количество чисел больших среднего. Sub ПримерНаДинамическиеМассивы() Dim Dm() As Long, s As Double, N As Long, Numb As Long, i As Long N = Val(InputBox("Введите количество чисел")) ' Создание динамического массива из N элементов ReDim Dm(1 To N) s = 0 Randomize Timer ' Построить ряд псевдослучайных чисел For i = 1 To N Dm(i) = Rnd * 899 + 100 ' Получить целые случайное ‘трехзначное число s = s + Dm(i) Next i s = s / N: Numb = 0 For i = 1 To N If Dm(i) > s Then Numb = Numb + 1 Next i MsgBox ("Количество чисел больших среднего значения = " _ + Str(Numb) + " Среднее значение =" + Str(s)) End Sub 41 В процессе работы программы можно менять размеры динамического массива оператором ReDim. При этом предыдущие данные теряются. Час- то возникает необходимость либо увеличить, либо уменьшить размерность массива, не теряя значения. Для этого необходимо использовать оператор ReDim с ключевым словом Preserve. В следующем примере увеличивается размерность существующего массива DinMas, на 10 элементов не теряя предыдущих значений. ReDim Preserve Dinmas(Ubound(DinMas)+10) Этот оператор можно использовать в любом месте программы и любое количество раз. Пример. В первом столбце рабочего листа, начиная с первой строки, находятся произвольное число действительных чисел. Прочитать эти числа в массив. Найти сколько элементов этого массива принимают значения больше среднеарифметического значения элементов этого массива. Sub ПримерНаРасширениеДинамическогоМассива() Dim a() As Long, N As Long, S As Long, I as Long, NS as Long N = 0: Sheets("Лист1").Select ReDim a(10) ' Первые 10 элементов массива While Cells(N + 1, 1) <> Empty N = N + 1 a(N) = Cells(N, 1) S = S + a(N) ' Увеличить размерность массива на 10 элементов после каждых ’10 элементов сохраняя значения предыдущих элементов If (N Mod 10) = 0 Then ReDim Preserve a(N + 10) Wend ‘ N ─ это окончательная размерность массива A S=S/N ‘ Среднеарифметическое значение For I=1 to N If a(i)>S Then NS=NS+1 Next i MsgBox("Количество элементов > среднеарифметического=" & NS) End Sub 42 3.3. Пользовательские типы данных В современных языках программирования появились сложные, вводи- мые пользователем типы данных, называемые структурами. Допустим, све- дения о сотруднике учреждения являются типом данных, в котором опреде- лены необходимые характеристики: фамилия, имя, отчество, домашний ад- рес, телефон, возраст, время принятия на работу, день рождения и т.д. Вме- сто того чтобы для каждого из этих сведений вводить отдельную перемен- ную, можно ввести одну сложную структурированную переменную. В VB такие типы данных называют пользовательскими. Пользовательский тип создается оператором Type, который должен быть помещен вначале модуля. При этом данное описание действует на все программы, находящихся во всех программах текущего модуля. Синтаксис оператора Type является следующим: [Private | Public ] имяТипаДанных имяПоля_1 [(размер)] As тип имяПоля_2 [(размер)] As тип … имяПоля_n [(размер)] As тип End Type Параметр имяТипаДанных - имя нового типа данных, введенного поль- зователем, которое в текущем модуле можно использовать так же, как и обычные типы данных. Элементы введенного типа данных - имяПоля_1, имяПоля_2, …, имяПоля_n называются полями и являются либо простыми переменными, либо массивами, либо переменными других пользователь- ских типов. После описания пользовательского типа данных необходимо объявить одну или несколько переменных этого типа. Для описания переменных ис- пользуется оператор Dim: Dim имяПеременной[(размер)] As имяТипаДанных Для обращения к полям описанной переменной пользовательского типа требуется указать имя переменной, точку, а затем имя поля. Если перемен- ная является массивом, то после имени переменной необходимо в круглых скобках поставить номер элемента массива, к которому обращаемся. Пример 1 . С клавиатуры вводятся координаты двух точек. Написать программу для вычисления расстояния между ними. Type Point2 'Введение пользовательского типа x As Double y As Double End Type Sub ПримерПользовательскогоТипа() Dim A As Point2, B As Point2, z As Double A.x = CDbl(InputBox("Введите абсциссу точки A")) A.y = CDbl(InputBox("Введите ординату точки A")) B.x = CDbl(InputBox("Введите абсциссу точки B")) 43 B.y = CDbl(InputBox("Введите ординату точки B")) z = Sqr((B.x - A.x) ^ 2 + (B.y - A.y) ^ 2) ‘ расстояние MsgBox ("Расстояние между точками A и B равно" & z) End Sub Пример 2. Ввести внутри программы переменную, описывающую све- дения о человеке: фамилию, имя, отчество, телефон и возраст. Сведения о трех человеках заполнить внутри программы операторами присваивания. Подсчитать и вывести на монитор средний возраст и среднюю длину их фа- милий. Type FullName 'Введение пользовательского типа firstName As String lastName As String pName As String tell As String ye As Double End Type Sub ТестНаСтруктурныеДанные() Const N = 3 Dim MName(N) As FullName 'Описание массива структурного типа ' Заполнение полей структуры данными MName(1).firstName = "Иванов" MName(1).lastName = "Петр" MName(1).pName = "Андреевич" MName(1).tell = "277-xx-27" MName(1).ye = 45 MName(2).firstName = "Петрова" MName(2).lastName = "Мария" MName(2).pName = "Николаевна" MName(2).tell = "277-xx-77" MName(2).ye = 17 MName(3).firstName = "Александров" MName(3).lastName = "Петр" MName(3).pName = "Владимирович" MName(3).tell = "277-xx-77" MName(3).ye = 60 Dim s As Double, d As String, k As Integer, I As Integer For I = 1 To N s = s + MName(I).ye ‘ Сумма возрастов Next I MsgBox ("Средний возраст =" + Str(s / N)) ' Все фамилии в одну переменную. Для упрощения алгоритма ‘обработки d = MName(1).firstName + MName(2).firstName + MName(3).firstName k = 0 For I = 1 To Len(d) ' Количество букв во всех фамилиях If Mid(d, I, 1) <> " " Then k = k + 1 Next I 44 MsgBox ("Средняя длина фамилии = " + Str(k / N)) End Sub 4. Операторы организации функций и подпрограмм 4.1. Подпрограммы-функции Подпрограмма-функция является отдельной программной единицей и может быть откомпилирована отдельно от основной программы и записана в библиотеку подпрограмм. Подпрограмма-функция может вычислить только одно число, являющееся значением функции в зависимости от зна- чений аргументов. Т.е. это отображение n-мерного пространства множест- ва значений аргументов на одномерное пространство множества значение функции. 4.1.1. Оператор FUNCTION Подпрограмма-функция определяется ключевым словом FUNCTION. Общая форма подпрограммы-функции: Function имя( [a1] [, a2] [,…] [,an] ) [As тип] [неисполняемые операторы (операторы описания)] [исполняемые операторы, среди которых должен быть оператор присваивания: имя= значение или выражение] [Exit Function] [исполняемые операторы, среди которых должен быть оператор присваивания: имя= значение или выражение] End Function где имя - имя функции; ai - формальные параметры (аргументы). Фор- мальный параметр ai имеет следующий синтаксис : [Optional] [ByVal | ByRef] [ParamArray] имяПеременной [() ] [As тип] [=значениеПоУмолчанию] Напомним, что выражение в квадратных скобках необязательно; верти- кальная линия | означает, что выбирается один из предложенных вариантов. Ключевые слова, стоящие перед именами переменных, называются атри- бутами переменных. Приведем функции атрибутов аргументов. Optional – указывает, что при вызове функции данный фактический па- раметр необязателен. ByVal – указывает, что параметр передается по значению. Т.е. после вы- зова функции создается копия параметра, и все операторы тела функции ра- ботают с этой копией, а перед возращением значения функции значения па- раметра восстанавливается. 45 ByRef - указывает, что параметр передается по ссылке. Т.е. все измене- ния параметра внутри функции остаются после выхода из нее. В Visual Basic по умолчанию параметр передается по ссылке. ParamArray – указывает, что при вызове функции вместо этого пара- метра можно включать произвольное число формальных входных парамет- ров. Формальный параметр с атрибутом ParamArray должен быть последним в списке. Формальные параметры могут быть именем простой переменной, име- нем структуры, массивом. Замечание. Список параметров может отсутствовать, но скобки обязаны быть. Вызов подпрограммы-функции осуществляется так же, как и встроенной функции. Пример . Написать программу для вычисления по введенным длинам сторон треугольника значения его углов в радианах и градусах. Sub УглыТреугольника() ‘ Основная программа Dim a As Double, b As Double, c As Double, x As Double a = CDbl(InputBox("Введите длину первой стороны треугольника")) b = CDbl(InputBox("Введите длину второй стороны треугольника")) c = CDbl(InputBox("Введите длину третьей стороны треугольника")) If (a + b <= c Or b + c <= a Or a + c = b) Then MsgBox ("Введенные числа не образуют треугольник") Exit Sub ‘ Выйти из программы End If Debug.Print "Углы в радианах" Debug.Print "alfa="; ugol(b, c, a); " beta="; ugol(a, c, b); _ ; " hamma=", ugol(a, b, c) Debug.Print "Углы в градусах" Debug.Print " alfa="; Radgrad(ugol(b, c, a)); " beta="; _ Radgrad(ugol(a, c, b)); " hamma="; Radgrad(ugol(a, b, c)) End Sub ‘ Функция, возвращающая угол между двумя сторонами a и b Function ugol(a As Double, b As Double, c as Double) As Double ugol = Arccos((a ^ 2 + b ^ 2 - c ^ 2) / (2 * a * b)) End Function ‘ Перевод угла x из радианов в градусы Function Radgrad(x As Double) As Double Dim pi As Double pi = Atn(1) * 4 ' Вычисление числа π Radgrad = x / pi * 180 End Function ‘ Вычисление функции arccos(x) через встроенную функцию arctg(x) Function Arccos(x As Double) As Double Arccos = Atn(-x / Sqr(-x * x + 1)) + 2 * Atn(1) End Function 46 В данном примере используются три функции: ugol - для вычисления уг- ла между сторонами треугольника по теореме косинусов; Radgrad - для пе- ревода угла, заданного в радианах, в угол, заданный в градусах, и функция Arccos – для арккосинуса угла через арктангенс. 4.1.2. Необязательные параметры Рассмотрим пример с использованием значений по умолчанию. Sub testOptinal() ‘ Основная программа для теста Debug.Print funOpt (1); : Debug.Print funOpt (1, 5); Debug.Print funOpt (1, 5, 6); : Debug.Print funOpt (1, , 6) End Sub Function funOpt(a As Long, Optional b As Long = 7, _ Optional c As Long = 3) As Long fun3 = a * 100 + b * 10 + c End Function В представленном примере рассмотрена функция funOpt, имеющая три аргумента ( a , b и c) и возвращающая сумму 100 a +10 b + c . Если a , b и c однозначные числа, то результатом функции будет трехзначное число, где a – число сотен, b – число десятков, а c – число единиц. Второй и третий ар- гументы необязательные. Поэтому при вызове функции их можно опускать. В этом случае они принимают значения по умолчанию b =7, c=3 . В основ- ной программе четыре раза вызывается функция funOpt с различным числом фактических параметров. В случае если опускается средний параметр, то его необходимо выделить запятыми. Результаты этой программы печатаются в окне отладки и равны: 173 153 156 176. 4.1.3. Передача параметров по ссылке и значению По умолчанию формальные параметры, используемые в подпрограм- мах и функциях языка Visual Basic, передаются по ссылке или адресу. Это означает, что для переменных не создается копия внутри подпрограммы или функции, а все вычисления происходят в ячейках, отведенных компи- ляторам для формального аргумента. После выхода из подпрограммы или функции значения фактических параметров соответствуют значению в подпрограмме после ее завершения. Этот метод имеет достоинства и не- достатки. К достоинству следует отнести экономию памяти и время. К не- достаткам – математическая некорректность с точки зрения определения функции. В математике функция не меняет значения аргумента. Во многих языках программирования (С++, Паскаль) параметры пере- даются по значению. Это означает, что после входа в подпрограмму или функцию создаются копии формальных параметров. Затем выполняются операторы тела подпрограммы со значениями копией параметров, а после возврата в вызвавший ее программный модуль происходит восстановление значений фактических параметров. |