| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 1832 人关注过本帖
标题:VB自定义数据类型的数组调用内部变量,如何做入子程序
只看楼主 加入收藏
lianyicq
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:26
帖 子:737
专家分:3488
注 册:2013-1-26
收藏
得分:0 
回复 9楼 donholy
当然不直接用变量名来操作数据,通过相对地址来操作。是不是有点象C的指针。

大开眼界
2015-06-01 14:08
donholy
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2015-5-27
收藏
得分:0 
回复 6楼 风吹过b
直接用出错。数组问题不好解决
图片附件: 游客没有浏览图片的权限,请 登录注册
2015-06-01 14:10
donholy
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2015-5-27
收藏
得分:0 
回复 11楼 lianyicq
这样就不是我们需要解决的问题了
2015-06-01 14:22
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
回复 12楼 donholy
所以要引入全局的模块
在全局模块里写过程,所以有些过程也必须放到全局模块中写成全局的过程。

这点是很烦的。限制有点多,比结构要多一点。

授人于鱼,不如授人于渔
早已停用QQ了
2015-06-01 16:25
lianyicq
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:26
帖 子:737
专家分:3488
注 册:2013-1-26
收藏
得分:0 
回复 13楼 donholy
没有正确理解,再给你写了一例.多琢磨
程序代码:
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Type StuSub
  Chinese As Integer
  Math As Integer
  English As Integer
  Physics As Integer
  Chemistry As Integer
End Type

Dim Stu(5) As StuSub
  Dim FirstAdd As Long
Private Sub Form_Load()

  Dim i As Integer
  FirstAdd = VarPtr(Stu(0))
  For i = 0 To 5
    Stu(i).Chinese = Int((150 - 70 + 1) * Rnd + 70)
    Stu(i).Math = Int((150 - 70 + 1) * Rnd + 70)
    Stu(i).English = Int((100 - 40 + 1) * Rnd + 40)
    Stu(i).Physics = Int((100 - 50 + 1) * Rnd + 50)
    Stu(i).Chemistry = Int((100 - 50 + 1) * Rnd + 50)
  Next
Calculate

End Sub

Sub Calculate()
  Dim temp As Integer
  Dim i As Integer, j As Integer
  Dim output(4) As Integer
  For j = 0 To 4
    For i = 0 To 50 Step 10
      Call CopyMemory(ByVal VarPtr(temp), ByVal FirstAdd + i + 2 * j, 2)
      output(j) = output(j) + temp
    Next
  Next
  For i = 0 To 4
    Text1.Text = Text1.Text & output(i) & vbCrLf
  Next
End Sub

 

大开眼界
2015-06-01 16:25
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
15楼 的代码。
一个结构的数据,在内存里就是顺序保存的。
如果你知道各个结构占用的内存长度(i = 0 To 50 Step 10),也知道首地址(FirstAdd = VarPtr(Stu(0)))
也知道每个字段占用内存长度(2),那就计算出具体字段所在的地址。
就可以把这个地址的内存复制出来。


按照你的代码,然后重写了函数,供 楼主参考 ,要求很严格的。
程序代码:
Option Explicit

'要求最好各个字段的数据是一样的,这里定义的是 long ,占4字节。一共是26个字段。
'如果每个字段占用的内存长度不一样,要么有函数计算到某个字段的长度,要么手动计算好长度后保存到一个数组中
'顺序一定不能错。
Private Type OutStatustype
    A_Value As Long
    B_Value As Long
    C_Value As Long
    D_Value As Long
    E_Value As Long
    F_Value As Long
    G_Value As Long
    H_Value As Long
    I_Value As Long
    J_Value As Long
    K_Value As Long
    L_Value As Long
    M_Value As Long
    N_Value As Long
    O_Value As Long
    P_Value As Long
    Q_Value As Long
    R_Value As Long
    S_Value As Long
    T_Value As Long
    U_Value As Long
    V_Value As Long
    W_Value As Long
    X_Value As Long
    Y_Value As Long
    Z_Value As Long
End Type
Private Const OutStatuslen = 4      '每个字段的长度,long=4 ,Integer=2

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

