?
Solved

How to create an array from a string using MoveMemory function.

Posted on 2003-03-14
20
Medium Priority
?
562 Views
Last Modified: 2010-04-07
Hi,
I have a very big text containing over 30000 characters. And i want to know how to create an array from that string. It's not reasonable to use Mid$() function due to low speed.

for example;
Dim strTxt   as string
dim strArr() as string

strTxt = Text1.Text
....
How to make an array from this text..
I want to analyse each of the characters. (Japanese or Roman)
0
Comment
Question by:bsavas
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 3
  • 3
  • +6
20 Comments
 
LVL 11

Expert Comment

by:rdrunner
ID: 8136743
What do you want in each array element ?

One or two bytes?
0
 

Expert Comment

by:RichBisset
ID: 8136886
you could use Split() function if there are certain characters you can seperate the string by (ie ;)

if not then you probably dont have much choice using something like

=======
dim myArray(2000) as string

intStringLen = len(strMainString)  'strMainString being your 300000 char string

intChunkSize = intStringLen / 2000  'calculate the size of each string piece to add into each array cell

for i = 0 to intChunkSize - 1
     myArray(i) = left(strMainString, intChunkSize)
     tempStr = right(strMainString, len(strMainString) - intChunkSize 'Truncate the main string each time
next
=======

probably be v slow though!
0
 

Expert Comment

by:RichBisset
ID: 8136898
there should be another line before the 'next' statement:

strMainString = tempStr
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 11

Expert Comment

by:rdrunner
ID: 8136911
Ok it works now ;)

here is the code :

Private Sub Command4_Click()
Dim ar1() As dblByte
Dim cLine As String
cLine = "Test for strings in VB"
ReDim ar1(Len(cLine))
CopyMemory ByVal VarPtr(ar1(0)), ByVal StrPtr(cLine), Len(cLine) * 2
DoEvents
End Sub
'definitions:
Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
Public Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (Destination As Any, ByVal Length As Long)
Public Type dblByte
    Hi As Byte
    Lo As Byte
End Type
0
 
LVL 11

Expert Comment

by:rdrunner
ID: 8136970
P.s: It also works if you use a Integer as datatype (For the array ar1)..

To get the character for each letter back you just do

Debug.Print Chr$(ar1(0))

0
 
LVL 3

Expert Comment

by:phildaley
ID: 8137384
You could use a dynamic byte array.

Example:
Dim b() as byte
Dim s as string

s="abc...30000 chars"
b=s

b(0) will be 97 (ascii 'a')
b(1) will be 0
b(2) will be 98 (ascii 'b')
b(3) will be 0

etc.

You will get 2 bytes per char in string in unicode systems, hence the 0 after each char.

Hence to access the nth char, you use b(((n-1) * 2))

0
 
LVL 38

Expert Comment

by:PaulHews
ID: 8137464
This is also very fast:

Option Explicit

Private Sub Command1_Click()
    Dim strText As String
    Dim bytArr() As Byte
    Dim strArr() As String
    Dim i As Long
    Dim sngTime As Single
   
    sngTime = Timer
   
    strText = String(30000, "X")
    bytArr = StrConv(strText, vbFromUnicode)
    ReDim strArr(0 To UBound(bytArr))
    For i = 0 To UBound(bytArr)
        strArr(i) = Chr(bytArr(i))
    Next i
    MsgBox Timer - sngTime & " s"
   
End Sub
0
 
LVL 11

Expert Comment

by:rdrunner
ID: 8137558
About very Fast ... ;)

I measured your way vs my way with a slightly bigger string (300K)

Result :
Your way       My way    
 0,28125       0

I made the string bigger since at 30 K i got 0 for my Version... At 300K it still returns 0 *evilgrin*

'Snipp to test

Private Sub Form_Load()
   
   Dim cLine As String
   Dim bytArr() As Byte
   Dim strArr() As String
   Dim i As Long
   Dim sngTime As Single
   Dim nTotal1 As Single
   Dim nTotal2 As Single
   Dim ar1() As Integer
   sngTime = Timer
   
   cLine = String(300000, "X")
   bytArr = StrConv(cLine, vbFromUnicode)
   ReDim strArr(0 To UBound(bytArr))
   For i = 0 To UBound(bytArr)
       strArr(i) = Chr(bytArr(i))
   Next i
   nTotal1 = Timer - sngTime
   sngTime = Timer
   
   ReDim ar1(Len(cLine))
   CopyMemory ByVal VarPtr(ar1(0)), ByVal StrPtr(cLine), Len(cLine) * 2
   
   nTotal2 = Timer - sngTime
   
   Debug.Print nTotal1, nTotal2
   
End Sub
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 8137623
Right and where do you produce an array of strings, as asked in the question, using your method?  If I leave it as a byte array there is only a small difference between your method and mine at len = 300000, which is about 3x larger than the original question asked for.

Option Explicit
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (Destination As Any, ByVal Length As Long)

Private Sub Form_Load()
 
  Dim cLine As String
  Dim bytArr() As Byte
  Dim strArr() As String
  Dim i As Long
  Dim sngTime As Single
  Dim nTotal1 As Single
  Dim nTotal2 As Single
  Dim ar1() As Integer
  sngTime = Timer
 
  cLine = String(300000, "X")
  bytArr = StrConv(cLine, vbFromUnicode)
  ReDim strArr(0 To UBound(bytArr))
'  For i = 0 To UBound(bytArr)
'      strArr(i) = Chr(bytArr(i))
'  Next i
  nTotal1 = Timer - sngTime
  sngTime = Timer
 
  ReDim ar1(Len(cLine))
  CopyMemory ByVal VarPtr(ar1(0)), ByVal StrPtr(cLine), Len(cLine) * 2
 
  nTotal2 = Timer - sngTime
 
  Debug.Print nTotal1, nTotal2
 
End Sub

Output on a few runs:
1.146875E-02  0.00975
 0.0091875    0.011375
 9.90625E-03   0.0081875
 0.0113125    9.59375E-03

0
 
LVL 11

Expert Comment

by:rdrunner
ID: 8137750
Ok ;)

I didnt convert to string ....Thats where it costs a lot of time ...


0
 
LVL 1

Expert Comment

by:ARMC
ID: 8137781
You can use split Command For exapmle:
Dim A() as Byte
Dim B as string
Dim I as Long
Redim A(Len(b)-1)
For i= 1 to len(B)
  A(i-1)=asc(mid(B,I,1))
Next i
0
 
LVL 38

Expert Comment

by:PaulHews
ID: 8137792
Of course if it's Japanese, a conversion to single byte is not going to be nice.  Maybe integer array makes more sense.
0
 

Author Comment

by:bsavas
ID: 8142187
Hi RdRunner,
Thanks for your code. It's the nearest code that satisfied me. But, here is the problem;

'definitions:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (Destination As Any, ByVal Length As Long)
'Private Type dblByte
'   Hi As Byte
'   Lo As Byte
'End Type


Private Sub Form_Load()

    Dim ar1() As Integer
    Dim cLine As String
    cLine = "Test for strings in VB"

    ReDim ar1(Len(cLine))
    CopyMemory ByVal VarPtr(ar1(0)), ByVal StrPtr(cLine), Len(cLine) * 2
    DoEvents
   
End Sub

! This works good with ANSI characters. But what i want is to copy Japanese characters and analyze them one by one. I mean i'll code like after copying Japanese characters into the array;

 for x= 0 to len(Japanese_String)
   if ar1(x) = something... then ...
 next x

so the code above doesnt show japanese characters...
0
 
LVL 11

Expert Comment

by:rdrunner
ID: 8142215
Well i THOUGHT Japanese chars would be 2 byte per character...

Try to output

debug.? chrW(ar1(x))

This should output the character correctly...

I dont know how Japanese characters are stored so i am not quite sure about it... If its Unicode it should work... (i hope)

Well after all i am german and a-z usually do the trick for me ;)
0
 

Author Comment

by:bsavas
ID: 8142220
Hi RdRunner,
Thanks for your code. It's the nearest code that satisfied me. But, here is the problem;

'definitions:
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDest As Any, pSrc As Any, ByVal ByteLen As Long)
Private Declare Sub ZeroMemory Lib "kernel32.dll" Alias "RtlZeroMemory" (Destination As Any, ByVal Length As Long)
'Private Type dblByte
'   Hi As Byte
'   Lo As Byte
'End Type


Private Sub Form_Load()

    Dim ar1() As Integer
    Dim cLine As String
    cLine = "Test for strings in VB"

    ReDim ar1(Len(cLine))
    CopyMemory ByVal VarPtr(ar1(0)), ByVal StrPtr(cLine), Len(cLine) * 2
    DoEvents
   
End Sub

! This works good with ANSI characters. But what i want is to copy Japanese characters and analyze them one by one. I mean i'll code like after copying Japanese characters into the array;

 for x= 0 to len(Japanese_String)
   if ar1(x) = something... then ...
 next x

so the code above doesnt show japanese characters...
0
 
LVL 3

Expert Comment

by:phildaley
ID: 8144846
I am now totally confused as to what is trying to be achieved. The original question was to convert a long string to an array for analyis because Mid was too slow.

Well I've just tried the following code:

Dim s As String

Private Sub Command1_Click()
    Dim t As Single
    Dim l As Long
    Dim c As String
   
    t = Timer
    For l = 1 To Len(s)
        c = Mid(s, l, 1)
    Next
    Debug.Print Timer - t
End Sub

Private Sub Command2_Click()
    Dim t As Single
    Dim l As Long
    Dim b() As Byte
    Dim c As String
   
    t = Timer
    b = s
    For l = 1 To Len(s)
        c = chr(b((l - 1) * 2))
    Next
    Debug.Print Timer - t
End Sub

Private Sub Form_Load()
    Dim l As Long
   
    For l = 0 To 25
        s = s & String(100000, Asc("a") + l)
    Next
End Sub

This uses a far longer string than requested, and on my AMD 1700+ machine it takes just under 1 sec for both methods (actually on average Mid takes very slightly less time).

So, my advice would be to stop complicating the issue and just use Mid
0
 

Author Comment

by:bsavas
ID: 8146162
Well, no need to be complicated. Simply, all i want is to make an array from a Japanese text string using CopyMemory function...(No ANSI chars)
The code of RdRunner above works well and fast with ANSI chars. But i want it to be for Japanese characters.
0
 

Expert Comment

by:CleanupPing
ID: 9056316
bsavas:
This old question needs to be finalized -- accept an answer, split points, or get a refund.  For information on your options, please click here-> http:/help/closing.jsp#1 
EXPERTS:
Post your closing recommendations!  No comment means you don't care.
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 9699693
bsavas, an EE Moderator will handle this for you.
Moderator, my recommended disposition is:

    Refund points and save as a 0-pt PAQ.
    *** useful techniques shown, but DBCS question was not answered.

DanRollins -- EE database cleanup volunteer
0
 
LVL 1

Accepted Solution

by:
Computer101 earned 0 total points
ID: 9756536
PAQed, with points refunded (250)

Computer101
E-E Admin
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

When trying to find the cause of a problem in VBA or VB6 it's often valuable to know what procedures were executed prior to the error. You can use the Call Stack for that but it is often inadequate because it may show procedures you aren't intereste…
This article describes some techniques which will make your VBA or Visual Basic Classic code easier to understand and maintain, whether by you, your replacement, or another Experts-Exchange expert.
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses
Course of the Month11 days, 4 hours left to enroll

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question