PRB: Compare User-Defined Type Variables w/ PEEK or _fmemcmp (101258)
The information in this article applies to:
- Microsoft Visual Basic for MS-DOS
- Microsoft Cinemania for Windows 1993 edition
- Microsoft QuickBASIC 4.0
This article was previously published under Q101258 SYMPTOMS
An attempt to use the relational operators (=, <>, and so on) to compare
user-defined type variables results in a "Type mismatch" error.
CAUSE
The relational operators do not support the comparison of user-defined type
variables.
RESOLUTION
This article discusses two alternative methods for comparing user-defined
type variables.
The first method compares user-defined type variables by converting the
variables to strings, and then comparing the strings. It uses PEEK, VARPTR,
and CHR$ to convert the user-defined type variable to a string.
The second method uses the C function _fmemcmp to compare two user-defined
type variables. This second method is much faster than the first,
particularly when comparing large (up to 64k in size) user-defined type
variables. In addition, the second method avoids "out of string space"
errors which can occur with the first method and it can be modified to
compare arrays of numeric, fixed length strings or user-defined types up
to 64k in size.
STATUS
This behavior is by design.
MORE INFORMATIONWARNING: One or more of the following functions are discussed in this article; VarPtr, VarPtrArray, VarPtrStringArray, StrPtr, ObjPtr. These functions are not supported by Microsoft Technical Support. They are not documented in the Visual Basic documentation and are provided in this Knowledge Base article "as is." Microsoft does not guarantee that they will be available in future releases of Visual Basic.
When comparing user-defined type variables, you can check to see if they
are Equal or Not Equal ('=' or '<>'), but don't attempt to use the other
relational operators (<, >, <=, >=) unless the user-defined type variable
contains fixed length strings. This behavior is due to how numeric
variables are stored and how these functions accomplish their comparisons.
These methods treat the numeric variables as unsigned numbers and because
the negative sign is stored in the most significant bit of a numeric
variable, comparing positive and negative numbers would result in the
negative number being seen as greater than the positive number.
Method One
The following example program demonstrates how to compare user-defined
type variables by converting the variables to strings:
DECLARE FUNCTION type2str$ (t AS ANY)
TYPE myType
f1 AS STRING * 2
f2 AS SINGLE
END TYPE
<BR/><BR/>
DIM x AS myType
DIM y AS myType
<BR/><BR/>
x.f1 = "ab"
x.f2 = 2
y = x
<BR/><BR/>
IF type2str(x) = type2str(y) THEN
PRINT "x = y"
ELSE
PRINT "x <> y"
END IF
y.f1 = "ba"
IF type2str(x) > type2str(y) THEN
PRINT "x > y"
ELSE
PRINT "x < = y"
END IF
'
' type2str converts a user-defined type variable to a string.
'
FUNCTION type2str$ (t AS myType)
DEF SEG = VARSEG(t) ' In case the variable is in a dynamic array.
FOR i% = 0 TO LEN(t) - 1
s$ = s$ + CHR$(PEEK(VARPTR(t) + i%))
NEXT
DEF SEG
type2str = s$
END FUNCTION
Method Two
The _fmemcmp function takes three parameters. The first two parameters
are far pointers to the memory buffers it compares, and the third
parameter is the number of bytes to check. The function returns a value
to be tested against zero:
- If the value is zero (0), the two buffers are equal.
- If the value is greater than zero (0), buffer1 is greater than buffer2.
- If the value is less than zero (0), buffer1 is less than buffer2
To use the function, link your compiled Basic program with the medium or
large model C library (MLIBCE.LIB or LLIBCE.LIB) of the appropriate
version; that is, use Microsoft C version 5.1 for Microsoft Quickbasic
version 4.50, use Microsoft C version 6.0 for Microsoft Basic PDS version
7.10, and use Microsoft C version 7.0 for Microsoft Visual Basic for
MS-DOS version 1.0.
If you want to run this program inside the Visual Basic for MS-DOS
environment, use the following code to build a library and quicklibrary:
LIB MLIBCE.LIB*FMEMCMP.OBJ; ' extract fmemcmp object
LIB MLIBCE.LIB*DIFFHLP.OBJ; ' and a support object
LIB TYPECOMP.LIB+FMEMCMP.OBJ+DIFFHLP.OBJ; ' build new library
LINK /Q TYPECOMP.LIB,TYPECOMP.QLB,,VBDOSQLB.LIB; ' build quicklib
' use QBXQLB.LIB
' for Basic PDS or
' BQLB45.LIB for QB45
Then invoke Visual Basic for MS-DOS with the /L switch to load the new
quicklibrary:
VBDOS /L TYPECOMP
Below is a Basic program that calls the C _fmemcmp function. Note that
the underscore character (_) is used as a line continuation character
and should not be used inside the Visual Basic for MS-DOS environment:
DEFINT A-Z
' Declare the C function
DECLARE FUNCTION TypeCmp% CDECL ALIAS "__fmemcmp" _
(SEG buf1 AS ANY, SEG buf2 AS ANY, BYVAL Length%)
CONST max = 1000
TYPE RecType ' Set Up the User Defined Type
CustID AS INTEGER
AcctCode AS LONG
Memo AS STRING * 6
Dates(1 TO max) AS STRING * 10
END TYPE
CLS
DIM Rec1 AS RecType ' Dimension 2 variables
DIM Rec2 AS RecType
Rec1.CustID = 2 ' Initialize first record
Rec1.AcctCode = 42356
Rec1.Memo = "mojoho"
FOR i = 1 TO max
Rec1.Dates(i) = "Test" + STR$(i)
NEXT i
Rec2 = Rec1 ' Initialize second record
result% = TypeCmp%(Rec1, Rec2, LEN(Rec1)) ' Compare the records:
IF result% <> 0 THEN ' if result% = 0, Rec1 = Rec2
PRINT "Not Equal" ' if result% > 0, Rec1 > Rec2
ELSE ' if result% > 0, Rec1 < Rec2
PRINT "Rec1 = Rec2"
END IF
Rec2.Memo = "toasty" ' Change information in 2nd record
result% = TypeCmp%(Rec1, Rec2, LEN(Rec1)) ' Compare
IF result% <> 0 THEN ' Print result
PRINT "Not Equal"
ELSE
PRINT "Rec1 = Rec2"
END IF
END
This program prints the following output:
Rec1 = Rec2
Not Equal
Modification Type: | Minor | Last Reviewed: | 8/16/2005 |
---|
Keywords: | kbhowto kbprb KB101258 |
---|
|