Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Moving strings into UDTs

Status
Not open for further replies.

SteveJR

Programmer
Aug 13, 2001
72
GB
I was wondering if someone could help me with the following.

I want to overlay a string with a global type I have declared in a module i.e.

Str = abcdefghijkl

Public Type Steve
str1 as string * 3
str2 as string * 4
str3 as string * 5
End Type

Overlay type structure on string eg steve = str to get :

steve.str1 = abc
steve.str2 = defg
steve.str3 = hijkl

Does anyone know if this can be done?

Thanks.
 
Do you come from a C background? There is nothing comparable to this. The obvious way would be to use a function to initialise your type from the string.

Chaz
 
Chaz,

I do come from an object orient background but it is not C. It is a language that is used on Tandem/Compaq servers.

Do you know if any functions that could do this?

Cheers,

Steve
 
Oh , but you CAn do this. Very easily.

Option Explicit

Private Type Steve
str1 As String * 3
str2 As String * 4
str3 As String * 5
End Type

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



Private Sub Command1_Click()
Dim str As String
Dim mySteve As Steve
str = "abcdefghijkl"


CopyMemory mySteve, ByVal str, Len(str)

Debug.Print mySteve.str1
Debug.Print mySteve.str2
Debug.Print mySteve.str3

End Sub
 
StrongM,

I just done what you suggested and got a access violation exception!

Any ideas?

Steve
 
Did you just copy and paste the code, or type it in? Are you using W9X or NT4/W2000? And where does the error occur? I only ask because the exact code I quote in the example works 100% correctly here.

 

You can also use the LSET command...

Private Type Steve
str1 As String * 3
str2 As String * 4
str3 As String * 5
End Type

Private Type Buffer
str As String * 12
End Type

Private Sub Command1_Click()
Dim udtSteve As Steve
Dim udtBuffer As Buffer

udtBuffer.str = "abcdefghijkl"
LSet udtSteve = udtBuffer

Debug.Print udtSteve.str1
Debug.Print udtSteve.str2
Debug.Print udtSteve.str3

End Sub

 
StrongM,

I am using NT4.

I copied the CopyMemory Declare statement only. I already have a string and UDT set up in my code(The one in the question was just an example).

The error occurs on the Copymemory statement. I debugged it and it starts then the access violation happens.

Could it be that the string I am trying to place into the UDT is too big? The string also contains un-displayable characters in ebcdic. Should I convert the string to Hex before trying to move it?

Also, if the string len is less/greater than the UDT total len then will it fail?

Thanks,

Steve
 
JJames,

Thanks for the example. Unfortunately I can't use this as my UDT contains integer and varient datatypes aswell and the LSet command seems to only work on one datatype.

Thanks,

Steve
 
if it is greater than the UDT then you may/will have problems, since we are trampling all over memory locations with this call...

(if it is less than the size of the UDT there should not be an issue).

In essence, all CopyMemory does is copy a specified number of bytes (the third parameter) from the location pointed to by the second parameter to the block of memory pointed to by the first parameter.



 

You can use LSET with any data type (except variant but this would be a problem with copymemory also) as long as you use correct alignment...


Option Explicit

Private Type Steve
str1 As String * 3 '3 bytes
int1 As Integer '2 bytes - word aligned so xtra 2 bytes here
lng1 As Long '4 bytes
dte1 As Date '8 bytes
str2 As String * 3 '3 bytes
End Type
'15 unicode bytes


Private Type Buffer
str As String * 14 '6 + (16/2)
End Type

Private Sub Command1_Click()
Dim udtSteve As Steve
Dim udtBuffer As Buffer

With udtSteve
.str1 = "abc"
.int1 = 5
.lng1 = 55000
.dte1 = Now
.str2 = "end"
End With

LSet udtBuffer = udtSteve

Debug.Print udtBuffer.str


LSet udtSteve = udtBuffer

Debug.Print udtSteve.str1
Debug.Print udtSteve.int1
Debug.Print udtSteve.lng1
Debug.Print udtSteve.dte1
Debug.Print udtSteve.str2

End Sub
 
All,

Thanks for your help. The program is now up and running.

I figured out what I was doing wrong with the CopyMemory Statement - I missed out the ByVal keyword. I think I should get some glasses!

Thanks again for your help.

Steve
 
jjames,

late I know, but Lset does not work on UDT's with strings in them.
 
strongm,

I think jjames is correct. At least the demo thinnggyy works. It has SOME issues whith the number representation, but even these could be overcome with some num2str and str2num conversions at least as long as the structures of the strings were known. I have used this concept in reading/writing data to BTRieve files with the strange/ugly antique conversions for a couple of years and it is not a problem -as long as the string structure is known. Certainly, where there are NO numeric to fixed length string representation issues, the UDT and the string are easily interchangeable and provide a convenient transposition from the positional notation to a variable notation style for addressing the sub-strings. I have also used this approach (I believe it is almost the "STANDARD") for reading / writing fixed length records to a txet file on a disc.

MichaelRed
mred@att.net

There is never time to do it right but there is always time to do it over
 
it's only correct when you use Lset to copy one UDT to another UDT, and even then, if you use different types within the UDT, Microsoft warn against doing it.

jjames method only works because source and destination are both UDTs

Try running the following simple example, and see if you get an error...

[tt]
Option Explicit

Private Type SimpleUDT
Test As String * 10
End Type

Private Sub Command1_Click()
Dim mySimple As SimpleUDT
Dim strDummy As String
strDummy = Space(LenB(mySimple))
LSet strDummy = mySimple
End Sub
[/tt]
 
Perhaps we are discussing this from different perspectives. It is possible to move "stuff" from the string to the UDT and from the UDT to the string. Which specific set of instructions to use is dependent on the data types of the objects involved. To simpily move a string, LSet is not necessary or useful. The rather contrived procedures below merely illustrate A manner of moving a string to a UDT element and a string element of a UDT to a string. In this instance, the strings are of eqlau length, so positioning of the substring is irrelevant, however it could easily be accomodated.


Code:
Option Explicit

Private Type SimpleUDT
    Test As String * 10
End Type
'________________________________________________________
Public Function str2Udt()
    Dim mySimple As SimpleUDT
    Dim strDummy As String
    Dim Idx As Long
    mySimple.Test = String(10, "X")
    strDummy = Space(LenB(mySimple))
    For Idx = 1 To Len(strDummy)
        Mid(strDummy, Idx, 1) = Mid(mySimple.Test, Idx, 1)
    Next Idx
    Debug.Print strDummy
    'strDummy = mySimple
End Function
'__________________________________________________________

Public Function Udt2str()
    Dim mySimple As SimpleUDT
    Dim strDummy As String
    Dim Idx As Long
    strDummy = String(10, "X")
    For Idx = 1 To Len(strDummy)
         Mid(mySimple.Test, Idx, 1) = Mid(strDummy, Idx, 1)
    Next Idx
    Debug.Print mySimple.Test
End Function

MichaelRed
mred@att.net

There is never time to do it right but there is always time to do it over
 
On this occassion I don't think we're discussing from different perspectives at all. You've merely moved the goalposts. Obviously, if I have a UDT with a string element in it I can specifically reference that element and use normal string manipulation methods. In fact, since that is basically all that you are illustrating, the code you use can be simplified thus to remove any obfuscation:

Option Explicit
Private Type SimpleUDT
Test As String * 10
End Type
'________________________________________________________
Public Function str2Udt()
Dim mySimple As SimpleUDT
Dim strDummy As String
Dim Idx As Long
mySimple.Test = String(10, "X")
strDummy = mySimple.Test 'Simple.Test is just a string
Debug.Print strDummy
'strDummy = mySimple
End Function
'__________________________________________________________

Public Function Udt2str()
Dim mySimple As SimpleUDT
Dim strDummy As String
Dim Idx As Long
strDummy = String(10, "X")
mySimple.Test = strDummy
Debug.Print mySimple.Test
End Function

However, this bears no (or little) relationship to the original question, nor indeed as a clarification of the issues that arise from that original question.

My points have been simple:

1) Here's a solution that addresses your problem
2) LSet doesn't work like this

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top