title: How to remove a structure from an array of structures and correctly overwrite a file using fwrite()
body: <p><strong>Hi everyone I'm new to C. I had to create a "library" where I can store some books and make some changes on them (add a book, remove a book or change it) using an array of structures, then I have to save it in a file.</strong></p>
  
  <p>The problem is that it should be possible to remove a book and overwrite the changes in the file opened in "r+b" mode using the fwrite() function.</p>
  
  <p>At first I read from the file to the array of structures and count the number of books in it using fread(), then after I remove a book I scroll the structures down and I assign an empty structure to the last structure.</p>
  
  <p>Ex.</p>
  
  <ul>
  <li>Book1</li>
  <li>Book2</li>
  <li>Book3</li>
  </ul>
  
  <p>After removing "Book2" and scrolling down the structures:</p>
  
  <ul>
  <li>Book1</li>
  <li>Book3</li>
  <li>Book3</li>
  </ul>
  
  <p>After assigning an empty structure to the last one that has been read:</p>
  
  <ul>
  <li>Book1</li>
  <li>Book3</li>
  <li>Random_Stuff</li>
  </ul>
  
  <p>Then I save only the first two structures to the file and when I read the file I get:</p>
  
  <ul>
  <li>Book1</li>
  <li>Book3</li>
  <li>Book3</li>
  </ul>
  
  <p>If I overwrite the file with the 3 structures I get:</p>
  
  <ul>
  <li>Book1</li>
  <li>Book3</li>
  <li>Random_Stuff</li>
  </ul>
  
  <p>And that's reasonable, but how can I overwrite the whole file just with, in this case, the first two structures using fwrite()?</p>
  
  <p>This is my structure</p>
  
  <pre><code>typedef struct book {
          char title[MAXTIT];
          char autor[MAXAUT];
          float price;
  } info;
  </code></pre>
  
  <p>This is the function to remove a book:</p>
  
  <pre><code>void remove_book(info bibl[], int * num) {
  
  // Empty structure to assign to the last structure after the removal
  info empty;
  
  char title[256];
  
  puts("Enter the title of the book you want to remove:");
  read(title, 256);
  
  // Scrolling down the structures to cover the removed one
  for (int i = 0 ; i &lt; *num ; i++)
      if (strcmp(title, bibl[i].title) == 0) {
          for (int index = i ; index &lt; *num ; index++)
              bibl[index] = bibl[index + 1];
          bibl[*num] = empty;
          (*num)--;
          break;
      }
  
  for (int index = 0 ; index &lt; *num ; index++)
      printf("%s, autor: %s, price: %.2f €\n", bibl[index].title, bibl[index].autor, bibl[index].price);
  }
  </code></pre>
  
  <p>This is the full code (just in case):</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;stdbool.h&gt;
  
  #define MAXTIT  40          // Maximum lenght of the title
  #define MAXAUT  40          // Maximum lenght of the name of the autor
  #define MAXBOOK 10          // Maximum number of books
  
  typedef struct book {
          char title[MAXTIT];
          char autor[MAXAUT];
          float price;
  } info;
  
  int size = sizeof(info);
  int counter = 0;
  int counterp;
  FILE * fp;
  char file_name[64];
  
  int menu(void);
  void add_book(info [], int *);
  void remove_book(info [], int *);
  void modify_book(info [], int);
  void input(info [], int *, int *);
  char *read(char *, int);
  
  int main(void) {
  
  info bibl[MAXBOOK];
  int index, choice;
  
  puts("Please, enter the file to be read:");
  read(file_name, 64);
  
  // If returns a NULL pointer puts an error message and ends the program
  if (!(fp = fopen(file_name, "r+b"))) {
      fprintf(stderr, "An error occurred while trying to open \"%s\".", file_name);
      exit(1);
  }
  
  // Read the content of the file
  input(bibl, &amp;counter, &amp;counterp);
  
      // If the file is empty lets the user add a book
      if (counterp == 0) {
          add_book(bibl, &amp;counter);
          fwrite(&amp;bibl[counterp], size, counter - counterp, fp);
  
          // If the user added a book shows the content of the file
          if (counter &gt; 0) {
              puts("Updated file content:");
              for (index = 0 ; index &lt; counter ; index++)
                  printf("%d) %s, autor: %s, price: %.2f €\n", index + 1, bibl[index].title, bibl[index].autor, bibl[index].price);
              putchar('\n');
          }
      }
  
      // If there is something in the file lets the user choose between some options (add, remove, modify a book or simply quit)
      if (counter &gt; 0) {
  
          // Menu returns a value for the switch function
          choice = menu();
  
          // Repeats the choice until the "Quit" option has been chosen
          while (choice) {
  
              switch(choice) {
  
              // First case, reads from the file, adds the book and writes everything in the file
              case 1 :    input(bibl, &amp;counter, &amp;counterp);
                      add_book(bibl, &amp;counter);
                      fwrite(&amp;bibl[counterp], size, counter - counterp, fp);
                      break;
  
              // Second case, reads from the file, (should) removes the book and overwrites everything in the file
             case 2 : input(bibl, &amp;counter, &amp;counterp);
                      remove_book(bibl, &amp;counter);
                      rewind(fp);                 // Rewind to overwrite the new values in the file
                      fwrite(&amp;bibl[0], size, counterp, fp);
                      break;
  
              // Third case, reads from the file, modifies the book and overwrites everything in the file
             case 3 : input(bibl, &amp;counter, &amp;counterp);
                      modify_book(bibl, counter);
                      rewind(fp);                 // Same as before
                      fwrite(&amp;bibl[0], size, counter, fp);
                      break;
  
              // Forth case, quits the menu
             case 4 : break;
  
              // Should never activate but I put it in case I'd like to modify something in the menu ecc...
            default : fputs("You entered wrong data!", stderr);
                      break;
  
            }
  
          // If a change has been made shows the new content
          if (choice &gt;= 1 &amp;&amp; choice &lt;= 3) {
              puts("Updated file content:");
  
              for (index = 0 ; index &lt; counter ; index++)
                  printf("%d) %s, autor: %s, price: %.2f €\n", index + 1, bibl[index].title, bibl[index].autor, bibl[index].price);
  
              putchar('\n');
          }
  
          // Exit the loop in case of "Quit" option
          if (choice == 4)
              break;
  
          choice = menu();
      }
  
  } else
      puts("No books? What a pity!");
  
  // If fclose() != NULL, an error occurred
  if (fclose(fp))
      fprintf(stderr, "An error occurred while trying to close \"%s\".", file_name);
  
  puts("Ending process...");
  
  return 0;
  }
  
  // Function that shows the options of the menu
  int menu(void) {
  
  int num;
  
  puts("Choose between:\n1) Add a book\n2) Remove book\n3) Modify a book\n4) Quit");
  
  while (scanf("%d", &amp;num) != 1 || num &lt; 1 || num &gt; 4)
      puts("Choice between:\n1) Add a book\n2) Remove book\n3) Modify a book\n4) Quit");
  
  while (getchar() != '\n');
  
  return num;
  }
  
  // Function used to add a book to the file (works fine)
  void add_book(info bibl[], int * num) {
  
  int index;
  bool flag = false;
  
  puts("Please, enter a new title ([enter] at the start of the line ends the process):");
  
  while (*num &lt; MAXBOOK &amp;&amp; read(bibl[*num].title, MAXTIT) &amp;&amp; bibl[*num].title[0] != '\0') {
  
      puts("Now enter the autor.");
      read(bibl[*num].autor, MAXAUT);
  
      for (index = 0 ; index &lt; *num ; index++)
          if (strcmp(bibl[index].title, bibl[*num].title) == 0 &amp;&amp; strcmp(bibl[index].autor, bibl[*num].autor) == 0) {
              puts("This book is already in your library.");
              puts("Please, enter a new title ([enter] at the start of the line ends the process):");
              flag = true;
              break;
          }
  
      if (flag)
          continue;
  
      puts("And finally enter the price.");
      scanf("%f", &amp;bibl[(*num)++].price);
  
      while (getchar() != '\n');
  
      if (*num &lt; MAXBOOK)
          puts("\nPlease, enter a new title ([enter] at the start of the line ends the process):");
      }
  }
  
  // Function that should work and do what it's meant to do but it doesn't for I don't know what reason
  void remove_book(info bibl[], int * num) {
  
  // Empty structure to assign to the last structure after the removal
  info empty;
  
  char title[256];
  
  puts("Enter the title of the book you want to remove:");
  read(title, 256);
  
  // Scrolling down the structures to cover the removed one
  for (int i = 0 ; i &lt; *num ; i++)
      if (strcmp(title, bibl[i].title) == 0) {
          for (int index = i ; index &lt; *num ; index++)
              bibl[index] = bibl[index + 1];
          bibl[*num] = empty;
          (*num)--;
          break;
      }
  
  for (int index = 0 ; index &lt; *num ; index++)
      printf("%s, autor: %s, price: %.2f €\n", bibl[index].title, bibl[index].autor, bibl[index].price);
  }
  
  // Function used to change a book's informations
  void modify_book(info bibl[], int num) {
  
      char title[256];
      int choice;
  
      puts("Enter the title of the book you want to modify:");
      read(title, 256);
  
      puts("Choose what you want to modify:\n1) Title\n2) Autor\n3) Price\n4) Everything");
      while(scanf("%d", &amp;choice) != 1 || choice &lt; 1 || choice &gt; 4)
          puts("Choose what you want to modify:\n1) Title\n2) Autor\n3) Price\n4) Everything");
  
      while (getchar() != '\n');
  
      for (int i = 0 ; i &lt; num ; i++) {
          if (strcmp(title, bibl[i].title) == 0) {
  
              switch (choice) {
  
  
              case 1 :    puts("Please, enter the new title of the book:");
                          read(bibl[i].title, MAXTIT);
                          break;
  
              case 2 :    puts("Enter the new autor of the book:");
                          read(bibl[i].autor, MAXAUT);
                          break;
  
              case 3 :    puts("Enter the new price:");
                          scanf("%f", &amp;bibl[i].price);
                          while (getchar() != '\n');
                          break;
  
              case 4 :    puts("Please, enter the title of the book:");
                          read(bibl[i].title, MAXTIT);
                          puts("Now enter the autor of the book:");
                          read(bibl[i].autor, MAXAUT);
                          puts("And finally its cost:");
                          scanf("%f", &amp;bibl[i].price);
                          while (getchar() != '\n');
                          break;
  
              default :   break;
  
              }
  
              break;
          }
      }
  
      for (int index = 0 ; index &lt; num ; index++)
          printf("%s, autor: %s, price: %.2f €\n", bibl[index].title, bibl[index].autor, bibl[index].price);
  }
  
  // Function that reads from the file in which we are saving the structures
  void input(info bibl[], int * counter, int * counterp) {
  
      *counter = 0;
      rewind(fp);
  
      while (*counter &lt; MAXBOOK &amp;&amp; fread(&amp;bibl[*counter], size, 1, fp) == 1) {
  
          if (*counter == 0)
              printf("Actual content of the file \"%s\":\n", file_name);
  
          printf("%d) %s by %s: %.2f €\n", *counter + 1, bibl[*counter].title, bibl[*counter].autor, bibl[*counter].price);
          (*counter)++;
      }
  
      if (*counter &gt; 0 &amp;&amp; *counter &lt; MAXBOOK)
          putchar('\n');
  
      *counterp = *counter;
      if (*counter == MAXBOOK) {
          fprintf(stderr, "The file \"%s\" is full.", file_name);
          exit(1);
      }
  }
  
  // Better alternative for gets()
  char *read(char * str, int len) {
  
      char * res, * here;
  
      if (res = fgets(str, len, stdin))
          if (here = strchr(str, '\n'))
              *here = '\0';
          else
              while (getchar() != '\n');
  
      return res;
  }
  </code></pre>