Option Base ?

Программирование на Visual Basic for Applications
Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Option Base ?

Сообщение Евгений Д. » 18.10.2005 (Вт) 19:36

Еще вопрос по масивам. Как определить, какое значение имеет Option Base в модуле, где определен динамический массив (но не переопределен по ReDim) и передан в качестве аргумента функции, которая вообще говоря может находиться в другом модуле (со своим значением Option Base). И в теле этой функции я хочу узнать с 0 или с 1-го элемента у меня будет начинаться динамический массив.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 18.10.2005 (Вт) 19:39

LBound?
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 18.10.2005 (Вт) 19:41

А почему, собственно, только 0 и 1?..
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 18.10.2005 (Вт) 19:42

Не-а! Если массив пустой (неинициализированный), то Lbound даст ошибку!

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 18.10.2005 (Вт) 19:45

Ты прикалываешься?

Тебе же тут ответили.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 18.10.2005 (Вт) 19:54

Уточню. В примере Андрея Федорова:


Код: Выделить всё
Public Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" _
    (Destination As Any, Source As Any, ByVal Length As Long)

Public Function UboundArray(ArrayName As Variant, Optional Dimension As Integer = 1) As Long
    If Dimension < 1 Or Dimension > GetArrayDimensions(ArrayName) Then
        UboundArray = -1
    Else
        UboundArray = UBound(ArrayName, Dimension)
    End If
End Function

Public Function GetArrayDimensions(arr As Variant) As Integer
    Dim a As Long

    CopyMemory a, ByVal VarPtr(arr) + 8, 4
    CopyMemory a, ByVal a, 4
    If a Then CopyMemory GetArrayDimensions, ByVal a, 2
End Function


я хочу присваивание UboundArray = -1 делать когда Option Base 0 в том модуле, где объявлен ArrayName, и UboundArray = 0, если там стоит Option Base 1. Тогда получая значение UboundArray, номер первого элемента динамического массива будет UboundArray+1, как для Option Base 0, так и Option Base 1.

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 18.10.2005 (Вт) 20:22

А какая разница, какой option base? Кто-то использует в VB массивы с неявным объявлением нижней границы? :roll:
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 10:39

Я не использую нижний индекс отличный от 0 или 1, и поэтому хочу иметь некоторую универсальность. Например, если я создаю список в List или ComboBox, то там индекс первого элемента - нулевой, а обычные массивы у меня, как правило, имеют индекс 1. Поэтому несколько странно, что в VBA, похоже, нет функции, которая возвращает значение Option Base, хотя, возможно, она зарыта где-то в структуре SAFEARRAY, в которой я еще подробно не копался.

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 19.10.2005 (Ср) 10:45

Помоему это как раз тот случай, когда создают себе трудности, чтобы героически их преодолевать.
Указывай нижнюю границу массива и будет тебе счастье.
Lasciate ogni speranza, voi ch'entrate.

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 10:58

Для динамического массива? Насколько я понимаю ее можно указать только в момент переопределения по Redim [Preserve]. И что я должен написать для первого элемента Redim MyArray(0) или Redim MyArray(1) я должен знать заранее. Если это не первый элемент, то все работает на автомате:
Код: Выделить всё
Rows = UBound(MyArray)+1
Redim Preserve MyArray(Rows)
MyArray(Rows) = ...


Т.е. вопрос о том, с какого индекса VBA начнет "гнать" элементы динамического массива?

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 19.10.2005 (Ср) 11:06

Блин.

Ни с какого.
До создания массив не существует и у него нет нижнего элемента, равно как верхнего и всех остальных.
А при создании и то, и другое указывается явно.
А если ты этой возможностью пренебрегаешь и находишь кайф косить траву в противогазе, то флаг в руки.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 11:14

Нет, так нет. Нет проблем. Жил как-то и до этого. Ну сделаю пару похожих функций или пусть будет одна с Optional параметром FirstIndex = 0. Все в наших руках :lol:

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 19.10.2005 (Ср) 11:31

О господи...


Ты можешь членораздельно объяснить, нафига тебе этот FirstIndex?
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 11:49

У меня есть функция:

Код: Выделить всё
Function arr_AddItem_AZ( _
  NewItem, _
  TgtArr()) As Long

