Thread: Is this an EOF problem ?

  1. #1
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154

    Is this an EOF problem ?

    I have this struct
    Code:
    typedef struct
    {
     int  salary;
     char id[9];
     char name[12];
     char surname[15];
     char origin[15];
    }record;
    and i also have a binary file that includes records as the above.
    I want to make a function to delete records with the desired ID. My idea was to zero those blocks of memory and write them back to bin file, so look what i've done :
    Code:
    void SO_deleteRecord(FILE *IO)
    {
     int recsNum;
     char id[9];
     char toCmp[recSize];
    
     record tempRec;
    
    
          //Initialize
          rewind(IO);
          recsNum = 0;
          memset(toCmp,0,recSize);
    
          //Interface to read id
          printf("\n\nInsert ID : ");
          getStr(id,9);
          while(checkStr(id,ALN))
          {
            printf("ID should be consisted of letters and numbers.\n");
            printf("Insert ID : ");
            getStr(id,9);
          }
    
          puts("\n");
    
          //Search for this record
          while(fread(&tempRec,1,recSize,IO) == recSize)
          {
            if((memcmp(&tempRec,toCmp,recSize) != 0)&&(strcmp(tempRec.id,id) == 0))
            {
              //Set all block to 0
              memset(&tempRec,0,recSize);
    
              //Move back one record
              fseek(IO,-recSize,SEEK_CUR);
    
              //Write it back to file
              fwrite(&tempRec,1,recSize,IO);
    
              printf("%d record with ID = %s has been deleted.\n",++recsNum,id);
            }
          }
    
          puts("\n");
    
          //If no record found
          if(recsNum == 0)
            printf("Record with ID = %s hasn't been found.\n\n",id);
    }
    My algorithm follows those steps :
    1 While you can read from file (not EOF)
    2 If record isn't empty (zero bytes)
    3 Turn it to zero bytes and then
    4 Move file pointer back one record (to write to the specific position)
    5 Write the empty block (zero bytes) to file

    The problem is in the bold text and especially is that the loop runs for ever if the record is located near the end.

    If the record is located near the beginning it works fine, so i suppose the problem is the end of file.

    Any ideas whats wrong ?

    Thanks in advance !!

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I don't think this is an EOF issue.
    Throw a printf in at the beginning of the loop to see what data it is reading:
    Code:
    while(fread(&tempRec,1,recSize,IO) == recSize)
          {
    printf("->%s<-\n",tempRec.id); fflush(stdout);
            if((memcmp(&tempRec,toCmp,recSize) != 0)&&(strcmp(tempRec.id,id) == 0))
            {
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154
    Quote Originally Posted by MK27 View Post
    I don't think this is an EOF issue.
    Throw a printf in at the beginning of the loop to see what data it is reading:
    I did that and it prints a range of records all the time.
    ex

    .....
    ID : N111111
    Surname : PAPPAS
    Name : PETER
    Origin : BOSTON
    Salary : 19169

    ID : Z111111
    Surname : DIMAS
    Name : KOSTAS
    Origin : ATHENS
    Salary : 15724

    ID : F111111
    Surname : TSARTA
    Name : MARIA
    Origin : THIVA
    Salary : 11478

    .....

    But every time those records are different.

    Extra question : while(fread(&tempRec,1,recSize,IO) == recSize) shouldn't terminate loop when reach the end of file anyway ?

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by ch4 View Post
    Extra question : while(fread(&tempRec,1,recSize,IO) == recSize) shouldn't terminate loop when reach the end of file anyway ?
    Definitely it would terminate the loop at EOF. I don't see why your loop doesn't work the way you want, since altho while you set the file pointer back, it should end up at the end after writing.

    You said in the OP that the loop "runs forever"; presumably the number of records is not infinite, so can you not tell from the debug content (ie the printf) of the loop what it is actually doing?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154
    It's actually prints the message in the loop "XXXX record with ID = * has been deleted" and the bin file is getting bigger and bigger.

  6. #6
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154
    Look my search function which is working fine.

    Code:
    void SO_searchRecord(FILE *IO)
    {
     int recsNum;
     char id[9];
     char toCmp[recSize];
    
     record tempRec;
    
    
          //Initilize
          recsNum = 0;
          rewind(IO);
          memset(toCmp,0,recSize);
    
          //Interface
          printf("\nInsert the ID of the record to search for : ");
          getStr(id,9);
          while(checkStr(id,ALN))
          {
            printf("ID should be consisted of letters and numbers.\n");
            printf("Insert ID : ");
            getStr(id,9);
          }
    
          printf("\nRecord(s) found with ID %s : ",id);
    
          //Start to search
          while(fread(&tempRec,1,recSize,IO) == recSize)
          {
            if((memcmp(&tempRec,toCmp,recSize) != 0)&&(strcmp(tempRec.id,id) == 0))
            {
              puts("\n");
              fprintf(stdout,"-------%d-------\n",++recsNum);
              fprintf(stdout,"ID : %s \n",tempRec.id);
              fprintf(stdout,"Surname : %s \n",tempRec.surname);
              fprintf(stdout,"Name : %s \n",tempRec.name);
              fprintf(stdout,"Origin : %s \n",tempRec.origin);
              fprintf(stdout,"Salary : %d \n",tempRec.salary);
            }
          }
    
          //If no record found
          if(recsNum == 0)
            puts("None\n");
    }
    It's working the same way !!!!

  7. #7
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by ch4 View Post
    It's actually prints the message in the loop "XXXX record with ID = * has been deleted" and the bin file is getting bigger and bigger.
    Oops! It sounds like fwrite is appending the data, so by moving back, you insert an empty record in front of the one you meant to zero out. Over and over again.

    I actually haven't done this for sure so I can't give you a tested solution*. Maybe start a new thread and ask how to use fwrite to overwrite rather than append; it might be as simple as an argument to fopen().

    Probably you want to write a short test program using a throw away file while you figure this overwrite vs. insert issue out.

    *or at least I don't remember this issue
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  8. #8
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154
    Yes thats true !!!
    You're amazing on finding the problem, but how to overwrite ??

    I'll google it and if no result i'll create a new thread.

    Thanks MK27 you rock !!!

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is how I overwrite a binary record:

    I don't understand why you would want to write out an empty record. Mark it deleted, and go on.

    Code:
    /***************************************************************************/
    
    void delSR()
    
    {
       record stud;
       fpos_t filepos;
       int ch, j=0;
       long long int num;
       clrscr();
       rewind(fp);
       gotoxy(35,2);printf("\n\nDELETE STUDENT RECORD. Enter student to be deleted.");
       printf("\n\nStudent number   = ");
       scanf("%lld", &num);
    
       while( fread (&stud,sizeof(stud),1,fp) )
       {
          if(num==stud.snum)
          {
             j++;
             printf("\n\nStudent found: \n\n");
             printf("\nStudent number    =  %lld", stud.snum);
             printf("\nPassword          =  %s", stud.password);
             printf("\nName              =  %s, %s %s", stud.lname, stud.fname, stud.mi);
             printf("\nBirthdate         =  %s", stud.bday);
             printf("\nCourse            =  %s", stud.course);
    
    
             printf("\n\n\nAre you sure you want to delete the above student record(s)? Y if yes\n\n");
             ch=toupper(getche());
    
             if(ch=='Y')
             {
                filepos = ftell(fp);
                filepos -= sizeof(stud);
                fseek(fp,filepos,SEEK_SET);
                stud.snum = -1;  //indicating a deleted record
                fwrite(&stud,sizeof(stud),1,fp);
    
                printf("\n\nStudent record deleted... ");
             }
             else
                printf("\n\nNo Record Deleted...");
          }
       } 
       if(j == 0)
          printf("\n\nThat Record Was Not Found...");
       getch();
    
    }
    The actual data isn't changed, except the -1 value that is put into the field for student number.

    After many deletions, if the additions don't "take up" enough records, then your program can compress the data, and eliminate all or most of the deleted records (your choice).

    It's good to have some empty records though.

    If you'd like to see the pseudo code for the compression function, let me know.
    Last edited by Adak; 05-02-2009 at 11:44 AM.

  10. #10
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154
    Fortunately i had to do one exercise with two different ways.
    The first one i've already finished, works the same with your idea, namely i use three $ for an empty (useless) record by using strcpy(tempRec.id,"$$$") and write it back to file.

    But i have to do the same exercise with one more different way, so i decided to use zero blocks and now i can't write empty blocks and that's why they appended and not overwritten.

    To sum up, thank you for your reply and if you have a new idea to accomplish my exe let me now please.

  11. #11
    Registered User ch4's Avatar
    Join Date
    Jan 2007
    Posts
    154
    [SOLVED]

    I've tried the same code in a linux machine (Ubuntu 8.10) and works perfect.

    Previous the code had been compiled in a solaris machine and gcc hadn't been updated to the latest version, so i suppose that was the problem.

    [/SOLVED]

    Thank everyone

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. small reference problem
    By DavidP in forum C++ Programming
    Replies: 6
    Last Post: 06-21-2004, 07:29 PM
  2. Problem with destructors.
    By Hulag in forum C++ Programming
    Replies: 7
    Last Post: 06-11-2004, 12:30 PM
  3. Replies: 5
    Last Post: 12-03-2003, 05:47 PM
  4. half ADT (nested struct) problem...
    By CyC|OpS in forum C Programming
    Replies: 1
    Last Post: 10-26-2002, 08:37 AM
  5. binary tree problem - help needed
    By sanju in forum C Programming
    Replies: 4
    Last Post: 10-16-2002, 05:18 AM