例如我有个数组
    Dim MyArr() As String
    ReDim MyArr(1)
    MyArr(0) = "aa"
    MyArr(1) = "bb"
    Erase MyArr'这里进行这个操作后如何在下面判断该数组已经为空了我用过几个方法:
               1.在"Erase MyArr"这里做个标识,下面援用一下
               2.用SafeArrayGetDim这个API
               3.用CopyMemory这个API
我的问题:
          用CopyMemory的时候要用个VarPtrStringArray,关键是这个东西要自己添加Lib库(这是别的地方看到的说法),
          不好用,请问如何方便的用上CopyMemory?或者有没有别的方法来判断动态字符串数组是否为空?

解决方案 »

  1.   

    Option ExplicitSub Main()
        Dim MyArr() As String
        Debug.Print IsArraryEmpty(MyArr)
        
        ReDim MyArr(1)
        MyArr(0) = "aa"
        MyArr(1) = "bb"
        Debug.Print IsArraryEmpty(MyArr)
        
        Erase MyArr
        Debug.Print IsArraryEmpty(MyArr)
    End SubFunction IsArraryEmpty(ByVal arr As Variant) As Boolean
        Dim bHasDims As Boolean
        
        On Error Resume Next
        bHasDims = (LBound(arr) <= UBound(arr))
        On Error GoTo 0
        
        IsArraryEmpty = Not bHasDims
    End Function
      

  2.   

    如果只判断字符串数组,如下声明效率更高
    Function IsArraryEmpty(ByRef arr() As String) As Boolean
      

  3.   

    嗯,这样的方法倒也比较简洁可行
    请问CopyMemory这个API方便用吗?我也是看到西西同学的帖子想起这么个问题的
      

  4.   

    突然想到是不是可以利用一下split的特性,自己写个Erase?下面的代码测试是可以的:Sub myErase(s() As String)
        Erase s
        s = Split(vbNullString)
    End SubPrivate Sub Command1_Click()
        Dim a() As String
        '........
        myErase a
        Debug.Print UBound(a)
    End Sub
      

  5.   

    CopyMemoy 的灵活性是最容易导致错误,有 SafeArrayGetDim 用更好,做好的 tlb 可以重复使用,并且不用随 exe 一起发布,并不麻烦。
      

  6.   

    用copymemory 也行,而且效率可能更好看我原文 http://www.cnblogs.com/pctgl/articles/1540556.html
    获取安全数组的信息,包括安全数组结构内的所有数据
    本来用结构做的话,更方便,但会增加代码量,而且用起来也会麻烦些,所以就用了N多变量了
    有兴趣的朋友可以再改改Private Function GetSafeArrayInfo(AnyArray As Variant, Optional sDimension As Integer, Optional LowerBound As Long, Optional UpperBound As Long, Optional Elements As Long, Optional Flags As Integer, Optional cbElements As Long, Optional cLocks As Long, Optional AddressOfData As Long) As Long
    '**************************************************************
    '*
    '*  数组头地址 = GetSafeArrayInfo(数组 ,[维数],[下标],[上标],[元素个数],[属性],[元素长度],[锁定计数],[首元素地址])
    '*
    '*  result:  成功返回数组头地址;  返回 0 代表这是一个未被初始化过的数组
    '*
    '*  note:    除第1个参数外,均为输出型参数,要获取数组的什么信息,传入相应的变量,执行后,变量的值即为相应的数组数据
    '*
    '*           要获取多维数组的非第1维的上/下标,应按照下面的方法调用
    '*
    '*           GetSafeArrayInfo (数组, 指定一个维数,[下标],[上标]
    '*
    '**************************************************************    Dim ArrayHeaderAddress  As Long
        Dim DimensionCount As Integer     '维数计次    CopyMemory ArrayHeaderAddress, ByVal VarPtr(AnyArray) + 8, 4
        CopyMemory ArrayHeaderAddress, ByVal ArrayHeaderAddress, 4              '获取数组头地址
       
        If ArrayHeaderAddress < 1 Then Exit Function    CopyMemory DimensionCount, ByVal ArrayHeaderAddress, 2                  '获取数组维数    If sDimension > DimensionCount Then Exit Function                       '若指定的维数大于实际维数则退出    CopyMemory LowerBound, ByVal (ArrayHeaderAddress + 16 + (DimensionCount - sDimension) * 8) + 4, 4 '获取下标
        CopyMemory Elements , ByVal (ArrayHeaderAddress + 16 + (DimensionCount - sDimension) * 8), 4                                                   '获取指定维数下的元素个数
        UpperBound = Elements + LowerBound - 1                                '获取指定维数下的上标
       
        CopyMemory Flags, ByVal ArrayHeaderAddress + 2, 2                       '获取数组属性
        CopyMemory cbElements, ByVal ArrayHeaderAddress + 4, 2                  '获取数组单个元素长度
        CopyMemory cLocks, ByVal ArrayHeaderAddress + 8, 2                      '获取数组锁定计数
        CopyMemory AddressOfData, ByVal ArrayHeaderAddress + 12, 2              '获取数组首元素地址
       
        GetSafeArrayInfo = ArrayHeaderAddress
     
    End Function
     
      

  7.   

    Function IsArraryEmpty(ByRef arr() As String) As Boolean我就用这个
      

  8.   

    9 楼代码先不说调用 API 的效率,根本没有考虑:地址超过 2G,SAFEARRAY**
      

  9.   

    整数不用区分是否包含符号,特别是整数内存地址值的copy
    copymemory 的效率没的说, 那个函数如果不做那么多的无用功,效率肯定比你的 isarrayempty 要好的多
      

  10.   

    我的是字符串动态数组,刚试了下你这个,第一次直接崩溃.
    后来  VarPtr 这个用不了,网上倒是提供了一种方法VarPtrStringArray,不过这个要自己做个tlb,我是嫌麻烦没有做,等下去试试.
    谢谢大家的关注!
      

  11.   

    我一般也是用SafeArrayGetDim,最可靠。
      

  12.   

    http://topic.csdn.net/u/20090829/12/B2931277-B973-48F5-8BF2-117F80897F2E.html
      

  13.   

    ls 我相信算法, 我相信 api 的算法过程和算法高人做的算法过程是没法比的
    但我觉得是否迷信api,对我来说简直是在开玩笑
    对于功能性api来讲,他的效率一般的vb代码是比不了的
      

  14.   


    学习
    不过好像有关于这方面的API函数。
      

  15.   

    Private Sub Command1_Click()
        On Error Resume Next
        Dim MyArr() As String
            
        ReDim MyArr(1)
        MyArr(0) = "aa"
        MyArr(1) = "bb"
        Erase MyArr '这里进行这个操作后如何在下面判断该数组已经为空了
        MyArr(0) = MyArr(0)
        If Err.Number = 9 Then
           Debug.Print "数组已经为空"
        End If
            
    End Sub
      

  16.   

    再给你一个方法看看,不用出错处理,也不用API:Private Sub Command1_Click()
        Dim MyArr() As String
        ReDim MyArr(1)
        MyArr(0) = Empty
        MyArr(1) = Empty
        Erase MyArr '这里进行这个操作后如何在下面判断该数组已经为空了,可以注释掉这句再看看
        Dim iFlag As String
        iFlag = Join(MyArr, ",")
        If Len(iFlag) = 0 Then 
           Debug.Print "该数组内存已释放"
        Else
           Debug.Print "该数组内存未释放"
        End If
        
    End Sub
      

  17.   

    其实最简单,最容易掌握还是 copymemory
    将copymemory 声明的第2个参数改成数组型, 比如 srcArray() as anydim m() as byte
    dim i as long 
    copymemory i , m,4
    if i then msgbox "已初始化数组" else msgbox "未初始化数组"判断是否为空数组,我的程序中就是这样做的,不过这样做会导致字符串数组的 ansi 转换
    所以,一般我只用到非字符串数组上
      

  18.   

    觉得大家的心思挺不错,加分go on
      

  19.   

    Private Sub Form_Load()
    Dim m(1) As Byte
    Dim i As Long
    i = StrPtr(m)
    If i Then 
        MsgBox "已初始化数组" 
    Else 
        MsgBox "未初始化数组"
    end if
    End Sub
      

  20.   

    s = join(arr,vbnullstring)
    if lenb(trim(s)) = 0 then
    debug.print "empty"
    end if
      

  21.   

    Option Explicit
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
    Private Declare Function ArrayPtr Lib "msvbvm60.dll" Alias "VarPtr" (Destination() As String) As LongPrivate Sub Form_Load()
    Dim m(1) As String
    Dim i As Long
    i = ArrayPtr(m)
    CopyMemory i, ByVal i, 4If i Then MsgBox "已初始化数组" Else MsgBox "未初始化数组"
    End Sub
      

  22.   

    我的是动态字符数组,你试试我的条件,貌似你这样不可以的
        Dim m() As String
        Dim i As Long
        i = StrPtr(m)
        ReDim m(1)
        m(0) = "1"
        m(1) = "111"
        Erase m'这里注释了再看看
      

  23.   

    跟27楼的类似,不过你这里是vbnullstring,感觉似乎更可取
      

  24.   

    Private Sub Form_Load()
        Dim m() As String
        Dim i As Long    ReDim m(1)
        m(0) = "1"
        m(1) = "111"
        Erase m '这里注释了再看看
    i = ArrayPtr(m)
    CopyMemory i, ByVal i, 4If i Then MsgBox "已初始化数组" Else MsgBox "未初始化数组"
    End Sub
      

  25.   

    其实你去关注西西那个CopyMemory帖子就很容易找到答案的
      

  26.   

    经测试,不好使;
    其实之前我就是这么用的
    我在网上看了下,说是要用到VarPtrStringArray这个
      

  27.   

    貌似帖子的分增加了,我想多弄点dim m() as byte
    dim i as long
    copymemory i , m,4
    if i then msgbox "已初始化数组" else msgbox "未初始化数组"lz 啊这个是可以用来测试字符串数组的,虽然他有 ansi的转换,但却是不影响结果的
    Private Function GetSafeArrayInfo(AnyArray As Variant) As Long    Dim ArrayHeaderAddress  As Long
        CopyMemory ArrayHeaderAddress, ByVal VarPtr(AnyArray) + 8, 4
        CopyMemory ArrayHeaderAddress, ByVal ArrayHeaderAddress, 4              '获取数组头地址
        GetSafeArrayInfo =  ArrayHeaderAddress
    end function
    。。   这个你们都觉得一点好处都没有的东西,其实很强 他可以禁止字符串数组的ansi转换
    为什么那么做的原因就在于此,不过两次的 copymemory 总归没有一次的 copymemory快就这样lz 问的是 copymemory 实现测试空数组, 我的答案最符合lz的问题了
      

  28.   

    就拿我的例子,给点代码我测下试试?
        Dim m() As String 
        Dim i As Long     ReDim m(1) 
        m(0) = "1" 
        m(1) = "111" 
        Erase m '这里注释了再看看
      

  29.   


    Option Explicit
    Private Declare Sub GetArrayHeader Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source() As Any, ByVal Length As Long)
    Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)Private Sub Command1_Click()
        Dim m() As String
        Dim i As Long
        ReDim m(1)
        m(0) = "1"
        m(1) = "111"
        Erase m '这里注释了再看看
        
        GetArrayHeader i, m, 4        ' 纯 copymemory 实现
        Debug.Print iEnd SubPrivate Sub Command2_Click()
        
        Dim m() As String
        Dim i As Long
        ReDim m(1)
        m(0) = "1"
        m(1) = "111"
        Erase m '这里注释了再看看
        
        i = GetSafeArrayInfo(m)      '禁止字符串数组的 ansi 转换实现
        Debug.Print i
    End SubPrivate Function GetSafeArrayInfo(AnyArray As Variant) As Long
        Dim ArrayHeaderAddress  As Long
        CopyMemory ArrayHeaderAddress, ByVal VarPtr(AnyArray) + 8, 4
        CopyMemory ArrayHeaderAddress, ByVal ArrayHeaderAddress, 4              '获取数组头地址
        GetSafeArrayInfo = ArrayHeaderAddress
    End Function
    为了我亲爱的分,写个完整的给你,你自己去测试吧, debug.print 显示 0 ,说明是空数组,非0不是
    那个 erase 你想测试什么?注释和反注释的效果你去测试吧,你还想怎么测试都随便你添加代码
      

  30.   

    小结:
    2,4,7,10,27,43楼的方法都可用;
    2L,4L---错误处理
    7L---split
    10L---SafeArrayGetDim
    27L---join
    43L---Copymemory 25,34楼 作了优化.7楼和27楼别开生面,很好用,不过稍有缺憾.
      

  31.   

    测了,就是把你的copy一下,不管Erase m这句是否注释掉都是一样,"未初始化数组"
    i始终为0