Как определить, инициализирован ли массив в VB6? - PullRequest
51 голосов
/ 08 октября 2008

Передача безразмерного массива в функцию Ubound VB6 вызовет ошибку, поэтому я хочу проверить, был ли он измерен, прежде чем пытаться проверить его верхнюю границу. Как мне это сделать?

Ответы [ 21 ]

1 голос
/ 30 апреля 2015

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

Он поддерживает код тестирования в соответствии с использованием UBOUND и не требует использования обработки ошибок для тестирования.

Это зависит от нулевых массивов (что имеет место в большинстве разработок).

Не должен использовать «Erase» для очистки массива. используйте альтернативу, указанную ниже.

Dim data() as string ' creates the untestable holder.
data = Split(vbNullString, ",") ' causes array to return ubound(data) = -1
If Ubound(data)=-1 then ' has no contents
    ' do something
End If
redim preserve data(Ubound(data)+1) ' works to increase array size regardless of it being empty or not.

data = Split(vbNullString, ",") ' MUST use this to clear the array again.
1 голос
/ 22 января 2012

Когда вы инициализируете массив, поставьте целое или логическое значение с флагом = 1. и запросите этот флаг, когда вам нужно.

0 голосов
/ 26 сентября 2018

Я вижу много предложений в Интернете о , как определить, был ли массив инициализирован . Ниже приведена функция, которая примет любой массив, проверит, что представляет собой ubound этого массива, повторно изменит размер массива в ubound +1 (с или без PRESERVER), а затем вернет текущее значение ubound массива без ошибок.

Function ifuncRedimUbound(ByRef byrefArr, Optional bPreserve As Boolean)
On Error GoTo err:

1: Dim upp%:           upp% = (UBound(byrefArr) + 1)

errContinue:

If bPreserve Then
         ReDim Preserve byrefArr(upp%)
Else
         ReDim byrefArr(upp%)
End If

ifuncRedimUbound = upp%


Exit Function
err:
If err.Number = 0 Then Resume Next
    If err.Number = 9 Then ' subscript out of range (array has not been initialized yet)
             If Erl = 1 Then
                         upp% = 0
                         GoTo errContinue:
             End If
    Else
               ErrHandler.ReportError "modArray", ifuncRedimUbound, "1", err.Number, err.Description
    End If
End Function
0 голосов
/ 15 февраля 2018

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

Вот мое решение (к актуальной проблеме, а не к названию):

Function UBound2(Arr) As Integer
  On Error Resume Next
  UBound2 = UBound(Arr)
  If Err.Number = 9 Then UBound2 = -1
  On Error GoTo 0
End Function

Эта функция работает в следующих четырех сценариях: первые три, которые я обнаружил, когда Arr создается внешним dll COM, и четвертая, когда Arr не ReDim -ед (предмет этого вопрос):

  • UBound(Arr) работает, поэтому вызов UBound2(Arr) добавляет немного накладных расходов, но не сильно ранит
  • UBound(Arr) терпит неудачу в функции, которая определяет Arr, но преуспевает внутри UBound2()
  • UBound(Arr) завершается ошибкой как в функции, которая определяет Arr, так и в UBound2(), поэтому обработка ошибок выполняет работу
  • После Dim Arr() As Whatever, до ReDim Arr(X)
0 голосов
/ 14 сентября 2016

Есть два слегка отличающихся сценария для тестирования:

  1. Массив инициализирован (фактически это не нулевой указатель)
  2. Массив инициализирован и имеет хотя бы один элемент

Случай 2 необходим для случаев типа Split(vbNullString, ","), который возвращает массив String с LBound=0 и UBound=-1. Вот простейшие примеры фрагментов кода, которые я могу создать для каждого теста:

Public Function IsInitialised(arr() As String) As Boolean
  On Error Resume Next
  IsInitialised = UBound(arr) <> 0.5
End Function

Public Function IsInitialisedAndHasElements(arr() As String) As Boolean
  On Error Resume Next
  IsInitialisedAndHasElements = UBound(arr) >= LBound(arr)
End Function
0 голосов
/ 12 июля 2016
If ChkArray(MyArray)=True then
   ....
End If

Public Function ChkArray(ByRef b) As Boolean
    On Error goto 1
    If UBound(b) > 0 Then ChkArray = True
End Function
0 голосов
/ 13 декабря 2015

Вы можете решить проблему с помощью функции Ubound(), проверьте, не является ли массив пустым, путем получения общего количества элементов с использованием объекта VBArray() JScript (работает с массивами вариантного типа, одиночного или многомерного):

Sub Test()

    Dim a() As Variant
    Dim b As Variant
    Dim c As Long

    ' Uninitialized array of variant
    ' MsgBox UBound(a) ' gives 'Subscript out of range' error
    MsgBox GetElementsCount(a) ' 0

    ' Variant containing an empty array
    b = Array()
    MsgBox GetElementsCount(b) ' 0

    ' Any other types, eg Long or not Variant type arrays
    MsgBox GetElementsCount(c) ' -1

End Sub

Function GetElementsCount(aSample) As Long

    Static oHtmlfile As Object ' instantiate once

    If oHtmlfile Is Nothing Then
        Set oHtmlfile = CreateObject("htmlfile")
        oHtmlfile.parentWindow.execScript ("function arrlength(arr) {try {return (new VBArray(arr)).toArray().length} catch(e) {return -1}}"), "jscript"
    End If
    GetElementsCount = oHtmlfile.parentWindow.arrlength(aSample)

End Function

Для меня это занимает около 0,4 мкс для каждого элемента + 100 мс инициализации, компилируется с VB 6.0.9782, поэтому массив из 10M элементов занимает около 4,1 с. Та же функциональность может быть реализована через ScriptControl ActiveX.

0 голосов
/ 25 июня 2014

Это сработало для меня, какая-то ошибка в этом?

If IsEmpty(a) Then
    Exit Function
End If

MSDN

0 голосов
/ 08 октября 2008
Dim someArray() as Integer    

If someArray Is Nothing Then
    Debug.print "this array is not initialised"
End If
0 голосов
/ 12 августа 2012

Моя единственная проблема с вызовами API - переход с 32-битных на 64-битные ОС.
Это работает с объектами, строками и т.д ...

Public Function ArrayIsInitialized(ByRef arr As Variant) As Boolean
    On Error Resume Next
    ArrayIsInitialized = False
    If UBound(arr) >= 0 Then If Err.Number = 0 Then ArrayIsInitialized = True
End Function
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...