'Добавление уникального элемента в одномерный массив
'TgtArr и сортировка получившегося по алфавиту (A->Z)
'
'На входе:
'~~~~~~~~~
'NewItem - добавляемый элемента
'TgtArr  -   массив, в который производится добавление
'
'На выходе:
'~~~~~~~~~~
'
'-1 - такой элемент уже существует в массиве (добавление не произведено)
'>0 - каким номером в массиве стал добавляемый элемент

Dim TgtArrRows As Integer

  On Error Resume Next
 
  TgtArrRows = UBound(TgtArr)
 
  If Err.Number <> 0 Then

    ReDim TgtArr(1)
    TgtArr(1) = NewItem

    arr_AddItem_AZ = 1
    Exit Function

  End If

  Err.Clear ' добавление первой записи

  For CurRow = 1 To TgtArrRows

    If TgtArr(CurRow) = NewItem Then

      arr_AddItem_AZ = -1
      Exit Function

    End If

  Next CurRow

  TgtArrRows = TgtArrRows + 1

  ReDim Preserve TgtArr(TgtArrRows)

  If TgtArrRows > 1 Then

    For CurRow = TgtArrRows - 1 To 1 Step -1

      If TgtArr(CurRow) > NewItem Then

'копируем запись вниз, т.к. "поплавок" еще не всплыл

        TgtArr(CurRow + 1) = TgtArr(CurRow)

      Else  'TgtArr(CurRow) > NewItem

        Exit For

      End If  'TgtArr(CurRow) > NewItem

    Next CurRow

  Else  'TgtArrRows > 1

    CurRow = TgtArrRows - 1

  End If  'TgtArrRows > 1

  CurRow = CurRow + 1

  TgtArr(CurRow) = NewItem

  arr_AddItem_AZ = CurRow

End Function


Я хочу сделать ее универсальной для пополнения любого массива: как начинающегося с нулевого индекса (если этот массив определен в модуле с Option Base 0 или вообще без Option Base), так и начинающегося с индекса 1 (если этот массив определен в модуле с Option Base 1).
Массивы, естественно, динамические, и я должен в этой функции знать начение первого индекса. Вроде тут я не туплю, хотя всякое бывало...

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 19.10.2005 (Ср) 12:02

Потрясающе.

А ты знаешь, что ReDim Preserve TgtArr(TgtArrRows) сработает только в том случае, если нижняя граница массива совпадает с текущей по умолчанию?
Нет?

И потом, прочитай внимательно то, что написано здесь.



И вообще, подумай надо одной забавной вещью: почему у тебя не вызывает проблем определить верхнюю границу, но вызывает определить нижнюю?
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 12:18

Ну не нужна мне возможность MyArray(-5 to 25), меня устраивает MyArray(0 to n-1) или MyArray(1 to n).
По поводу того, нижний или верхний индекс: при первом ReDim они будут одинаковыми, но какими?

GSerg писал(а): И потом, прочитай внимательно то, что написано здесь.


По кругу?

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 19.10.2005 (Ср) 12:25

Евгений Д. писал(а):Ну не нужна мне возможность MyArray(-5 to 25), меня устраивает MyArray(0 to n-1) или MyArray(1 to n).

А ты не понимаешь, что средства работы с массивами одни и те же независимо от нижних границ? Или ты думаешь, что 0 и 1 стоят как-то особянком как особые числа?

Евгений Д. писал(а):По поводу того, нижний или верхний индекс: при первом ReDim они будут одинаковыми, но какими?

Я тихо офигеваю.

Прочитай внимательно всё написанное в этом топике.
И спроси себя, почему ты используешь неявное задание нижней границы, а потом пытаешься с ним бороться.

Ты вообще знаешь о синтаксисе dim a(1 to 10)? И redim a(1 to 10) тоже, если на этот счёт у тебя возникнет вопрос.

Евгений Д. писал(а):По кругу?

Не по кругу.
Это ссылка на первый ответ в этом топике, который уже содержит всё, что можно сказать по этому вопросу.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Al Khamid
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 274
Зарегистрирован: 11.02.2004 (Ср) 10:00
Откуда: Москва, Ховрино

Сообщение Al Khamid » 19.10.2005 (Ср) 12:33

<К делу не относится>
Последний раз редактировалось Al Khamid 24.11.2007 (Сб) 13:13, всего редактировалось 1 раз.

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 12:40

Ставлю вопрос конкретно: пришел пустой (неинициализированый, без нижней и верхней границы) массив TgtArr

Код: Выделить всё
Dim TgtArrRows As Integer

  On Error Resume Next
 
  TgtArrRows = UBound(TgtArr)
 
  If Err.Number <> 0 Then

    ReDim TgtArr(?)
    TgtArr(?) = NewItem

    arr_AddItem_AZ = ?
    Exit Function

  End If


Что мне написать вместо "?"
[/code]

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 19.10.2005 (Ср) 12:51

Ни фига себе...

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

Проблема-то в чём? Я до сих пор её увидеть не могу.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 13:04

А я и не хочу ничего переопределять - я функция! Меня вызвали создать первый элемент: то ли с 0, то ли с 1 (потом все пойдет как по маслу). И я (функция) хочу знать откуда (из какого модуля) пришел этот "голый" массив (да и не массив он еще, а так - декларация с двумя круглыми скобками), чтобы начать его с правильного индекса.

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

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.10.2005 (Ср) 13:12

У декларации нету начального индекса.
Он появляется только в момент первого редима.

Ты не можешь узнать значение несуществующей величины. Никак.
Изображение

alibek
Большой Человек
Большой Человек
 
Сообщения: 14205
Зарегистрирован: 19.04.2002 (Пт) 11:40
Откуда: Russia

Сообщение alibek » 19.10.2005 (Ср) 13:15

Код: Выделить всё
Function FirstBoundIndex() As Integer
Dim temp(1)
FirstBoundIndex = LBound(temp)
End Function


P.S. Если бы я увидел данный код на собеседовании, я бы данного соискателя и в дворники не взял.
Lasciate ogni speranza, voi ch'entrate.

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 13:17

Вот я и говорю, пусть это будет либо 0, либо 1 (мне этого хватит :D ). И дайте мне, пожалуйста, значение Option Base, а там уже я сам смогу правильно н'ачать. А где его взять-то это Option Base?

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 13:21

alibek писал(а):
Код: Выделить всё
Function FirstBoundIndex() As Integer
Dim temp(1)
FirstBoundIndex = LBound(temp)
End Function


...


Опаньки! А почему temp(1), а не temp(0). А если у меня эта функция лежит в модуле, где Option Base отличный от того модуля, откуда приходит (где объявлен) мой массив?

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 19.10.2005 (Ср) 13:23

А пофигу.
Пойми суть этого кода.
Последний раз редактировалось GSerg 19.10.2005 (Ср) 13:25, всего редактировалось 1 раз.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 13:24

Блин, уже на одну звезду нашкрябал :D

Евгений Д.
Обычный пользователь
Обычный пользователь
 
Сообщения: 96
Зарегистрирован: 21.09.2004 (Вт) 17:32
Откуда: Москва

Сообщение Евгений Д. » 19.10.2005 (Ср) 13:27

GSerg писал(а):На самом деле нужн переделать весь остальной код так, чтобы он не зависел от нижней границы.


А я и писал, что хочу переделать: убрать On Error, поставить, где надо LBound и т.д.

tyomitch
Пользователь #1352
Пользователь #1352
Аватара пользователя
 
Сообщения: 12822
Зарегистрирован: 20.10.2002 (Вс) 17:02
Откуда: חיפה

Сообщение tyomitch » 19.10.2005 (Ср) 13:27

Оппа, предлагаю решение.
Подключай VBE (ThisDocument.VBProject), анализируй тексты модулей, находи в них оператор Option Base и анализируй.
Какая задача кривая, такое кривое и решение.
Изображение

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 19.10.2005 (Ср) 13:32

Евгений Д. писал(а):А я и писал, что хочу переделать: убрать On Error, поставить, где надо LBound и т.д.

Так вот когда ты это сделаешь, тебе вообще не понадобится знать, где какой option base.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

След.

Вернуться в VBA

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 7

    TopList  
cron