Массив переменных

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
STanli
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 163
Зарегистрирован: 31.05.2004 (Пн) 15:22
Откуда: ТОМСК

Массив переменных

Сообщение STanli » 02.09.2004 (Чт) 20:01

Как Очистить переменную из массива со здвигом данных?
Раз, два, три, четыре, пять, с детства с рифмой я дружу.

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

Сообщение GSerg » 02.09.2004 (Чт) 20:04

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

A.A.Z.
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3035
Зарегистрирован: 30.06.2003 (Пн) 13:38

Сообщение A.A.Z. » 02.09.2004 (Чт) 21:57

GSerg, ну ведь знаешь же, что сейчас пример потребуют! :)

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

Сообщение tyomitch » 02.09.2004 (Чт) 22:09

Дык а чё тут писать?
CopyMemory Massiv(i), Massiv(i + 1), LenB(Massiv(LBound(Massiv))) * (UBound(Massiv) - i)
Изображение

A.A.Z.
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
 
Сообщения: 3035
Зарегистрирован: 30.06.2003 (Пн) 13:38

Сообщение A.A.Z. » 02.09.2004 (Чт) 22:11

Вот теперь не потребуют :thumright:

CodeName33
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 297
Зарегистрирован: 01.09.2004 (Ср) 13:25
Откуда: SPb

Сообщение CodeName33 » 03.09.2004 (Пт) 9:30

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

TEH3OP
Продвинутый пользователь
Продвинутый пользователь
 
Сообщения: 143
Зарегистрирован: 12.12.2003 (Пт) 20:19
Откуда: Москва

А проще говоря...

Сообщение TEH3OP » 03.09.2004 (Пт) 9:48

А если массив не оч. большой (САБЖ не жалко памяти) и если не хочется париться, то заместо массива лучшее использовать Scripting.Dictionary или VBA.Collection. Тама и добавлять и удалять мона и поиск производится быстро.

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

Сообщение tyomitch » 03.09.2004 (Пт) 11:25

CodeName33 писал(а):CopyMemory не прокатит если это массив из пльзовательского типа данных. Кидать будет.

Почему? Объясни плз
Изображение

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

Сообщение GSerg » 03.09.2004 (Пт) 17:33

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

BP
Бывалый
Бывалый
 
Сообщения: 234
Зарегистрирован: 17.02.2004 (Вт) 5:34
Откуда: Украина

Сообщение BP » 04.09.2004 (Сб) 1:51

Не, ну вы молодцы ребята. У меня теперь из за ваши экскрементов VB перестал запускаться. Надеюсь только до перезагрузки.

Да, пользовательские типы он действительно копирует. Вот только выбивает когда обращаешся к последнему элементу. Возможно это лечится Redim Preserve. Проверить не могу по причинам указанным выше.

CodeName33
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 297
Зарегистрирован: 01.09.2004 (Ср) 13:25
Откуда: SPb

Сообщение CodeName33 » 04.09.2004 (Сб) 9:13

>Почему? Объясни плз

Раньше не мог понять, чего у меня прога одна кидает иногда. А причина была в том, что когда передаёшь в API функцию параметр A(1), то если A() массив обычных типов (Int, Long) то VB передаёт реальный адрес первого элемента, а если он массив сложных пользовательских типов данных (ещё с подтипами внутри), то VB почему-то копировал один передаваемый элемент в отдельную область памяти, и передавал его адрес. Зачаем я так и не понял. Но если самому докопаться до реального адреса массива (VarPtrArray(A()), а потом через структуры SAFEARRAY), то можно и через CopyMemory двигать.
Программисты не глючат - глючат компиляторы...

Approximator
Постоялец
Постоялец
 
Сообщения: 572
Зарегистрирован: 26.06.2004 (Сб) 3:10

Сообщение Approximator » 05.09.2004 (Вс) 2:49

CodeName33 писал(а):>Почему? Объясни плз

Раньше не мог понять, чего у меня прога одна кидает иногда. А причина была в том, что когда передаёшь в API функцию параметр A(1), то если A() массив обычных типов (Int, Long) то VB передаёт реальный адрес первого элемента, а если он массив сложных пользовательских типов данных (ещё с подтипами внутри), то VB почему-то копировал один передаваемый элемент в отдельную область памяти, и передавал его адрес. Зачаем я так и не понял. Но если самому докопаться до реального адреса массива (VarPtrArray(A()), а потом через структуры SAFEARRAY), то можно и через CopyMemory двигать.


Прости, уважаемый, но либо я тебя не понял (и тогда извиняюсь), либо это, ещё раз извини, фигня.
Массивы пользовательских типов имеют двух и более уровневую организацию.
Причём, первый уровень это практически всегда массив Long, в котором содержатся адреса на одтельные элементы массива (кстати говоря, массив String'ов устроен абсолютно таким же образом и делается так потому, что подобные переменные сложноустроены - имеют Long-префикс определяющий их длину). Конечно, далее ты правильно заметил, чтобы изменить такой массив необходимо изменять его размер в SAFEARRAY. Но на использовании CopyMemory это изначально никак не влияет.
С уважением, Approximator.

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

Сообщение tyomitch » 05.09.2004 (Вс) 12:23

Approximator, CodeName33 прав - я просто совсем выпустил из виду эту "особенность" VB. Если по ссылке передаётся структура, содержащая строки и/или паддинг, то VB создаёт её временную копию, и передаёт в функцию именно копию.
Поэтому вот UDT-safe версия сдвига:
CopyMemory ByVal VarPtr(Massiv(i)), ByVal VarPtr(Massiv(i + 1)), LenB(Massiv(LBound(Massiv))) * (UBound(Massiv) - i)
Изображение

CodeName33
Бывалый
Бывалый
Аватара пользователя
 
Сообщения: 297
Зарегистрирован: 01.09.2004 (Ср) 13:25
Откуда: SPb

Сообщение CodeName33 » 05.09.2004 (Вс) 22:12

>CopyMemory ByVal VarPtr(Massiv(i)), ByVal VarPtr(Massiv(i + 1)), LenB(Massiv(LBound(Massiv))) * (UBound(Massiv) - i)

У меня в своё время так не прокатило. Он в VarPtr тоже передавал копию элемента и не давал адрес самого массива. Хотя может я и ошибаюсь...
Программисты не глючат - глючат компиляторы...

Approximator
Постоялец
Постоялец
 
Сообщения: 572
Зарегистрирован: 26.06.2004 (Сб) 3:10

Сообщение Approximator » 06.09.2004 (Пн) 1:50

tyomitch писал(а):Approximator, CodeName33 прав

Неа. Ну, не виноват я, что он не прав. :)
tyomitch писал(а): - я просто совсем выпустил из виду эту "особенность" VB. Если по ссылке передаётся структура, содержащая строки и/или паддинг, то VB создаёт её временную копию, и передаёт в функцию именно копию.

Буду возражать. :) Усё зависит от того, как эту проблему решать. Если использовать инкапсуляцию, то всё получается нормально
Вот тебе функция, а заодно и идея, которые можешь использовать, как твоей душеньке угодно. :)
Код: Выделить всё
Public Function AnyPtr(ByRef vVar As Variant) As Long
CopyMem VarPtr(AnyPtr), VarPtr(vVar) + 1, 1
If AnyPtr = 64 Or AnyPtr = 96 Then CopyMem VarPtr(AnyPtr), VarPtr(vVar) + 8, 4
End Function

И никаких копий. Забудь о них. :)

tyomitch писал(а):
Код: Выделить всё
CopyMemory ByVal VarPtr(Massiv(i)), ByVal VarPtr(Massiv(i + 1)), LenB(Massiv(LBound(Massiv))) * (UBound(Massiv) - i)

Не, мне кажется, что здесь может подглючивать. Попробуй заменить VarPtr на AnyPtr.
С уважением, Approximator.

Approximator
Постоялец
Постоялец
 
Сообщения: 572
Зарегистрирован: 26.06.2004 (Сб) 3:10

Сообщение Approximator » 06.09.2004 (Пн) 1:57

CodeName33 писал(а):>CopyMemory ByVal VarPtr(Massiv(i)), ByVal VarPtr(Massiv(i + 1)), LenB(Massiv(LBound(Massiv))) * (UBound(Massiv) - i)

У меня в своё время так не прокатило. Он в VarPtr тоже передавал копию элемента и не давал адрес самого массива. Хотя может я и ошибаюсь...

Согласен. Надо было решать так же, как я это показал в AnyPtr (см. мой предыдущий пост в теме). :) Граждане, ползуйтесь инкапсуляцией! :) Она иногда очень сильно экономит нервы. :)

Есть, конечно ещё пара вариантов. Можно решать по примеру GSerg'а.
А именно
функция для пользовательского типа
Код: Выделить всё
Public Function SomeTypePtr(byref vSomeType as SomeType, optional byval vPleaseIgnoreMe as Long=0)as Long
CopyMem VarPtr(SomeTypePtr), VarPtr(vPleaseIgnoreMe)-4,4
End Function

функция для массива того же пользовательского типа
Код: Выделить всё
Public Function SomeTypeArrPtr(byref vSomeTypeArr() as SomeType, optional byval vPleaseIgnoreMe as Long=0)as Long
CopyMem VarPtr(SomeTypeArrPtr), VarPtr(vPleaseIgnoreMe)-4,4
End Function

Мы с GSreg'ом в своё время немного поспорили чей вариант лучше. Вот, теперь вы можете сравнить сами.

Мне мой (AnyPtr) больше нравится, так как он универсальный. GSerg'у его, так как он (:)патологически?:)) не любит тип Variant.
С уважением, Approximator.

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

Сообщение tyomitch » 06.09.2004 (Пн) 13:28

AnyPtr имхо здесь не прокатит, т.к. не удастся так легко засунуть UDT в вариант. Хотя идея любопытная, буду иметь в виду.
VarPtr, с другой стороны, работает правильно - возвращает адрес самой структуры, а не копии. В крайнем случае, можно брать VarPtr от первого элемента.
Я проверял всё это в топике, где мы с Ennor-ом обсуждали вызов юникодных функций, посмотри там.
Последний раз редактировалось tyomitch 06.09.2004 (Пн) 13:31, всего редактировалось 1 раз.
Изображение

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

Сообщение tyomitch » 06.09.2004 (Пн) 13:29

CodeName33 писал(а):У меня в своё время так не прокатило. Он в VarPtr тоже передавал копию элемента и не давал адрес самого массива. Хотя может я и ошибаюсь...

Ошибаешься. VarPtr всё возвращает совершенно правильно.
Вот тестовая прога:
Код: Выделить всё
Option Explicit
Private Declare Function AnyPtr Lib "msvbvm60" Alias "VarPtr" (v As Any) As Long
Private Declare Function TypePtr Lib "msvbvm60" Alias "VarPtr" (v As NastyType) As Long

Type NastyType
    m1 As Byte
    m2 As String * 6
    m3 As String
End Type

Private t As NastyType
Sub Main()
    Debug.Print Len(t), LenB(t)
    Debug.Print VarPtr(t), VarPtr(t.m1)
    Debug.Print AnyPtr(t), TypePtr(t)
End Sub
Изображение

STanli
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 163
Зарегистрирован: 31.05.2004 (Пн) 15:22
Откуда: ТОМСК

Сообщение STanli » 06.09.2004 (Пн) 16:30

