русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

Использование массивов


Дата добавления: 2015-08-31; просмотров: 2000; Нарушение авторских прав


После объявления массива использовать его в VB-коде довольно просто. Как уже объяснялось в начале этой главы, для доступа к элементу массива необходимо указать имя массива, за которым следует значение индекса, заключенное в круглые скобки.

Обращение к элементу массива имеет следующий синтаксис:

Синтаксис

arrayName(validIndex1, [validIndex2]…)

 

Здесь arrayName — имя массива; validIndex1 — допустимое значение индекса для первого измерения массива; validIndex2 — допустимое значение индекса для второго измерения массива, если таковое имеется. Необходимо предоставлять значение индекса для каждого измерения массива при каждом обращении к какому-либо элементу в массиве.

Например, для двумерного массива необходимо всегда определять два индекса. Допустимым индексом является любая VB-переменная (или VB-выражение), имеющая результатом целое число в диапазоне объявленных измерений массива. Например, допустимым значением индекса для одномерного массива, объявленного с индексами 1–10, может быть любое VB-выражение, имеющее результатом целое число в диапазоне от 1 до 10. Использование меньшего или большего индекса, чем диапазон для определенного измерения в массиве, приводит к тому, что отображается runtime-ошибка.

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

 

Dim Factorial(0 To 3) As Double 'объявление массива из 4-х элементов

Factorial(0) = 1 'инициализировать 1-й элемент

Factorial(3) = 1 'инициализировать 4-й элемент

 

Использование циклов для обработки массивов

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



В следующем фрагменте кода приведены операторы инициализации двумерного массива при помощи вложенного цикла:

Dim I As Integer, J As Integer

Static doMatrixA(1 To 10, 1 To 10) As Double

For I = 1 To 10

For J = 1 To 10

doMatrixA(I, J) = I * 10 + J

Next J

Next I

Чтобы получить тот же результат без цикла, нужно записать оператор присваивания значения элементу массива сто раз.

Вы можете создать Variant-массив и заполнить его другими массивами с различными типами данных. В коде приведенного далее листинга создается массив типа Variant (arr) и два массива типа Integer (intArrA и strArrB). После инициализации массивов intArrA и strArrB первому элементу массива arr присваивается массив intArrA, а второму — strArrB. Остальная часть предназначена для вывода информации с использованием функции MsgBox.

Листинг 10.1. Заполнение массива другими массивами

1 Private Sub Com()

3 Dim intX As Integer, strA As String

5 'массив для хранения массивов

6 Dim arr(2) As Variant '

8 'массивы, которые будут помещены в элементы

9 'массива arr(2)

10 Dim intArrA(5) As Integer, strArrB(5) As String

12 'инициализация массива intArrA

13 For intX = 0 To 4

14 intArrA(intX) = intX

15 Next intX

17 'инициализация массива intArrB

18 strArrB(0) = "h"

19 strArrB(1) = "e"

20 strArrB(2) = "l"

21 strArrB(3) = "l"

22 strArrB(4) = "o"

24 'заполнить массив arr другими массивами

25 arr(1) = intArrA()

26 arr(2) = strArrB()

28 'вывод массива arr на экран

29 For intX = 0 To 4

30 MsgBox arr(1)(intX)

31 Next intX

32 strA = arr(2)(0)

33 For intX = 1 To 4

34 strA = strA + arr(2)(intX)

35 Next intX

36 MsgBox strA

37 End Sub

Использование ReDim с динамическими массивами

Создать динамический массив просто:

1. Объявите массив с помощью ключевого слова (иногда говорят «оператором») Public (если нужен глобальный массив) или Dim в модуле (если нужен массив модульного уровня) или Static или Dim в процедуре (для локального массива). Размерность массива не указывайте:

Dim DynArray()

2. Укажите размерность массива с помощью оператора ReDim:

ReDim DynArray(X + 1)

Оператор ReDim может появляться только в процедуре, поскольку в отличие от Dim и Static является исполняемым оператором во время работы приложения.

При каждом выполнении оператора ReDim значения всех элементов массива, сохраненные ранее, теряются. Visual Basic переустанавливает их в Empty (для Variant-массивов), в нулевые значения (для числовых массивов), в строки нулевой длины (для строковых массивов) или в Nothing (для массивов-объектов).

Конечно, это, скорее, неудобно, чем удобно. Если нам нужно добавить к массиву новый элемент в конец массива, т.е., увеличить размер массива, то нет смысла терять при этом, может быть, с трудом полученные ранее элементы. Здесь снова уместно заметить, что, «к счастью», с помощью ключевого слова Preserve в операторе ReDim можно указать, чтобы система сохранила значения массива, размеры которого изменяются. В следующем примере размер массива увеличивается на единицу от текущего размера с сохранением значений, ранее запомненных в массиве. Текущий размер массива определяется с помощью функции UBound(подробнее об этой функции будет рассказано далее в этой главе):

ReDim Preserve DynArray(UBound(DynArray) + 1)

Применяя Preserve, следует учитывать одно ограничение: вы можете с использованием слова Preserve изменять только последнюю размерность многомерного массива. Если вы измените какую-либо другую размерность, произойдет ошибка времени исполнения.

Передача массива в качестве аргумента при вызове процедуры или функции-процедуры

Visual Basic дает возможность передавать массивы в качестве аргументов процедур и функций. Например, можно написать функцию, получающую числовой массив в качестве аргумента и возвращающую среднее значение всех чисел в массиве как результат функции. Еще один пример: можно написать процедуру, получающую массив в качестве аргумента, передаваемого по ссылке, и сортирующую этот массив. И в одном, и в другом примерах можно написать процедуру или функцию для работы с массивом любого размера — пять элементов, 10 элементов, 100 элементов и так далее.

Общий синтаксис для аргументов-массивов для процедур или функций-процедур такой же, как для любых аргументов процедур или функций-процедур:

Синтаксис

[ByVal | ByRef] arrayname() As type

 

Как в случае аргументов процедур и функций-процедур, о которых вы уже знаете, ключевое слово ByVal указывает Visual Basic передать аргумент-массив по значению, а ключевое слово ByRef указывает, что следует передавать аргумент-массив по ссылке. Если ByVal и ByRef пропущены, аргумент-массив передается по ссылке.

В этой синтаксической конструкции arrayname() представляет аргумент-массив; можно использовать любой допустимый VB-идентификатор в качестве имени аргумента-массива. Необходимо всегда включать пустые круглые скобки после arrayname; круглые скобки указывают, что этот аргумент является массивом. Параметр type представляет любой допустимый VB-тип (или определенный пользователем тип).

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

Sub ShowText(Lines(), NumLines As Integer)

'получает массив типа Variant, передаваемый по ссылке

End Sub

 

Sub SortList(ByRef List() As String, NumLines As Integer)

'получает массив типа String, передаваемый по ссылке

End Sub

 

Если вы помните, передача аргументов по значению (с помощью ключевого слова ByVal) приводит к тому, что Visual Basic передает копию данных функции-процедуре или процедуре. Не передавайте массивы по значению, если в этом нет особой необходимости — передача больших массивов по значению может быстро исчерпать ресурсы памяти вашего компьютера, приводя к runtime-ошибкам из-за нехватки памяти.

Бизнес-пример

Рассмотрим бизнес-пример, в котором нам необходимо заданный интервал дат разбить на столько интервалов, сколько входит месяцев в исходный интервал. Это может быть необходимо при извлечении данных из базы, в которой определенная информация располагается для каждого месяца отдельно, а в диалоговом окне пользователя допускается указать для обработки любой интервал дат.

А теперь — о деталях примера. Пусть задан интервал: dateBegindateEnd (начальная дата – конечная дата). Необходимо получить такие интервалы, в которых начальные и конечные даты будут иметь одинаковые месяцы. Например, интервал 10/01/2002–20/03/2002 состоит из следующих интервалов: 10/01/2002–31/01/2002, 01/02/2002–28/28/2002 и 01/03/2002–20/03/2002. Как видно из примера, количество получаемых интервалов заранее неизвестно и зависит от длины исходного интервала. Поэтому, если исходный интервал можно задавать двумя переменными (dateBegindateEnd ), то результат удобно получать в виде двух массивов: массив начальных дат (masBegin) и массив конечных дат (masEnd).

Алгоритм, по которому работает функция, может быть очень простым. Массивам задается размерность 1, поскольку она не может быть равной нулю (при dateBegin <= dateEnd). Первый элемент массива с начальными датами принимает значение начальной даты (переменная-аргументdateBegin). Этим же значением инициализируется временная переменная CurrentDate. Далее в цикле переменная CurrentDate, объявленная как Date, увеличивается на единицу (на один день), при этом проверяется, не произошло ли изменение месяца по сравнению с текущим. Если месяц изменился, меняется значение переменной CurrentMon, сохраняющей текущий месяц, изменяется размерность массивов, сохраняется значение конца интервала для предыдущего месяца. После окончания цикла остается только заполнить значение конца последнего интервала и значение, возвращаемое функцией-процедурой.

Функция-процедура (листинг 10.2) не проверяет правильность данных (dateBegin <= dateEnd); это может проверить вызывающая ее программа. Обратите внимание на то, как при объявлении функции-процедуры (строка 2) указываются аргументы-массивы.

Листинг 10.2. Передача массива в качестве аргумента

1 Function inervals(dateBegin As Date, dateEnd As Date, _

2 masBegin() As Date, masEnd() As Date)

3 ' Возвращает количество интервалов дат, равных количеству

4 ' вошедших в интервал месяцев. Сами диапазоны возвращаются

5 ' в массивах: masBegin, masEnd

7 Dim CurrentDate As Date 'текущая дата

8 Dim masSizeCurrent As Integer 'размерность массивов

9 Dim CurrentMon As Integer 'текущий месяц

11 masSizeCurrent = 1 ‘ размерность массивов не меньше 1

13 'Переопределение размерности массивов:

14 ReDim masBegin(masSizeCurrent)

15 ReDim masEnd(masSizeCurrent)

17 'первый элемент массива с начальной датой:

18 masBegin(0) = dateBegin

20 'Инициализация текущего месяца и даты:

21 CurrentMon = Month(dateBegin)

22 CurrentDate = dateBegin

24 'Цикл с изменением текущих значений даты и месяца

25 Do While CurrentDate < dateEnd

27 CurrentDate = CurrentDate + 1

28 If CurrentMon <> Month(CurrentDate) Then

30 'месяц изменился, меняем текущий месяц

31 CurrentMon = Month(CurrentDate)

33 'элемент массива с конечной датой:

34 masEnd(masSizeCurrent - 1) = CurrentDate – 1

36 'изменить размерность массивов

37 masSizeCurrent = 1 + masSizeCurrent

38 ReDim Preserve masBegin(masSizeCurrent)

39 ReDim Preserve masEnd(masSizeCurrent)

41 'элемент массива с конечной датой:

42 masBegin(masSizeCurrent - 1) = CurrentDate

44 End If

45 Loop

47 'последний элемент массива с конечной датой:

48 masEnd(masSizeCurrent - 1) = dateEnd

50 'значение, возвращаемой функцией

51 inervals = masSizeCurrent

53 End Function

Для тестирования функции intervals можно использовать следующую программу. Заметьте, что в исходных датах необязательно должен быть один и тот же год. До вызова функции необходимо объявить рабочие массивы, имена которых (как ссылки) должны быть переданы в функцию.

Листинг 10.3. Тестирование функции inervals

1 Private Sub Command1_Click()

2 Dim masBegin() As Date, masEnd() As Date

3 Dim dateBegin As Date, dateEnd As Date

5 'считать данные из элементов управления в переменные:

6 dateBegin = MaskEdBox1.Text

7 dateEnd = MaskEdBox2.Text

9 'если данные верны, вызвать функцию inervals

10 'и выдать в окне MsgBox результаты:

11 If Not dateBegin > dateEnd Then

12 zzz = inervals(dateBegin, dateEnd, masBegin, masEnd)

13 For i = 0 To zzz - 1

14 MsgBox masBegin(i) & "-" & masEnd(i)

15 Next

16 Else

17 MsgBox "Диапазон дат задан неверно!"

18 End If

19 End Sub

Функции LBound и UBound

Для контроля за размерами массивов переменной размерности можно использовать одну или пару переменных для сохранения минимального и максимального индекса массива. Если для отслеживания верхнего и нижнего пределов индексов массива пользователь полагается на собственные переменные, то он полностью отвечает за обновление и точность этих переменных. В противном случае процедуры не будут работать правильно — будет обрабатываться меньше элементов, чем в действительности содержит массив, или будет получено сообщение об ошибке при попытке доступа к массиву с индексами, выходящими за фактический размер массива. Такие программные ошибки бывает трудно отслеживать.

Visual Basic имеет две функции, которые освобождают пользователя от необходимости вручную отслеживать верхний и нижний пределы массива — функции LBound и UBound. Эти функции возвращают нижнее и верхнее граничные значения индексов массива переменной размерности.

Функции LBound и UBound имеют следующий синтаксис:

Синтаксис

LBound(arrayName [, dimension])

UBound(arrayName [, dimension])

 

Функция LBound возвращает первый индекс массива, представленного с помощью arrayName. Функция UBound возвращает наибольший индекс массива, представленного с помощью arrayName. Аргумент dimension представляет целое число, определяющее измерение массива, для которого необходимо получить нижний или верхний предел. Если опустить dimension, возвращается предел для первого измерения массива.

Следующие фрагменты кода являются примерами использования функций LBound и Ubound:

 

Dim A(3 To 9) As String

For I = LBound(A) To UBound(A)

A(I) = String(10, 65 + I)

Next I

 

Dim aMatrix(1 To 365, 1990 To 1999)

