Удаление элемента из массива строк

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
krobab
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 08.06.2003 (Вс) 5:34

Удаление элемента из массива строк

Сообщение krobab » 12.10.2006 (Чт) 0:59

Здравствуйте.
Есть динамический массив строк,строки также не имеют определённого размера, надо удалить n-ый элемент из этого массива, прочитал статью ANDLL где описывается подобное, но там только для числовых и массивов структур.
Пробовал переделать пример под строку, но из этого ничего не получилось,кроме краха ВБ. Понял только то, что Я не правильно определяю размер памяти для строки.
Может быть кто-нибуть поможет решить эту проблему?
Зарание благодарен.

Matew
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 894
Зарегистрирован: 28.06.2004 (Пн) 17:44
Откуда: Дальний Восток, г. Ха

Сообщение Matew » 12.10.2006 (Чт) 1:26

krobab, в статье прекрасно расписано про строки. :?
Адд: Вот так должно работать
Код: Выделить всё
Option Explicit
Private Declare Sub CopyMemory Lib "KERNEL32" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Long)
Private Declare Sub ZeroMemory Lib "KERNEL32" Alias "RtlZeroMemory" (ByVal Destination As Long, ByVal numBytes As Long)
Dim n() As String
Private Sub Command1_Click()
Dim i  As Long
ShrinkArray_SecondType n(), 2
For i = 0 To UBound(n)
    Debug.Print n(i)
Next i
End Sub

Private Sub Form_Load()
    ReDim n(0 To 3)
    n(0) = "24728673"
    n(1) = "fdgsdfgdfgds"
    n(2) = "fgds11221"
    n(3) = "oipoizb23321"
End Sub
Private Sub ShrinkArray_SecondType(ByRef nArr() As String, ByVal nIndex As Long)
    If UBound(nArr) = nIndex Then
        ReDim Preserve nArr(nIndex - 1)
    Else
        If nIndex < LBound(nArr) Or nIndex > UBound(nArr) Then
            Err.Raise 10, , "Откуда такой индекс?"
        Else
            nArr(nIndex) = vbNullString
            'Смещаем все элементы
            CopyMemory VarPtr(nArr(nIndex)), VarPtr(nArr(nIndex + 1)), (UBound(nArr) - nIndex) * LenB(nArr(0))
            'Мы уже очистили последний элемент(см. выше). Так не дадим же VB еще что-нибыдь очистить!
            ZeroMemory VarPtr(nArr(UBound(nArr))), LenB(nArr(0))
            'Подтираем последний
            ReDim Preserve nArr(UBound(nArr) - 1)
        End If
    End If
End Sub


Алкоголь и сканеры-ваши враги! Не верите-смотрите аватару :-)

krobab
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 08.06.2003 (Вс) 5:34

Сообщение krobab » 12.10.2006 (Чт) 13:50

to Matew Нет не помогает.
После выолнения ZeroMemory ВБ вылетает.
У меня массив строк в структуре, а сама и переменная объявляющаяся как эта структура сама массив.
Код: Выделить всё
Type MyType
    a As Integer
    n() As String
End Type
private SomeType() as MyType

Вопрос, у Вас LenB(nArr(0)), а n(0) = "24728673" и вызов ShrinkArray_SecondType n(), 2, при этом
n(2) = "fgds11221", ведь у них разные размеры? или Я чего-то не понял?
Тут прочитал в МСДН`е,что
The Len function may not be able to determine the actual number of storage bytes required when used with variable-length strings in user-defined data types.

Получается, что если у меня строка в стурктуре, то lenb не даст правильный размер? Может из-за этого ВБ вылетает, и получается мне придётся переделывать код под простые массивы?

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 12.10.2006 (Чт) 13:55

а почему тебя обычная коллекция не устраивает :?:
или Dictionary из Scripting

krobab
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 08.06.2003 (Вс) 5:34

Сообщение krobab » 12.10.2006 (Чт) 14:24

Konst_One писал(а):а почему тебя обычная коллекция не устраивает :?:
или Dictionary из Scripting


Вы про класс Collection и Microsoft Scripting Runtime? У меня пользовательский тип,в нём те переменные которыемне нужны, и удалять мне надо только из масстива внутри типа, не думаю, что из-за этого надо создавать лишний класс.

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 12.10.2006 (Чт) 14:46

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

krobab
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 08.06.2003 (Вс) 5:34

Сообщение krobab » 12.10.2006 (Чт) 14:57

Вы мне предлагаете написать класс, в нем переменные те что в типе, добавить в класс функцию ShrinkArray_SecondType по примеру Matew и закинуть этот класс в коллекцию?
Или я не правильно Вас понял? Тогда можно пример?

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 12.10.2006 (Чт) 15:35

Код: Выделить всё
'MyColl Class
Option Explicit

'local variable to hold collection
Private mCol As Collection

Public Function Add(Key As Integer) As MyClass
    'create a new object
    Dim objNewMember As MyClass
    Dim a As Collection
    Set objNewMember = New MyClass
    Set a = New Collection

    'set the properties passed into the method
    objNewMember.Key = Key
    Set objNewMember.n = a
        mCol.Add objNewMember, CStr(Key)


    'return the object created
    Set Add = objNewMember
    Set objNewMember = Nothing
    Set a = Nothing

End Function

Public Property Get Item(vntIndexKey As Variant) As MyClass
    'used when referencing an element in the collection
    'vntIndexKey contains either the Index or Key to the collection,
    'this is why it is declared as a Variant
    'Syntax: Set foo = x.Item(xyz) or Set foo = x.Item(5)
  Set Item = mCol(vntIndexKey)
End Property



Public Property Get Count() As Long
    'used when retrieving the number of elements in the
    'collection. Syntax: Debug.Print x.Count
    Count = mCol.Count
End Property


Public Sub Remove(vntIndexKey As Variant)
    'used when removing an element from the collection
    'vntIndexKey contains either the Index or Key, which is why
    'it is declared as a Variant
    'Syntax: x.Remove(xyz)


    mCol.Remove vntIndexKey
End Sub


Public Property Get NewEnum() As IUnknown
    'this property allows you to enumerate
    'this collection with the For...Each syntax
    Set NewEnum = mCol.[_NewEnum]
End Property


Private Sub Class_Initialize()
    'creates the collection when this class is created
    Set mCol = New Collection
End Sub


Private Sub Class_Terminate()
    'destroys collection when this class is terminated
    Set mCol = Nothing
End Sub



Код: Выделить всё
'MyClass class
Option Explicit
Public Key As Integer   'ключ
Public n As Collection  'коллеция строк



Код: Выделить всё
Dim m as MyColl
Dim c as MyClass

Set m=New MyColl
set c=m.Add(1)
with c.n
.Add "1"
.Add "2"
.Add "3"
End with


...

'получить члена коллекции с индексом 1
Set c=m("1")
'а это его коллеция строк
Dim o as Collection
Set o=c.n

Debug.Print o.Count

krobab
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 08.06.2003 (Вс) 5:34

Сообщение krobab » 12.10.2006 (Чт) 16:59

to Konst_One О Спасибо !!! :D Вы натолкнули меня на одну мысль.
Я сначало не понял Ваш ответ, щас разобрался c Вашим кодом и сделал проще.

Код: Выделить всё
Private Type MyType
    n As Integer
    s As New Collection
End Type
dim MyTyp(4) as MyType

Всё работает как надо! ВБ больше не вылетает, пока придётся работать с таким типом.
to Matew попробуйте оставить 0 элемент массива как пустую строку.
Функция просто будет очищать элемент не смещая сам массив.

Kovu
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 924
Зарегистрирован: 29.04.2005 (Пт) 17:38

Сообщение Kovu » 12.10.2006 (Чт) 20:09

krobab
А ведь ANDLL мне в топике объяснял что для строк такой же как для лонгов размер...в поиск! :)
Если всё делать своими ручками, они скоро отвалятся !

Matew
Постоялец
Постоялец
Аватара пользователя
 
Сообщения: 894
Зарегистрирован: 28.06.2004 (Пн) 17:44
Откуда: Дальний Восток, г. Ха

Сообщение Matew » 13.10.2006 (Пт) 6:25

krobab, поменяй
Код: Выделить всё
CopyMemory VarPtr(nArr(nIndex)), VarPtr(nArr(nIndex + 1)), (UBound(nArr) - nIndex) * LenB(nArr(0))
на
Код: Выделить всё
CopyMemory VarPtr(nArr(nIndex)), VarPtr(nArr(nIndex + 1)), (UBound(nArr) - nIndex) * 4

Konst_One, Set c = m.Item("1") опечатка?
Алкоголь и сканеры-ваши враги! Не верите-смотрите аватару :-)

Konst_One
Член-корреспондент академии VBStreets
Член-корреспондент академии VBStreets
Аватара пользователя
 
Сообщения: 3041
Зарегистрирован: 09.04.2004 (Пт) 13:47
Откуда: Химки

Сообщение Konst_One » 13.10.2006 (Пт) 11:25

Matew
да нет, не опечатка, это получение члена коллекции по его ключу, а ключ у меня задается в методе Add коллекции:
Код: Выделить всё
mCol.Add objNewMember, CStr(Key)

krobab
Новичок
Новичок
 
Сообщения: 30
Зарегистрирован: 08.06.2003 (Вс) 5:34

Сообщение krobab » 13.10.2006 (Пт) 18:07

To Matew
Спасибо, тоже работает, вроде ещё не вылетело.

To Kovu
И Вам спасибо +), вот только Я вначале пытался искать в поиске, но похоже не заметил тему, попробую поискать по автору.

To Konst_One
Не только по ключу, но и по индексу :wink: . Я вообще думал, что коллекция хранит в себе только объекты, а оказывается что нет.

Всем Спасибо за помощь, тема закрыта.


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

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

Сейчас этот форум просматривают: Mail.ru [бот] и гости: 25

    TopList  
cron