Private Const RecNum = 10                       '数据个数,可以为变量,这个示例就使用的常量
Private Outstatus(RecNum) As OutStatustype


Private Sub Command1_Click()
'示例
Dim k(RecNum) As Long

'调用,第一个是 需要取的字段的第一个字母,代表在结构体中的顺序号,第二个是 保存数据的数组
Call TestAll("B", k)

'显示取得的数据以及相临的数据
Dim i As Long
Cls
For i = 0 To RecNum
    Print k(i), Outstatus(i).A_Value, Outstatus(i).B_Value, Outstatus(i).C_Value
Next i

End Sub

Private Sub Form_Load()
Dim i As Long

'示例,初始化数据
For i = 0 To RecNum
    With Outstatus(i)
        .A_Value = Rnd() * 10000
        .B_Value = Rnd() * 10000
        .C_Value = Rnd() * 10000
        .D_Value = Rnd() * 10000
        .E_Value = Rnd() * 10000
        .F_Value = Rnd() * 10000
        .G_Value = Rnd() * 10000
        .H_Value = Rnd() * 10000
        .I_Value = Rnd() * 10000
        .J_Value = Rnd() * 10000
        .K_Value = Rnd() * 10000
        .L_Value = Rnd() * 10000
        .M_Value = Rnd() * 10000
        .N_Value = Rnd() * 10000
        .O_Value = Rnd() * 10000
        .P_Value = Rnd() * 10000
        .Q_Value = Rnd() * 10000
        .R_Value = Rnd() * 10000
        .S_Value = Rnd() * 10000
        .T_Value = Rnd() * 10000
        .U_Value = Rnd() * 10000
        .V_Value = Rnd() * 10000
        .W_Value = Rnd() * 10000
        .X_Value = Rnd() * 10000
        .Y_Value = Rnd() * 10000
        .Z_Value = Rnd() * 10000
    End With
Next i

End Sub


Private Sub TestAll(cs As String, data() As Long)
'字段名参数仅使用第一个字母。data 为接收数据的数组,VB默认是按地址传递,所以可以用数组把修改后的数据传递出去。
Dim a_start As Long, a_len As Long, address As Long
Dim i As Long
address = VarPtr(Outstatus(0).A_Value)              '首地址
a_start = (Asc(UCase(Left(cs, 1))) - 65) * OutStatuslen        '计算成,A=0,B=1 .. 的地址偏移
'a_len = 26 * OutStatuslen                           '每元素总长度
a_len = Len(Outstatus(0))                           '这是另一种取长度的方法,这种更精确

For i = 0 To RecNum
    Call CopyMemory(ByVal VarPtr(data(i)), ByVal address + i * a_len + a_start , OutStatuslen)       '把指定地址和数据复制到指定地址去
    'byval 传值 ,Varprt 取地址
Next i

End Sub

授人于鱼,不如授人于渔
早已停用QQ了
2015-06-01 17:56
风吹过b
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:364
帖 子:4947
专家分:30084
注 册:2008-10-15
收藏
得分:0 
Call CopyMemory(ByVal VarPtr(data(i)), ByVal address + i * a_len + a_start, OutStatuslen)        '把指定地址和数据复制到指定地址去
可以简化成:
    Call CopyMemory(data(i), ByVal address + i * a_len + a_start, OutStatuslen)        '把指定地址和数据复制到指定地址去

因为 VB默认是传址操作,在这个函数里,第一个我们需要的是地址,第二个需要的是值,所以第二个需要显式指出是传值。
第一个,如果我们取了地址,那也就要显式指出传值,没取地址,就可以使用默认的传地址。

授人于鱼,不如授人于渔
早已停用QQ了
2015-06-01 18:03
donholy
Rank: 1
等 级:新手上路
帖 子:14
专家分:0
注 册:2015-5-27
收藏
得分:0 
谢谢各位版主,现在明白原系统为什么那样编了——简单直观易于理解,虽然让人感觉过多重复。

尤其谢谢风吹过b,让我学到更多。
2015-06-02 03:37
快速回复:VB自定义数据类型的数组调用内部变量,如何做入子程序
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.040851 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved