not sure how to properly use fwrite()

This is a discussion on not sure how to properly use fwrite() within the C Programming forums, part of the General Programming Boards category; When you have a file open in binary mode ("r+b") via fopen(), and you're using fread() to read a sequence ...

  1. #1
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    82

    not sure how to properly use fwrite()

    When you have a file open in binary mode ("r+b") via fopen(), and you're using fread() to read a sequence of structure array elements, how do you "delete" a single record (array element's contents) and replace that record with the following element's values?

    e.g.
    Code:
    while (count < MAXBKS && fread(&libry[count], size, 1, pbooks) == 1)
       {
          if (count == 0)
          puts("Current contents of book.txt:\n");
          printf("%s by %s: $%.2f\n", libry[count].title, libry[count].author, libry[count].value);
    
          printf("Would you like to alter (a) or delete (d) this record? [Enter] for 'no'.\n");
    
          if ((ch = getchar()) == 'd')
          {
             num = count;
             libry[num] = libry[num + 1];  // this doesn't work
          }   // even if it did work, I have no idea how to properly use fwrite() to write
               // the shorter list of records into the original file before using fclose()
    
          count++;
       }
    Also, I've read in another post about making all sorts of changes in memory, then writing the changes to the file before closing the file pointer, but the reason why I'm failing in this task seems to be my lack of understanding of just *when* I'm supposed to incorporate fwrite() in the program.

    Any advice would be appreciated.
    Steering Wheel: gcc in Code::Blocks 10.05
    Batmobile: Linux Mint 14, running kernel 3.5 and KDE 4.9.2
    Engine: AMD FX-8350 Vishera 8-core
    Dashboard: NVIDIA GTX 570 HD
    Rusty old trailer for hauling games: Windows XP SP3 (in VirtualBox)
    ORV for composing music: Windows 7 Pro 64bit (in VirtualBox)

  2. #2
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    82

    hmmm

    I just had an idea, so here's a more appropriate question:

    After a file is open, do I need to read the *entire* file's contents with fread() before I can properly manipulate all the array elements in the structure I'm accessing?
    Steering Wheel: gcc in Code::Blocks 10.05
    Batmobile: Linux Mint 14, running kernel 3.5 and KDE 4.9.2
    Engine: AMD FX-8350 Vishera 8-core
    Dashboard: NVIDIA GTX 570 HD
    Rusty old trailer for hauling games: Windows XP SP3 (in VirtualBox)
    ORV for composing music: Windows 7 Pro 64bit (in VirtualBox)

  3. #3
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,164
    Not at all. You simply need to know where in your file the record you're trying to retrieve is. Then you can fseek() to that location, fread() the record in, and blam-o, you're done.

    If all of the records are the same size, then knowing where the record is in the file is pretty simple, but if the records vary in length (e.g. because of variable-length strings or whatnot) then you'll probably have to read every record up to the one you're looking for, or have some sort of index at the header or footer of the file.
    If you understand what you're doing, you're not learning anything.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    When you have a data file with records, you don't want to delete a record by actually removing it. That's a huge waste. If you had 30,000 records, every time you wanted to delete a record, you'd have to shift roughly 15,000 records. And every time you wanted to add a record, and keep it in sorted order, you might have to again, shift 15,000 records. (An index can be used to avoid most of this shifting, but then you have this index to take care of).

    Your program should mark that record as zero or available, and leave it where it is. Your searches and displays should then be adjusted to not show zeroed out records. Now when a new record is to be added, your program first looks for the nearest available record, and uses it. (If no record is available, your program should create one for you, and later, create some empty one's, scattered throughout your data file).

    Should too many empty records exist, your program should ask the operator if they want to "compress" the data base. We're talking about roughly 5% of the records, as an ideal number of available records.

    The total changes to the data file, are minimal, as well as to your program, and it's an elegant way to handle a large file of records. Note that a huge amount of data shuffling, is avoided. That's a big plus, because it's at those times, when your data file is at risk of being destroyed by unexpected catastrophes': power grid failure, disk failure, mobo error, power supply error, etc.
    Last edited by Adak; 11-02-2010 at 07:49 PM.

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,164
    Quote Originally Posted by Adak View Post
    When you have a data file with records, you don't want to delete a record by actually removing it. That's a huge waste. If you had 30,000 records, every time you wanted to delete a record, you'd have to shift roughly 15,000 records. And every time you wanted to add a record, and keep it in sorted order, you might have to again, shift 15,000 records. (An index can be used to avoid most of this shifting, but then you have this index to take care of).

    Your program should mark that record as zero or available, and leave it where it is. Your searches and displays should then be adjusted to not show zeroed out records. Now when a new record is to be added, your program first looks for the nearest available record, and uses it. (If no record is available, your program should create one for you, and later, create some empty one's, scattered throughout your data file).

    Should too many empty records exist, your program should ask the operator if they want to "compress" the data base. We're talking about roughly 5% of the records, as an ideal number of available records.

    The total changes to the data file, are minimal, as well as to your program, and it's an elegant way to handle a large file of records.
    It's important to note that this really only applies to records of consistent size. You won't be able to overwrite an existing record if the new record is bigger than the original one that was "deleted".
    If you understand what you're doing, you're not learning anything.

  6. #6
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    In my experience, records have fields. Fields *always* have a set size. If you have fields without a set size, you don't have a field. Otherwise you could make "War and Peace", a field. You could make the Library of Congress contents, a field.

    A field has to be defined, in size, or it's not a field. It's data.

  7. #7
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    82
    Quote Originally Posted by Adak View Post
    When you have a data file with records, you don't want to delete a record by actually removing it. That's a huge waste. If you had 30,000 records, every time you wanted to delete a record, you'd have to shift roughly 15,000 records. And every time you wanted to add a record, and keep it in sorted order, you might have to again, shift 15,000 records. (An index can be used to avoid most of this shifting, but then you have this index to take care of).

    Your program should mark that record as zero or available, and leave it where it is. Your searches and displays should then be adjusted to not show zeroed out records. Now when a new record is to be added, your program first looks for the nearest available record, and uses it. (If no record is available, your program should create one for you, and later, create some empty one's, scattered throughout your data file).

    Should too many empty records exist, your program should ask the operator if they want to "compress" the data base. We're talking about roughly 5% of the records, as an ideal number of available records.

    The total changes to the data file, are minimal, as well as to your program, and it's an elegant way to handle a large file of records. Note that a huge amount of data shuffling, is avoided. That's a big plus, because it's at those times, when your data file is at risk of being destroyed by unexpected catastrophes': power grid failure, disk failure, mobo error, power supply error, etc.
    That shifting problem is exactly the way I was approaching it, so thanks for clarifying what a mistake that would be. So, now, I'm getting to where I can ask the correct question:

    If each of my records is an element from a structure array (and each record has been read from an already existing file), how do I mark an element as "zero" or "available?" That's one thing I haven't been able to glean from the textbook, even though the exercise is asking me to "delete the record, (and) use the vacated array position for the next record to be read."

    I'm confused because when I think of array elements, their indexes are static, regardless of the contents of any variables within. I have no idea how to zero them or make them available.
    Steering Wheel: gcc in Code::Blocks 10.05
    Batmobile: Linux Mint 14, running kernel 3.5 and KDE 4.9.2
    Engine: AMD FX-8350 Vishera 8-core
    Dashboard: NVIDIA GTX 570 HD
    Rusty old trailer for hauling games: Windows XP SP3 (in VirtualBox)
    ORV for composing music: Windows 7 Pro 64bit (in VirtualBox)

  8. #8
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    82

    oh man!

    I hate to be dense, but when you say "mark" a record as zero or available, do you mean an assignment statement, such as:

    libry[count].title = "0"; // title being the first member of the structure libry

    ???

    If so, I apologize for being so dull about this...
    Steering Wheel: gcc in Code::Blocks 10.05
    Batmobile: Linux Mint 14, running kernel 3.5 and KDE 4.9.2
    Engine: AMD FX-8350 Vishera 8-core
    Dashboard: NVIDIA GTX 570 HD
    Rusty old trailer for hauling games: Windows XP SP3 (in VirtualBox)
    ORV for composing music: Windows 7 Pro 64bit (in VirtualBox)

  9. #9
    Codus Conjectus spongefreddie's Avatar
    Join Date
    Sep 2010
    Location
    USA
    Posts
    82

    oops

    Quote Originally Posted by spongefreddie View Post
    I hate to be dense, but when you say "mark" a record as zero or available, do you mean an assignment statement, such as:

    libry[count].title = "0"; // title being the first member of the structure libry

    ???

    If so, I apologize for being so dull about this...
    Good grief...

    I should have suggested:

    strcpy(libry[count].title, "0");

    sheesh...
    Last edited by spongefreddie; 11-02-2010 at 08:55 PM.
    Steering Wheel: gcc in Code::Blocks 10.05
    Batmobile: Linux Mint 14, running kernel 3.5 and KDE 4.9.2
    Engine: AMD FX-8350 Vishera 8-core
    Dashboard: NVIDIA GTX 570 HD
    Rusty old trailer for hauling games: Windows XP SP3 (in VirtualBox)
    ORV for composing music: Windows 7 Pro 64bit (in VirtualBox)

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    You can use any sentinel value you want. I like using the simple assignment of:
    Code:
    libry[count].title = '\0';
    Which is the char equivalent of zero, and the end of string marker. No strcpy() is needed, it will go into the first element of the title array.

    Also, having the key field as the first field in the record, just makes sense.

    When they say "reuse" the record, technically, this HAS to be what they mean. If you are deleting a record, and then creating a new record, you are simply reusing the old records space - maybe.

    But that may be too fine a point to make.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fwrite failing with japanese language
    By DrSnuggles in forum C++ Programming
    Replies: 4
    Last Post: 06-18-2010, 08:22 AM
  2. fread() + fwrite() not working properly
    By TaiL in forum C Programming
    Replies: 13
    Last Post: 02-24-2010, 10:29 PM
  3. Replies: 3
    Last Post: 03-05-2009, 02:14 AM
  4. Determining fwrite errors
    By cboard_member in forum C Programming
    Replies: 2
    Last Post: 04-26-2006, 05:30 AM
  5. fwrite file size
    By lambs4 in forum C Programming
    Replies: 4
    Last Post: 04-04-2003, 04:49 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21