Форум программистов, компьютерный форум, киберфорум
testuser2
Войти
Регистрация
Восстановить пароль

Изменение размерностей массива 1D, 2D в любых пределах

Запись от testuser2 размещена 14.06.2024 в 13:50
Показов 137 Комментарии 0
Метки vb, vba

Visual Basic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
Option Explicit
#If Win64 Then
    Private Const ptrSz As LongPtr = 8
#Else
    Private Const ptrSz As Long = 4
#End If
Private Type SAFEARRAYBOUND
    cCount              As Long
    lBound              As Long
End Type
Private Type SAFEARRAY
    cDims               As Integer
    fFeatures           As Integer
    cbElements          As Long
    cLocks              As Long
    #If Win64 Then
      unused            As Long
    #End If
    pvData              As LongPtr
End Type
Private Type SAFEARRAY2D
    Hdr                 As SAFEARRAY
    Bounds(1)           As SAFEARRAYBOUND
End Type
Private Declare PtrSafe Sub CopyPtr Lib "kernel32.dll" Alias "RtlMoveMemory" (Dst As Any, Src As Any, Optional ByVal Size As LongPtr = ptrSz)
Private Declare PtrSafe Sub SafeArrayAllocDescriptor Lib "oleaut32.dll" (ByVal cDims As Long, ppsaOut As LongPtr)
Private Declare PtrSafe Sub SafeArrayDestroyDescriptor Lib "oleaut32.dll" (ByVal pSA As LongPtr)
Private Declare PtrSafe Function GetProcessHeap Lib "kernel32.dll" () As LongPtr
Private Declare PtrSafe Function HeapReAlloc Lib "kernel32.dll" (ByVal hHeap As LongPtr, ByVal dwFlags As Long, ByVal lpMem As LongPtr, ByVal dwBytes As LongPtr) As LongPtr
Private Declare PtrSafe Function HeapSize Lib "kernel32.dll" (ByVal hHeap As LongPtr, ByVal dwFlags As Long, ByVal lpMem As LongPtr) As LongPtr
Private Const HEAP_ZERO_MEMORY = &H8
 
Private Sub TestChangeArrayDims()
    Dim Arr$()
    ReDim Arr(0 To 19)
    Arr(2) = 222
    Stop
    ChangeArrayDims Arr, 1, 20
    Stop
    ChangeArrayDims Arr, 1, 20, 1, 1
    Stop
    ChangeArrayDims Arr, 1, 1, 1, 20
    Stop
    ChangeArrayDims Arr, 0, 19, 0, 0
    Stop
    ChangeArrayDims Arr, 1, 20, 1, 2
    Stop
End Sub
 
Private Sub ChangeStrArrayDims(sArr() As String, ByVal Lb1 As Long, ByVal Ub1 As Long, _
            Optional ByVal Lb2 As Long = -1, Optional ByVal Ub2 As Long = -1, Optional ByVal Rllc As Boolean)
    Dim SA As SAFEARRAY2D, pArr As LongPtr
    
    CopyPtr pArr, ByVal VarPtr(Lb1) - ptrSz           'получаем указатель массива
    
    ChangeArrayDims_ pArr, Lb1, Ub1, Lb2, Ub2, SA, Rllc
End Sub
Private Sub ChangeArrayDims(vArr, ByVal Lb1 As Long, ByVal Ub1 As Long, _
            Optional ByVal Lb2 As Long = -1, Optional ByVal Ub2 As Long = -1, Optional ByVal Rllc As Boolean)
    Dim SA As SAFEARRAY2D, pArr As LongPtr, vt%
    CopyPtr vt, vArr, 2
    If vt < &H4000 Then 'isVariant = True             'получаем указатель массива
        pArr = VarPtr(vArr) + 8
    Else
        CopyPtr pArr, ByVal VarPtr(vArr) + 8
    End If
    ChangeArrayDims_ pArr, Lb1, Ub1, Lb2, Ub2, SA, Rllc
End Sub
Private Sub ChangeArrayDims_(ByVal pArr As LongPtr, ByVal Lb1 As Long, ByVal Ub1 As Long, _
                              ByVal Lb2 As Long, ByVal Ub2 As Long, SA As SAFEARRAY2D, ByVal Rllc As Boolean)
    Dim ptSA As LongPtr, ptSA2 As LongPtr, tmpSA As SAFEARRAY, hHeap As LongPtr
    Dim newSize As LongPtr, curSize As LongPtr, Cnt1D&, Cnt2D&
    
    CopyPtr ptSA, ByVal pArr                          'получение указателя дескриптора массива Safearray
    CopyPtr ByVal VarPtr(Ub2) + ptrSz, ptSA           'устанавливаем указатель SA на дескриптор массива
    If SA.Hdr.cDims > 2 Then Exit Sub                 'поддерживаются только 1D и 2D массивы
    
    hHeap = GetProcessHeap
    curSize = HeapSize(hHeap, 0, SA.Hdr.pvData)       'текущий размер блока данных
    Cnt1D = Ub1 - Lb1 + 1
    If Lb2 < 0 Then                                   'если не заданы параметры 2й размерности
        newSize = Cnt1D * SA.Hdr.cbElements           'вычисляем требуемый размер блока данных
        GoSub ReAlloc                                 '~ Redim Preserve
        SA.Hdr.cDims = 1
        SA.Bounds(0).lBound = Lb1
        SA.Bounds(0).cCount = Cnt1D
    Else                                              'если заданы параметры 2й размерности
        If SA.Hdr.cDims <> 2 Then                     'если массив не 2D (а 1D) переделываем его н 2D
            LSet tmpSA = SA                           'сохраняем параметры дескриптора 1D массива
            SafeArrayAllocDescriptor 2, ptSA2         'создаем новый дескриптор массива размерности 2D
            CopyPtr ByVal VarPtr(Ub2) + ptrSz, ptSA2  'устанавливаем указатель SA на новый дескриптор массива
            LSet SA = tmpSA                           'восстанавливаем сохраненные параметры массива
            CopyPtr ByVal pArr, ptSA2                 'назначаем массиву новый 2D дескриптор
            SafeArrayDestroyDescriptor ptSA           'уничтожаем старый 1D дескриптор
            SA.Hdr.cDims = 2
        End If
        Cnt2D = Ub2 - Lb2 + 1
        newSize = Cnt1D * Cnt2D * SA.Hdr.cbElements   'вычисляем требуемый размер блока данных
        GoSub ReAlloc
        SA.Bounds(0).lBound = Lb2                     'устанавлииваем заданные 1D и 2D размерности
        SA.Bounds(0).cCount = Cnt2D
        SA.Bounds(1).lBound = Lb1
        SA.Bounds(1).cCount = Cnt1D
    End If
Exit Sub
ReAlloc:                                              'перераспределяем блок данных согласно требуемого размера
    Select Case True
    Case newSize > curSize, Rllc                      'HEAP_ZERO_MEMORY - заполнение нулями добавленного объема
        SA.Hdr.pvData = HeapReAlloc(hHeap, HEAP_ZERO_MEMORY, SA.Hdr.pvData, newSize)
    End Select
Return
End Sub
Метки vb, vba
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Трассировка корутин Kotlin с OpenTelemetry
mobDevWorks 14.07.2025
Асинхронное программирование меняет правила игры, особенно когда речь заходит о трассировке операций. В Kotlin с его корутинами эта проблема приобретает особый оттенок, который я хотел бы детально. . .
Облачные приложения на Rust: руководство по архитектуре микросервисов
golander 13.07.2025
Когда я впервые взялся за проектирование облачной платформы для одного из наших клиентов, выбор стоял между привычными Go и Java. Но после нескольких месяцев разработки микросервисной системы,. . .
Как Node.js выполняет асинхронные операции
Reangularity 13.07.2025
Каждый раз, когда я рассказываю про Node. js, возникает один и тот же вопрос: "Как эта штука может быть быстрой, если JavaScript — однопоточный язык?" И это действительно кажется парадоксом. Ведь в. . .
Как писать чистый, тестируемый и качественный код на Python
py-thonny 12.07.2025
Помню свой первый проект на Python. Работал тогда быстро, грязно, лишь бы работало. Код был похож на запутанный клубок - переменные по одной букве, функции на 200 строк, комментарии отсутствовали как. . .
Blazor и контроллер сервопривода IoT Meadow Maple
Wired 11.07.2025
Я решил разобраться, как можно соединить современные веб-технологии с миром "железа". Интересная комбинация получилась из Blazor в качестве веб-интерфейса и микроконтроллера Meadow с его веб-сервером. . .
Генерация OpenQASM из кода Q#
EggHead 10.07.2025
Летом 2024-го я начал эксперименты с библиотекой Q# Bridge, и знаете что? Она оказалась просто находкой для тех, кто работает на стыке разных квантовых экосистем. Основная фишка этой библиотеки -. . .
Изучаем новый шаблон ИИ-чата .NET AI Chat Web App
stackOverflow 10.07.2025
В . NET появилось интересное обновление - новый шаблон ИИ-чата под названием . NET AI Chat Web App. Когда я впервые наткнулся на анонс этого шаблона, то сразу понял, что Microsoft наконец-то. . .
Результаты исследования от команды ARP (июль 2025 г.)
Programma_Boinc 10.07.2025
Результаты исследования от команды ARP (июль 2025 г. ) Африканский проект по дождям (ARP) World Community Grid снова запущен! Мы рады поделиться обновленной информацией о нашем прогрессе с осени. . .
Angular vs Svelte - что лучше?
Reangularity 09.07.2025
Сегодня рынок разделился на несколько четких категорий: тяжеловесы корпоративного уровня (Angular), гибкие универсалы (React), прогрессивные решения (Vue) и новая волна компилируемых фреймворков. . .
Code First и Database First в Entity Framework
UnmanagedCoder 09.07.2025
Entity Framework дает нам свободу выбора, предлагая как Code First, так и Database First подходы. Но эта свобода порождает вечный вопрос — какой подход выбрать? Entity Framework — это. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru