Article ID: 101258
Article Last Modified on 8/16/2005
APPLIES TO
- Microsoft Visual Basic for MS-DOS
- Microsoft Cinemania 97 Standard 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 INFORMATION
WARNING: 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
Keywords: kbhowto kbprb KB101258