ничё у меня не получается =( дайте готовый пример
Раз, два, три, четыре, пять, с детства с рифмой я дружу.

Approximator
Постоялец
Постоялец
 
Сообщения: 572
Зарегистрирован: 26.06.2004 (Сб) 3:10

Сообщение Approximator » 08.09.2004 (Ср) 1:27

tyomitch писал(а):AnyPtr имхо здесь не прокатит, т.к. не удастся так легко засунуть UDT в вариант. Хотя идея любопытная, буду иметь в виду.
VarPtr, с другой стороны, работает правильно - возвращает адрес самой структуры, а не копии. В крайнем случае, можно брать VarPtr от первого элемента.
Я проверял всё это в топике, где мы с Ennor-ом обсуждали вызов юникодных функций, посмотри там.

:) Дык, Тёмыч, достаточно же было всего лишь пихать не в функцию, а в локальную переменную :)
Код: Выделить всё
Public Function <ИмяРек>(byref vAny as Variant)as Long
dim lRes as Long
<прежнее тело функции>
CopyMem VarPtr(lRes), VarPtr(vAny)+8,4
<ИмяРек>=lRes
End Function
С уважением, Approximator.

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

Сообщение tyomitch » 08.09.2004 (Ср) 11:51

Approximator, ты имхо не понял главного :-)
VarPtr здесь работает прекрасно, зачем ещё что-то изобретать?

И зачем и причём здесь локальная переменная - я тоже не понял.
Изображение

Approximator
Постоялец
Постоялец
 
Сообщения: 572
Зарегистрирован: 26.06.2004 (Сб) 3:10

Сообщение Approximator » 09.09.2004 (Чт) 1:29

tyomitch писал(а):Approximator, ты имхо не понял главного :-)
VarPtr здесь работает прекрасно, зачем ещё что-то изобретать?

Тогда проверь свою функцию на массиве элементы которого вот такие пользовательские типы:
Код: Выделить всё
Type MyType
Sa(1 to 2) as String
End Type

хотя, ладно, может и правда, тебе ни к чему универсальность...
С уважением, Approximator.

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

Сообщение tyomitch » 09.09.2004 (Чт) 14:25

1) Она не моя, она стандартная. Притом работает. А ты-то её проверял на своём типе? Я же готовый тестовый пример тремя постами выше привёл.
2) Мне вообще вся эта бадяга не нужна - я думал, мы STanli собирались помочь. Что именно нужно ему, пусть он решит сам :-)
Изображение

STanli
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 163
Зарегистрирован: 31.05.2004 (Пн) 15:22
Откуда: ТОМСК

Сообщение STanli » 09.09.2004 (Чт) 14:51

Мне надо чтобы удалятась переменная и всё здвигалось вот и всё =)
ЛУчьше не кодом а примерчиком.
Раз, два, три, четыре, пять, с детства с рифмой я дружу.

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

Сообщение tyomitch » 09.09.2004 (Чт) 14:54

Переменная - она какого типа?
Изображение

STanli
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 163
Зарегистрирован: 31.05.2004 (Пн) 15:22
Откуда: ТОМСК

Сообщение STanli » 09.09.2004 (Чт) 19:20

ДА их целый массив 1800 :!: штук а тип Byte
Раз, два, три, четыре, пять, с детства с рифмой я дружу.

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

Сообщение tyomitch » 09.09.2004 (Чт) 19:39

Если Byte, то просто возьми код из самого первого поста, и забей на эту дискуссию :-)
Изображение

STanli
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 163
Зарегистрирован: 31.05.2004 (Пн) 15:22
Откуда: ТОМСК

Сообщение STanli » 10.09.2004 (Пт) 14:19

CopyMem он вобще не воспринемает, я же говорю дайте готовый пример
Раз, два, три, четыре, пять, с детства с рифмой я дружу.

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

Сообщение tyomitch » 10.09.2004 (Пт) 15:34

Эх... По памяти пишу:
Код: Выделить всё
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (D As Any, S As Any, ByVal c As Long)
Изображение

STanli
Продвинутый пользователь
Продвинутый пользователь
Аватара пользователя
 
Сообщения: 163
Зарегистрирован: 31.05.2004 (Пн) 15:22
Откуда: ТОМСК

Сообщение STanli » 11.09.2004 (Сб) 16:41

Ещё не пробывал будет работать или нет но всё равно НУЖЕН готовый пример!!!!!!!!
Раз, два, три, четыре, пять, с детства с рифмой я дружу.

След.

Вернуться в Visual Basic 1–6

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

Сейчас этот форум просматривают: PetalBot, Yandex-бот и гости: 8

    TopList