For i = LBound(aMatrix, 1) To UBound(aMatrix, 1)

For j = LBound(aMatrix, 2) To UBound(aMatrix, 2)

Matrix(i, j) = Rnd

Next j

Next i

 

Заметьте, что во втором примере функции LBound и UBound используют необязательный аргумент dimension. Внешний цикл For…Next выполняется столько раз, сколько элементов имеется в первом измерении массива aMatrix, тогда как внутренний цикл For…Next выполняется столько раз, сколько элементов имеется во втором измерении массива aMatrix.

Использование Erase для очистки или удаления массивов

Visual Basic имеет особый оператор Erase, позволяющий выполнять одну из двух задач в зависимости от того, каким массивом манипулирует пользователь — переменной размерности или фиксированной. В случае массивов фиксированных размеров Erase позволяет очищать все элементы массива, в основном переустанавливая массив в то же самое состояние, какое он имел, когда Visual Basic создавал его в оперативной памяти. В случае динамических массивов Erase позволяет полностью удалять массив и его содержимое из оперативной памяти.

Когда элементы массива заполнены, данные в массиве (фиксированных размеров или переменной длины) остаются до тех пор, пока пользователь не присвоит новые значения элементам массива или пока Visual Basic не освободится от массива. (Массивы следуют тем же правилам области действия, что и любая другая переменная в Visual Basic)

При некоторых обстоятельствах может понадобиться очистить все значения в массиве, устанавливая числовые значения на 0, строковые значения на пустые строки и так далее. Обычно следует использовать цикл For…Next или For…Each для установки всех элементов в массиве на определенное значение. Следующие фрагменты кода показывают оба цикла For…Next и For…Each, используемые для инициализации всех значений в числовом массиве на 0:

 

For k = LBound(NumArray) To UBound(NumArray)

NumArray(k) = 0

Next k

 

For Each Num In NumArray

Num = 0

Next Num

 

Первый фрагмент кода использует цикл For…Next и функции LBound и UBound для прохождения в цикле по всем элементам массива; второй фрагмент кода использует For…Each для прохождения в цикле по каждому элементу массива, также устанавливая каждый элемент на 0. Хотя эти циклы довольно короткие, можно выполнить ту же самую задачу для массива фиксированной размерности даже более эффективно с помощью единственного оператора Erase:

 

Erase NumArray

 

Массивы «имеют тенденцию» занимать относительно большой объем оперативной памяти — например, массив из 20 элементов занимает такой же объем памяти, как 20 отдельных переменных одного и того же типа. Поскольку массивам требуется так много памяти, следует удалять динамические массивы из оперативной памяти, когда они фактически не используются.

Visual Basic удаляет из памяти массивы, объявляемые локально в процедуре (так же, как и любые другие локальные переменные), каждый раз, когда процедура прекращает выполняться. Однако массивы, объявляемые на модульном уровне, существуют, пока любая процедура в этом модуле выполняется. Если программа большая, вам может понадобиться восстановить ресурс памяти, используемой динамическими массивами модульного уровня. Оператор Erase позволяет делать именно это.

Оператор Erase имеет следующий синтаксис:

Синтаксис

Erase array1 [, array2, …]

 

Здесь array1 и array2 представляют любое допустимое имя VB-массива Можно перечислить столько массивов в операторе Erase, сколько хотите, отделяя каждое имя массива запятой.

Оператор Erase удаляет из памяти динамические массивы, освобождая область памяти, ранее используемую этим массивом. При удалении динамического массива с помощью оператора Erase необходимо повторно создать массив с помощью оператора ReDim перед тем, как можно будет использовать этот определенный динамический массив снова. При попытке доступа к элементам в динамическом массиве, для которого был использован оператор Erase, без его переопределения, Visual Basic отображает сообщение о runtime-ошибке.

Поведение оператора Erase для массивов фиксированных размеров немного сложнее и зависит от конкретного типа элементов массива. В следующей таблице описывается действие оператора Erase с массивами фиксированных размеров различных типов:

 

Тип массива фиксированного размера Действие оператора Erase
Любой числовой тип Устанавливает элементы массива на 0.
Любой строковый тип Устанавливает элементы массива на строку нулевой длины («»); устанавливает строки фиксированной длины как все символы пробелов.
Variant Устанавливает элементы массива на Empty.
Object Устанавливает элементы массива на Nothing.
Любой пользовательский тип Устанавливает каждую переменную в пользовательском типе отдельно: численные типы устанавливаются на 0, строковые — на строки нулевой длины, Variant — на Empty, Object — на Nothing.


<== предыдущая лекция | следующая лекция ==>
Объявление массивов | Массивы элементов управления


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.083 сек.