Thread: Reading a file written by VB

  1. #1
    Registered User
    Join Date
    Jul 2002
    Posts
    5

    Reading a file written by VB

    I am by rights a VB programmer, and am trying to write a c++ routine to sort some data. I need help with trying to figure out:

    1) how to use VectorFromBstr, I added the oleauto.h file, but I still get undeclared identifier..

    2) how to write my custom compare function for qsort, listed far below, to compare each field of the type Patient..

    Before that, a little background:
    I have a file of patient data, written by the following VB type:
    Code:
    Type P1
        LName As String * 16   'last name
        FName As String * 12   'first name
        MName As String * 1    'middle initial
        BDate As String * 10    'birthdate
        NDate As String * 10    'next office visit
        Upi As Integer              'unique patient identifier
    End Type
    My VB program does not sort the records in the file, but instead loads the file contents into memory, and sort them, in memory. I then run through the sorted array of patient records, writing the UPI's to an index file.

    (bare with me here)
    As an example if I have three patients, John with UPI of 5343 , Brad with UPI of 9232, Tim with UPI of 2322, the array would be sorted, and index file would contain:
    9232
    5343
    2322

    OK, now, what I did above, I want to accomplish in C++, which is basically: open the patient file, read in the file, qsort the patients, and write the sorted UPI's(which are just integers) to file.

    So this is what I have so far:
    Code:
    typedef struct patient
    {
    BSTR Lname;
    BSTR Fname;
    char Mname;
    BSTR Bdate;
    BSTR Ndate;
    int Upc;
    }p;
    
    int cmp(const void*,const void *);
    int main(){
            struct patient *first,*a,*b;
            FILE *in,*out;
            int nelem;
            struct stat statbuf;
            struct stat *s;
            s=&statbuf;       
            in = fopen("patient.dat","rb");
            stat("patient.dat",s);
            first = (p*) malloc( s->st_size );
            fread(first,s->st_size,1,in);
            nelem = (int)(s->st_size / (long)sizeof(p) );
            qsort(first,nelem,sizeof(p),cmp );
            //need to modify code below to run through
            //struct array and write out only the UPI's of the
            //sorted array.
            out=fopen("patient_sorted.dat","wb");
            fwrite(first,sizeof(p),nelem,out);
            fclose(in);
            fclose(out);
            free(first);
    	return 0;
    }
    As you can see, I am using qsort... which I was advised to use to sort these. So here's my compare function:
    I need to compare the last names, if they are equal:
    compare the first names, if they are equal:
    compare middle initals, if equal:
    compare birthdates, if equal:
    compare UPI's (which are never equal),

    If any of the above are not equal, it returns a value to qsort.

    Custom compare function I wrote for qsort
    Code:
    int cmp(const void *a, const void *b){ //custom compare routine
        int j;
        char tmp[40],tmp1[40];
        char *working,*working1;
        struct patient *s;
        struct patient *t;
        zout(tmp);
        zout(tmp1);
        s = (struct patient*)a;
        //the below code converts bstr into a vector passing it
        //to safearray working?  But then how do I strcomp then?
        HRESULT i = VectorFromBSTR(s->Lname,working);
            
       //below code does the same as above code for 2nd patient
        t=(struct patient*)b;
        i = VectorFromBSTR(s->Lname,working1);
        j =strcmp( ? );
    
    	//compare last names
    	if j < 0 || j > 0  'if last names are not equal
    		return j;
    	if j == 0 
    	{
    		//compare first names
                                    //need code here to set tmp,tmp1 to fnames
                                    j=strcomp(tmp,tmp1)
    		if j < 0 || j > 0  'if first names are not equal
    			return j;
    		if j == 0
    		{
    			//compare middle initials
                                                     //need code here to set tmp,tmp1 to middleinitial
                                                    j=strcomp(tmp,tmp1)
    			if j < 0 || j > 0  'if middle init's are not equal
    				return j;
    			
    			if j == 0
    			{
    				//compare birthdates **the dates are stored as strings remember
    				//ie.  11/20/2000  or 02/31/1995
                                                                    //need code here to set tmp,tmp1 to bdates
                                                                    j=strcomp(tmp,tmp1)
    				if j < 0 || j > 0  'if birthdates's are not equal
    				return j;
    
    				if j == 0
    				{
    					//compare UPI (unique patient identifier, which is an integer)
    					//no two UPI's are the same, so one will
    					//always be greater or lesser than another
    					return j;	
    
    
    				}//end UPI comparison
    				}//end birthdate comparison
    			} // end middle initial comparison
    		}//end firstname comparison
    	} //end lastname compare 
    }//end custom compare function
    Last edited by nemaroller; 07-12-2002 at 01:49 PM.

  2. #2
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    You have way too much information to sort through there. I'm not talking about code either! What is your problem? You seem to be on the right track. Did you need to port this from VB? If not then don't lose sleep over this one.

  3. #3
    Registered User
    Join Date
    Jul 2002
    Posts
    5
    I want to port the VB code simply for learning more about C++ and for gettin a faster sorting time. As it stands, my app usually only databases at most 2,000 patients, and the VB app can do that in 1 second... but just for efficiency sake, and learning, I want to attach a C++ DLL, and call the sort routine to open the patient file, and write the sorted index back...

    My problem is how to use VariantFromBstr.. I used #include <oleauto.h>, but get an undeclared identifier on a line of code where I use it.

  4. #4
    Registered User raimo's Avatar
    Join Date
    Jun 2002
    Posts
    107
    Even a VB programmer should know that this is illogical:
    Code:
    if j == 0
    {
        //compare first names 
        if j < 0 || j > 0  'if first names are not equal
            return j;
            if j == 0
            {
    Why do you test the j to be zero for a second time if it cannot possibly have changed?

  5. #5
    Registered User
    Join Date
    Jul 2002
    Posts
    5
    if j == 0
    {
    //compare first names
    if j < 0 || j > 0 'if first names are not equal
    return j;
    if j == 0
    {
    --------------------------------------------------------------------------------

    Why do you test the j to be zero for a second time if it cannot possibly have changed?
    LOL, left it out by accident...

    Code:
    if j == 0
     {
         //compare first names
         //need code here  to set tmp, tmp1 to first name field
         j = strcomp(tmp, tmp1);
         if j < 0  || j > 0
            return j;
         
        if j == 0   //if they are equal, compare other fields
    j is the target of strcomp's return on each level of comparison. So if the last name's match, I set j = strcomp(fnames) , check j again...

    So, you see, it is logical.. I'm just not sure how I can get tmp,tmp1 to fnames, then middleinitials, birthdates, upi's, as necessary... but thanks for the reply at least. I have update the above code, so no one that assumes again...
    Last edited by nemaroller; 07-12-2002 at 01:50 PM.

  6. #6
    Registered User
    Join Date
    Jul 2002
    Posts
    5
    Maybe i should clarify this...

    Using an array of Patient structs... I need way I can point to the individual element's fields... so that I can throw them to the strcomp function and compare which comes first alphabetically.

    Array of struct Patient called P,

    compare p[0].lname with p[1].lname
    if equal, we need to check firstnames,

    compare p[1].fname with p[1].fname.
    if equal, we need to check middle initials...

    and so on..
    Last edited by nemaroller; 07-12-2002 at 02:01 PM.

  7. #7
    Banned master5001's Avatar
    Join Date
    Aug 2001
    Location
    Visalia, CA, USA
    Posts
    3,685
    Okay, if I were you I would go to google and look for a page that teaches VB programmers how to program C++. These kinds of tutorials a good because they tend to skip things like "Chapter 1 for loops" and other crap you already know. Next thing would be to read one or two docs on the win32 api. DLL's aren't really that complicated once you've done one but that first one is usually a killer. In the meanwhile, no one here is going to port your code for you. I can see that you do know what you are doing and can see that C++ shouldn't come too hard to you.

  8. #8
    Registered User
    Join Date
    Jul 2002
    Posts
    5
    I'm not looking for someone to port the code. I took a C++ class, and it covered everything about the basics, including vectors and pointers. I included the amount of information I did, so people could get a better idea of where I'm coming from, and what I'm trying to accomplish. I came to this forum for help and this is why:

    If I had written the patient file using character arrays, this would be easy. But as the title states, Reading a file written by VB. The problem is VB uses BSTRINGS. As soon as I have to use VariantFromBSTR, u have to understand, I am getting confused. So now I have a vector... which makes it difficult for me anyway, and obviously alot of people here, to point to the proper element in the vector.

    So if someone has the time, which someone at some point will, I could use help on how to properly pass the proper address...

    And also, help me figure out why C++ keeps returning an undeclared identifier when I try to use VariantFromBstr.... I included the necessary header, so it should recognize correct?
    Last edited by nemaroller; 07-12-2002 at 07:30 PM.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    1. Get yourself a hex editor, so you can view the contents of the file on a byte by byte basis, without any formatting, or danger of the editor blowing up due to funny characters. I'm guessing you probably have VC++, and I think the editor in there can cope with binary data.

    Use this to get an idea of what the VB record actually looks like when written to the file. Start with a small file (1 record only), containing known data.

    2. I've no idea what this BSTR thing is, but
    LName As String * 16 'last name

    could perhaps be
    char LName[16];

    3. When you think you've got the "typedef struct patient" sorted out, use it to write the same data as your VB program in step 1 to another file and compare the outputs on a byte level to ensure they are the same.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sequential file program
    By needhelpbad in forum C Programming
    Replies: 80
    Last Post: 06-08-2008, 01:04 PM
  2. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM