Thread: Need help.

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    69

    Need help.

    I have 2 txt files that I have converted to binary files. I need to take these two binary files merge them into one. The attempt I have made using a while loop created an endless loop. A fellow programer pointed out the error but not that I know what the problem is I have been unable to figure out a method that will successfully merge the two binary files. Here is the segment of code.
    Code:
    void mergeBinFiles(FILE* binFile1, FILE* binFile2, FILE** binOutFile)
    {
    //Local Declarations
    	INV_REC itemM1;
    	INV_REC itemM2;
    	INV_REC sentinel = {9999};
    	int mergeCnt = 0;
    //int fp1;
    //int fp2;
    		
    //Statements
                printf("\nBegin File Merge:\n");
                fread(&itemM1, sizeof(INV_REC), 1, binFile1);
    	if(feof(binFile1))
    	itemM1 = sentinel;
               fread(&itemM2, sizeof (INV_REC), 1, binFile2);
    	if(feof(binFile2))
    	itemM2 = sentinel;
    
              while((fgets(&itemM1, sizeof(INV_REC), binFile1) != NULL) ||
    	   (fgets(&itemM2, sizeof(INV_REC), binFile2) != NULL)) 
              {	
                   if(strcmp(itemM1.partNo, itemM2.partNo) >= 0)
    	{
    	fwrite(&itemM2, sizeof(INV_REC), 1, *binOutFile);
    	mergeCnt++;
    	fread(&itemM2, sizeof(INV_REC), 1, binFile2);
    	 if(feof(binFile2))
    	 itemM2 = sentinel;
    	}//if			 
                   else
    	{				 
    	 fwrite(&itemM1, sizeof(INV_REC), 1, *binOutFile);
    	  mergeCnt++;
    	 fread(&itemM1, sizeof(INV_REC), 1, binFile1);
    	 if(feof(binFile1))
    	 itemM1 = sentinel;
    	 }//else
                }//while
    	printf("\nFiles Merged. %d items merged.\n", mergeCnt);
    	system("Pause");
    	return;
    }//mergeBinFiles
    I now that the while statement is the problem. This is the original while statement:
    Code:
    while(!foef(binfile1) || !feof(binFile2))
    I learned that this doesn't work because it tests for the end of file indicator, not the stream itself. So my question is how can I correct the problem? I tried the above and I have tried this:

    Code:
    while(binFile1 != NULL || binFile2 != NULL)
    None of my solutions have corrected the problem and I am in need of some help. could someone help me please.

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    while(!foef(binfile1) || !feof(binFile2))
    Presumably you meant "feof", not "foef", but you're right about it not working.

    Code:
              while((fgets(&itemM1, sizeof(INV_REC), binFile1) != NULL) ||
    	   (fgets(&itemM2, sizeof(INV_REC), binFile2) != NULL))
    You're saying "while this file still has some data or that file still has some data". In other words, both files have to reach EOF for the loop to exit. I think you probably want "&&" instead, because you assume that both files were read from in your loop.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Registered User
    Join Date
    Nov 2007
    Posts
    69

    ok.

    changes || to &&
    Code:
    while((fgets(&itemM1, sizeof(INV_REC), binFile1) != NULL) &&
             (fgets(&itemM2, sizeof(INV_REC), binFile2) != NULL))
    reran compiler.

    These are errors I get now.

    Error messages. cpp(183) : error C2664: 'fgets' : cannot convert parameter 1 from 'INV_REC *__w64 ' to 'char *'
    1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

    : 'fgets' : cannot convert parameter 1 from 'INV_REC *__w64 ' to 'char *'
    1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

    : fatal error C1903: unable to recover from previous error(s); stopping compilation

    I reference a structure and I'm not sure how to resolve this problem?

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Oh, of course. fgets() reads strings. Since you're already using fread() and fwrite() to write structures, all that remains is for you to check the return values of these functions.

    fread(), for example, returns the number of items successfully written. Since you're writing one item at a time, something like this would work.
    Code:
    if(fread(&itemM2, sizeof(INV_REC), 1, binFile2) == 1) {
        /* success */
    }
    else {
        /* failure */
    }
    Notes: break; can be used to exit from a loop at any time, should you want it. Also, you can use sizeof() on a variable, which eliminates the possibility that you'll mess up the type.
    Code:
    fread(&itemM2, sizeof(itemM2), 1, binFile2);
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Registered User
    Join Date
    Nov 2007
    Posts
    69

    ok is this what I should do/

    Code:
    if(fread(&itemM1, sizeof(itemM1), 1, binFile1) == 1);
         if(feof(binFile1))
         itemM1 = sentinel;
    		
    
    if(fread(&itemM2, sizeof (itemM2), 1, binFile2)== 1);
         if(feof(binFile2))
         itemM2 = sentinel;
    		 
    while((fgets(&itemM1, sizeof(itemM1), binFile1) != NULL) &&
             (fgets(&itemM2, sizeof(itemM2), binFile2) != NULL))
    or would i eliminate the while statement with the if statements before the read. Am unsure if this is what you meant.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    if(fread(&itemM1, sizeof(itemM1), 1, binFile1) == 1);
         if(feof(binFile1))
         itemM1 = sentinel;
    First: that red semicolon would mess you up.

    Now, keep in mind what these functions do.
    • feof(): checks for EOF without reading anything. Only useful directly after a function call that actually reads something.
    • fread(): reads data from a binary file. Returns number of items successfully read.
    • fgets(): reads a string from a text file.

    You only need one of those functions: fread. feof() checks for EOF, but you know that anyway by looking at fread()'s return value. fgets() is for reading strings, which you don't want at all.

    What I would do is this. Every time you call fread(), check its return value. If the return value isn't 1, you have reached the end of the file. How you handle that is up to you. You only need a loop if you want to keep reading from a file until you reach the end of the file; and if you did use a loop, you'd use it in conjunction with fread.
    Code:
    while(fread(...) == 1) {
        /* ... */
    }
    Does that answer your question? . . . .

    And another thing: try indenting your code properly. It really helps. cpwiki.sf.net/Indentation
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  7. #7
    Registered User
    Join Date
    Nov 2007
    Posts
    69

    this I know.

    I tried eliminating the while statement. This created many more problems. So I put it back in but how do I get my while statement to do what it is I want it to do. I understand the fgets reads a string and I have working with strings and numbers. What is it that I'm not realizing? How do I format the while statement so that it will work?

  8. #8
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    First, I'm going to indent your code (with "indent -kr") because I couldn't read it at all. Oh, and codeform it too.
    Code:
    void mergeBinFiles(FILE * binFile1, FILE * binFile2, FILE ** binOutFile)
    {
    //Local Declarations
        INV_REC itemM1;
        INV_REC itemM2;
        INV_REC sentinel = { 9999 };
        int mergeCnt = 0;
    //int fp1;
    //int fp2;
    
    //Statements
        printf("\nBegin File Merge:\n");
        fread(&itemM1, sizeof(INV_REC), 1, binFile1);
        if (feof(binFile1))
    	itemM1 = sentinel;
        fread(&itemM2, sizeof(INV_REC), 1, binFile2);
        if (feof(binFile2))
    	itemM2 = sentinel;
    
        while ((fgets(&itemM1, sizeof(INV_REC), binFile1) != NULL) ||
    	   (fgets(&itemM2, sizeof(INV_REC), binFile2) != NULL)) {
    	if (strcmp(itemM1.partNo, itemM2.partNo) >= 0) {
    	    fwrite(&itemM2, sizeof(INV_REC), 1, *binOutFile);
    	    mergeCnt++;
    	    fread(&itemM2, sizeof(INV_REC), 1, binFile2);
    	    if (feof(binFile2))
    		itemM2 = sentinel;
    	}			//if                    
    	else {
    	    fwrite(&itemM1, sizeof(INV_REC), 1, *binOutFile);
    	    mergeCnt++;
    	    fread(&itemM1, sizeof(INV_REC), 1, binFile1);
    	    if (feof(binFile1))
    		itemM1 = sentinel;
    	}			//else
        }				//while
        printf("\nFiles Merged. %d items merged.\n", mergeCnt);
        system("Pause");
        return;
    }				//mergeBinFiles
    See, there's lots of stuff going on there that I wasn't really aware of . . . .

    First thing: you don't want to use fgets(). It reads strings. You're trying to merge two binary files, so fgets() has no place here.

    Now, it looks like your loop doesn't actually have to read anything at all. fread() before and inside the loop takes care of the file reading.

    Maybe what you want is this.
    Code:
    while(itemM1 != sentinel && itemM2 != sentinel)
    You already detect EOF and set itemM1 and/or itemM2 to sentinel when one of the files reaches its end. All you have to do is continue until both of the files have ended.

    Note: you can't use strcmp() on numbers. I'm guessing INV_REC::partNo is a number, because you initialize sentinel with 9999. Just use plain old
    Code:
    if (itemM1.partNo >= itemM2.partNo) {
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  9. #9
    Registered User
    Join Date
    Nov 2007
    Posts
    69

    Many thanks.

    I really appreciate your explianation. I now see the problem and I appreciate your help. It have a few bugs to work out of the rest of the program but that was the biggie.

    Thank you again. If I should have any more questions do you mind if I ask?
    Thank You again...

  10. #10
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Thank you again. If I should have any more questions do you mind if I ask?
    Fire away. It's what we do best -- answer questions. Sorry I took so long to do a full examination of your code . . . .

    Good luck with programming.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  11. #11
    Registered User
    Join Date
    Nov 2007
    Posts
    69

    Fixed the merge problem. Have a new one.

    I corrected the merge problem but now there is a read problem with my binOutFile.

    this part of the code is to read the merged bin file and prepare it to be printed. Here is the code.

    Code:
    /*============================getDataB====================================
    		This function reads the binary file.
    		  Pre: Bin file is opened for reading
    		  Post: warehouse Inventory List read and returned.
    */
    INV_REC getDataB (FILE *binOutFile)
    {
        //Local declarations
             int ioResult;
             INV_REC stkList;
    
       //Statements
            ioResult = fread(&stkList, sizeof(stkList), 1, binOutFile);
            if(!ioResult)
            if(!feof(binOutFile))
               {
               printf("\nError reading binOutFile.\n");
               system("Pause"), exit(501);
               }//if !feof
           return stkList;
    }//getdataB
    Get the error message within the if statement. Not sure why? Please help.

  12. #12
    Registered User
    Join Date
    Nov 2007
    Posts
    69
    No problem. I just appreciate the help. I have been working on this code for a while and I thought I had it then when I open the report it was empty. It was kind of like starting over from the start. It was hard.

    I want you to know how much I appreciate your help.

  13. #13
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Mmm, that's good, I was a bit stumped.

    Also look at this:
    Code:
            if(!ioResult)
            if(!feof(binOutFile))
               {
               printf("\nError reading binOutFile.\n");
               system("Pause"), exit(501);
               }//if !feof
    What you're saying is: "if no items were read from the file, then: if the end of the file has not been reached, then: print an error . . . ."

    In other words, you shouldn't have a ! on that feof. Come to think of it, you can just use this:
    Code:
            if(!ioResult)
               {
               printf("\nError reading binOutFile.\n");
               system("Pause"), exit(501);
               }//if !feof
    [edit]
    I want you to know how much I appreciate your help.
    You're welcome. Thanks are appreciated. [/edit]
    Last edited by dwks; 03-21-2008 at 02:55 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  14. #14
    Registered User
    Join Date
    Nov 2007
    Posts
    69

    I see.

    I deleted the line of code recompiled then debugged. I am still recieving the error message.

    Code:
    INV_REC getDataB (FILE *binOutFile)
    {
       //Local declarations
    	  int ioResult;
    	  INV_REC stkList;
    
       //Statements
    	  ioResult = fread(&stkList, sizeof(stkList), 1, binOutFile);
    	  if(!ioResult)
    	   {
    	     printf("\nError reading binOutFile.\n");
    	     system("Pause"), exit(501);
    	    }//if !ioResult
    	 return stkList;
    }//getdataB

  15. #15
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Code:
    ioResult = fread(&stkList, sizeof(stkList), 1, binOutFile);
    You're trying to read from an output file, judging from its name at least.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed