Вложенные литералы массива
Можно создать многомерный массив с помощью вложенных литералов массива. Вложенные литералы массива должны иметь измерение и число измерений или ряда, согласованным с итоговым массивом. В следующем примере кода создается двухмерный массив целых чисел с помощью литерала массива.
VB
Dim grid = {{1, 2}, {3, 4}}
В предыдущем примере возникла ошибка минимум, если число элементов во вложенных литералах массива не соответствует. Ошибка возникла бы также случае явного объявления переменной массива, за исключением двухмерного.
|
|
|
Избежать ошибки при указании вложенных литералов массива с различными измерениями можно, заключив внутренние литералы массива в круглые скобки. Скобки принудительный выражение литерала массива должен вычисляться и результирующие значения используются с внешним литералом массива, как показано в следующем коде. |
VB
Dim values = {({1, 2}), ({3, 4, 5})}
При создании многомерного массива с помощью вложенных литералов массива можно использовать вывод типа. При использовании вывода типа выводимый тип является главным типом для всех значений всех литералов массива какого-либо уровня вложенности. В следующем примере кода создается двухмерный массив типа Double из значений типа Integer и Double.
VB
Dim a = {{1, 2.0}, {3, 4}, {5, 6}, {7, 8}}
Дополнительные примеры см. в разделе Практическое руководство. Инициализация переменных массива в Visual Basic.
Итерация через массив
Можно получить доступ ко всем элементам массива из нижнего индекса к наибольшему индексу. Это вызываются итерация через массив.
В следующем примере выполняется итерация через одномерный массив с помощью Оператор For... Next (Visual Basic). Метод GetUpperBound возвращает самое большое значение может иметь индекс. Наименьшее значение индекса всегда равно 0.
Следующий
пример выполняет итерацию по таблице,
используя многомерную
выписки For...Next. Метод GetUpperBound содержит
параметр, который определяет
измерение. GetUpperBound(0) возвращает
максимальное значение индекса первого
измерения, и возвращать GetUpperBound(1) высокое
значение индекса для второго измерения.
В следующем примере выполняется итерация через одномерный массив с помощью Оператор For Each... Next (Visual Basic).
Следующий пример выполняет итерацию по таблице, используя многомерную выписки For Each...Next. С многомерными таблицами однако, приведенный выше пример использования вложенных выписку For...Next вместо выписки For Each...Next обеспечивает большую элемента управления над элементами массива.
Массивы массивов
Массив, который содержит другие массивы как элементы в виде массива массивов или массива массивов. Массив массивов и каждый элемент массива массивов могут иметь одно или несколько измерений. Иногда структура данных в приложении является двухмерной, но не прямоугольной.
Следующий пример содержит массив месяцев, каждый элемент которого массив дней. Поскольку разные месяцы имеют различные число дней, элементы не формируют прямоугольный двумерный массив. Поэтому вместо многомерного массива используется массив массивов.
VB
' Declare the jagged array.
' The New clause sets the array variable to a 12-element
' array. Each element is an array of Double elements.
Dim sales()() As Double = New Double(11)() {}
' Set each element of the sales array to a Double
' array of the appropriate size.
For month As Integer = 0 To 11
Dim days As Integer =
DateTime.DaysInMonth(Year(Now), month + 1)
sales(month) = New Double(days - 1) {}
Next month
' Store values in each element.
For month As Integer = 0 To 11
Dim upper = sales(month).GetUpperBound(0)
For day = 0 To upper
sales(month)(day) = (month * 100) + day
Next
Next
Массивы нулевой длины
Массив, который не содержит элементов также вызвать массив нулевой длины. Переменная, которая содержит массив нулевой длины не имеет значенияNothing. Создание массив, не содержащий элементов, объявите одно из измерений массива на -1, как показано в следующем примере.
VB
Dim twoDimensionalStrings(-1, 3) As String
Возможно, потребуется создать массив нулевой длины в следующих случаях.
-
Без рисковать исключение NullReferenceException код должен получить доступ к членам класса Array, как Length или Rank или вызовите функцию Visual Basic как UBound.
-
Требуется сделать соответствующий код проще, избежав необходимости проверки на значение Nothing как особый случай.
-
Код взаимодействует с программным интерфейсом (API) или необходимо передавать массив нулевой длины в одну или несколько процедур или возвращает массив нулевой длины из одной или нескольких процедур.
Размер массива
Размер массива является произведением длин всех его измерений. Он представляет собой общее число элементов, в данный момент содержащихся в массиве.
В следующем примере показано объявление трехмерного массива:
Dim prices(3, 4, 5) As Long
Общий
размер массива в переменной prices составляет (3
+ 1) x (4 + 1) x (5 + 1) = 120.
Размер массива можно определить с помощью свойства Length.Длину каждого измерения многомерного массива можно получить с помощью методаGetLength.
Можно изменять размер переменной массива, присваивая ей новый объект массива, или с помощью оператора ReDim.
Существует ряд особенностей, о которых следует помнить при работе с размером массива.
|
Длина измерения |
Индекс каждого измерения начинается с 0, что означает, что его диапазон от 0 до верхней границы.Таким образом, длина данного измерения на 1 больше объявленной верхней границы этого измерения. |
|
Ограничения длины |
Длина каждого измерения массива ограничена максимальным значением типа Integer, которое равно (2 ^ 31) - 1.Тем не менее, общий размер массива также ограничен доступной памятью в системе.При попытке инициализировать массив, размер которого превышает объем доступной оперативной памяти, общеязыковая среда выполнения создает исключение OutOfMemoryException. |
|
Размер и размер элемента |
Размер массива не зависит от типа его элементов.Размер всегда представляет общее число элементов, а не число байтов, занимаемое массивом при хранении. |
|
Затраты памяти |
Небезопасно делать любые предположения относительно способа хранения массива в памяти.Хранение зависит от размерности данных платформы, так один и тот же массив может потреблять больше памяти на 64-разрядных системах, чем на 32-разрядных.В зависимости от конфигурации системы при инициализации массива общеязыковая среда выполнения (CLR) может указывать такие способы хранения, как упаковка элементов максимально близко друг к другу или выравнивание всех элементов по естественным аппаратным границам памяти.Кроме того массив нуждается в хранении служебной информации, и размер этой информации возрастает при каждом добавлении измерения. |
Типы массива и другие типы
Каждый массив имеет тип данных, но этот тип отличается от типа данных его элементов. Не существует единого типа данных, подходящего для всех массивов.Вместо этого тип данных массива определяется числом измерений массива, или рангом, и типом данных элементов массива. Две переменные массивов имеют один тип, только если массивы одного ранга и содержат данные одного и того же типа. Длины измерений массива не влияют на тип данных массива.
Каждый массив наследуется от класса System.Array, и можно объявить переменную типа Array, но не нельзя создать массив типа Array. Кроме того, Оператор ReDim (Visual Basic) не может работать с переменной, объявленной как тип Array. По этой причине и для строгой типизации рекомендуется объявить каждый массив как конкретный тип, например Integer, как в предыдущем примере.
Можно выяснить тип данных массива или его элементов несколькими способами.
-
Можно вызвать метод Object.GetType для переменной для получения объекта Type типа переменной времени выполнения. Объект Type содержит подробные сведения в своих свойствах и методах.
-
Можно передать переменную функции TypeName, чтобы получить объект String, содержащий имя типа времени выполнения.
-
Можно передать переменную функции VarType для получения значения VariantType, представляющего классификацию типа переменной.
В следующем примере вызывается функция TypeName для определения типа массива и типа элементов в массиве. Массив имеет тип Integer(,), а элементы массива относятся к типу Integer.
VB
Dim thisTwoDimArray(,) As Integer = New Integer(9, 9) {}
MsgBox("Type of thisTwoDimArray is " & TypeName(thisTwoDimArray))
MsgBox("Type of thisTwoDimArray(0, 0) is " & TypeName(thisTwoDimArray(0, 0)))
Коллекции как альтернатива массивам
Массивы наиболее полезны для создания и работы с фиксированным числом сильной типизированных объектов. Коллекции предоставляют более гибкий способ работы с группами объектов. В отличие от массивов, коллекция, с которой вы работаете, может расти или уменьшаться динамически при необходимости.
Если требуется изменить размер массива, необходимо использовать Оператор ReDim (Visual Basic). После этого Visual Basic создает новый массив и освобождает предыдущий массив. Это занимает время выполнения. Таким образом, если число элементов при работе изменяется часто или нельзя предсказать максимальное число необходимых элементов, можно получить большую производительность при использовании коллекции.
Некоторые коллекции допускают назначение ключа любому объекту, который добавляется в коллекцию, чтобы в дальнейшем можно можно быстро извлечь связанный с ключом объект из коллекции.
Если ваша коллекция содержит элементы только одного типа данных, можно использовать один из классов в пространстве имен System.Collections.Generic.Универсальная коллекция обеспечивает безопасность типов, так что другие типы данных не могут быть в нее добавлены. При извлечении элемента из универсальной коллекции нет необходимости определять или преобразовывать его тип данных.
Дополнительные сведения о коллекциях см. в разделе Коллекции (C# и Visual Basic).
Пример
В
следующем примере используется
универсальный класс .NET
Framework System.Collections.Generic.List<T> для
создания коллекции-списка объектовCustomer.
VB
' Define the class for a customer.
Public Class Customer
Public Property Name As String
' Insert code for other members of customer structure.
End Class
' Create a module-level collection that can hold 200 elements.
Public CustomerList As New List(Of Customer)(200)
' Add a specified customer to the collection.
Private Sub AddNewCustomer(ByVal newCust As Customer)
' Insert code to perform validity check on newCust.
CustomerList.Add(newCust)
End Sub
' Display the list of customers in the Debug window.
Private Sub PrintCustomers()
For Each cust As Customer In CustomerList
Debug.WriteLine(cust)
Next cust
End Sub
Объявление
коллекции CustomerFile задает,
что она может содержать только элементы
типа Customer. Она
также имеет исходную емкость 200
элементов.Процедура AddNewCustomer проверяет
новый элемент на допустимость и затем
добавляет его к
коллекции. Процедура PrintCustomers использует
цикл For
Each для
прохода по коллекции и отображения ее
элементов.
Билет № 13
Функции пользователя
Приёмы построения алгоритмов
Для создания работающей программы разработчик должен пройти три
основных этапа:
проектирование – построение алгоритма решения поставленной задачи;
кодирование – перевод алгоритма на язык программирования;
отладка – проверка работы программы на заранее разработанном наборе
тестовых примеров (под тестовым примером подразумевают набор исходных
данных и результат, который должен получиться в процессе выполнения
разработанной программы).
Существуют разные способы создания алгоритмов. Известна доказанная
теорема о том, что любой алгоритм можно построить при помощи трех
алгоритмических структур: следования, развилки и цикла. Объединяя
различным образом эти структуры можно разработать алгоритм, а по нему
составить программу для решения любой логической задачи на компьютере. В
этом случае говорят о структурном программировании.
Одним из приемов структурного программирования является разбиение
(декомпозиция) решаемой задачи на логически завершенные подзадачи. Для
каждой подзадачи строится так называемый вспомогательный алгоритм. В
связи с этим можно представить два способа построения алгоритмов:
метод последовательной детализации;
сборочный метод.
Сборочный метод предполагает, что при решении задачи у программиста
должна быть библиотека модулей (модуль содержит подпрограмму, которая
позволяет решать общие, но небольшие задачи). При решении достаточно
сложной задачи алгоритм можно составить и таких модулей. Недостаток
метода заключается в том, что для решения конкретной задачи необходимо
наличие алгоритмов решённых задач.
Метод последовательной детализации можно разбить на три этапа:
1. Строится основной алгоритм решения общей задачи, т.е. исходная
задача разбивается на логически завершённые подзадачи.
2. Для каждой подзадачи определяются входные данные, от которых
функционально будет зависеть решение конкретной подзадачи; выходной
параметр, который должен быть получен на выходе решения конкретной
подзадачи; описывается вспомогательный алгоритм решения этой
подзадачи.
3. Каждому вспомогательному алгоритму присваивается уникальное имя,
и решение исходной задачи будет строиться как логическая цепочка
правильно построенных вспомогательных алгоритмов.
Метод последовательной детализации используется для решения задач
большой сложности. При этом к построению алгоритмов можно привлечь
целый коллектив программистов.2
Понятие функции
Определение функции
В любом языке программирования алгоритм решения подзадачи можно
описать в виде отдельной подпрограммы. В языке VBA каждая подпрограмма
называется функцией – это конструкция языка программирования, связанная с
решением конкретной части поставленной задачи. Функция – это
самостоятельная единица программы. В языке VBA функции разделяются на
встроенные и пользовательские (разработаны самим программистом).
Определение функции состоит из описания заголовка и тела функции.
После заголовка функции точка с запятой не ставится. Общий вид функции:
<имя_функции>(<список_формальных_параметров>) As <тип_возвр_результата>
<тело_функции>
end
<тип_возвращаемого_результата> – тип результата работы функции, может быть
целочисленным, вещественным, символьным или указателем на любой
допустимый тип. Результат работы функции возвращается и записывается сразу
после имени функции в ее теле в виде переменной или выражения, допустимого
в языке VBA. В описании метода последовательной детализации результат
работы функции называется выходным параметром.
<имя_функции> – идентификатор (применительно к методу последовательной
детализации – это уникальное имя некоторого вспомогательного алгоритма),
при помощи которого функцию можно вызвать для выполнения. Надо
стараться задавать такие имена пользовательским функциям, которые не
совпадали бы с ключевыми словами языка VBA.
<список_формальных_параметров> определяет типы и имена формальных
параметров. В <список_формальных_параметров> параметры разделяются запятыми. С
точки зрения построения алгоритмов методом последовательной детализации,
формальные параметры – это входные данные, от которых функционально
зависит решение конкретной подзадачи. Таким образом, формальные
параметры – это переменные, которые позволяют произвести обмен между
вызываемой (решает подзадачу) и вызывающей функциями.
<список_формальных_параметров> может отсутствовать. В этом случае в заголовке
функции после ее имени пишутся «пустые» скобки.
<тело функции> – алгоритм решения подзадачи, включая описание локальных,
т.е. нужных только внутри тела функции, переменных, записанный на языке
программирования. Операторы тела функции выполняются до первого
оператора return. Если в теле функции нет такого оператора (т.е. функция не
возвращает никакого результата), то выполняются все операторы до
закрывающейся операторной скобки.
Function Sum(x as Integer, y as Integer) As Single
x=x^2
Sum = x+y
Заголовок функции3
End Function
Z = Sum(1, 5)
D = Sum(Z, 56)
Область видимости переменных
Каждая переменная, используемая в теле функции, должна быть
объявлена в теле функции, в списке формальных параметров или вне функции.
Переменные, используемые в функциях:
глобальные (внешние): объявленные в программе либо как внешние;
локальные (внутренние): объявленные, доступные и используемые только
в теле функции;
формальные – переменные, объявленные в списке формальных
параметров и доступные только в теле функции.
Объявление переменной вводит её имя в области видимости. Имя
переменной может использоваться только в определенной части программы.
Для локальной переменной, описанной в теле функции, область видимости
начинается с точки объявления до конца тела функции.
Скрытие имен неизбежно при написании больших программ. В этом
случае легко не заметить, что имя скрыто и некоторые ошибки, возникающие
из-за этого, очень трудно обнаружить. Следовательно, от скрытия имен нужно
уходить при написании программ. Использование для глобальных переменных
часто употребляемых имен вроде i или x как раз и приводит к ошибкам, вроде
переобъявления переменной.
При объявлении переменная создается, когда встречается её описание, и
уничтожается, когда её имя выходит из области видимости. Переменные с
глобальными именами создаются и инициализируются только один раз и
“живут” до завершения программы.
Параметры функции
Параметры функции определяются списком формальных параметров.
Область видимости формальных параметров – тело функции. Имена
формальных параметров используются в операторах тела функции.
Формальными параметрами могут быть только идентификаторы.
Кроме формальных параметров есть фактические. При вызове функции
фактические параметры заменяют формальные, т.е. все формальные параметры
в теле функции будут заменены на соответствующие фактические. Этот процесс
называется передачей фактических параметров в функцию. Это делается для
обмена фактическими данными между вызывающей и вызываемой функцией и
получения фактического результата после завершения работы вызываемой
функции для передачи его в вызывающую функцию.
Между списками формальных и фактических параметров при вызове
функции должно быть соответствие:
1) количества формальных и фактических параметров;4
2) последовательности формальных и соответствующих им фактических
параметров (первому формальному параметру соответствует первый
фактический, второму – второй и т. д.);
3) типов формальных и соответствующих им фактических параметров.
Сопоставление формальных и фактических параметров производится при
каждом вызове функции: первому формальному параметру будет сопоставлен
первый фактический, второму – второй и т.д. При передаче параметров
нарушение соответствия по количеству или типам параметров может привести
к серьезным ошибкам, например к нарушению границ переменных, в том числе
массивов. Некорректная по смыслу передача фактических параметров может
привести к неверному результату, хотя алгоритм, записанный в функции, будет
верен.
Список формальных параметров может содержать нуль и более
объявлений переменных, разделенных запятыми. При объявлении
формальных параметров для каждого элемента списка формальных
параметров объявляется имя и тип только этого параметра. Объявление
каждого формального параметра имеет форму
<идентификатор_параметра> As <имя_типа_параметра>
Здесь <имя_типа_параметра> – имя допустимого типа значений, стандартного или
определенного пользователем; <идентификатор_параметра> – имя формального
параметра.
Отсутствие имени типа параметра в списке формальных параметров
является синтаксической ошибкой.
Организация вызова функции
Форма вызова функции:
<имя_функции>(<список_фактических_параметров>);
Если при описании функции список формальных параметров отсутствовал,
то при вызове функции <список_фактических_параметров> так же должен
отсутствовать. При вызове функции ей передается управление. Опишем
организацию вызова функции.
Каждая строка в программе определяется своим адресом. Строка
вызывающей функции, в которой вызывается другая функция, также имеет
свой адрес, называемый точкой вызова функции. При вызове функции,в ОП
организуется структура, которая называется стеком.
При вызове функции стек заполняется следующим образом:
1. В стек помещается адрес вызова функции.
2. В стек копируются значения переданных в функцию фактических
параметров.
3. Выполняются операторы тела функции.
4. После того как функция завершила свою работу из стека в ячейки ОП,
выделенные под переменные, являющиеся фактическими параметрами, 5
копируются (возвращаются) скопированные туда их же значения при вызове
функции.
5. Из стека забирается адрес точки вызова функции, и по этому адресу
происходит возврат в вызывающую функцию.
Затем выполняются операторы вызывающей функции, следующие за
строкой вызова функции.
