Microsoft KB Archive/101258

= PRB: Compare User-Defined Type Variables w/ PEEK or _fmemcmp =

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  DIM x AS myType DIM y AS myType  x.f1 = "ab" x.f2 = 2 y = x  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

-

[mailto:TECHNET@MICROSOFT.COM Send feedback to Microsoft]

© Microsoft Corporation. All rights reserved.