0

I'm developing an application and one of the functions is the function sort_books_file which basically has to sort the name of the books in the file fp by alphabetical order and then prints them in the file fp2.

At the moment, the only thing the function does is printing the name of the books from file fp into file fp2.

I would like to know how it is possible to sort the name of the books by alphabetical order into the file fp2.

I'm a C beginner and I don't have a lot of experience in C programming...somebody helps?

#include <stdio.h>    
FILE *fp;
FILE *fp2;

struct book{
   int key;
   char name[50];
   int price;
 };

sort_books_file(){

    struct book b;

    //r: open the file for reading (read-only)
    if ((fp=fopen("books.dat","r"))==NULL){
        printf("Error\n");
        exit(1);
    }

    //w: open the file for writing (write-only).
    //the file is created if it doesn't exist
    if ((fp2=fopen("books_sorted.dat","w"))==NULL){
        printf("Error: not possible to open the file. \n");
        exit(1);
    }

    //while end of file has not been reached
    while (!feof(fp)){  

        fread(&b,sizeof(b),1,fp);

        if(feof(fp))
        {
        break;
        }

        fwrite(&b.name,sizeof(b.name),1,fp2);

    }

    fclose(fp);
    fclose(fp2);
}
Zombie
  • 321
  • 3
  • 6
  • 16
  • Use `strcmp()` to sort – Gopi Jan 03 '15 at 17:57
  • You can use `strcmp()` or `stricmp()` to compare strings, but you still need an actual sorting algorithm. Most beginners use bubble sort, due to its simplicity, but it is atrociously inefficient in a real-world scenario. Can you provide a sample of what's in `books.dat`? Is it one string per line, or a comma-separated-values (CSV) file, etc? – Cloud Jan 03 '15 at 17:59
  • \00\00\00\00pfbiaegumcqgveplxkxt\00\B3i\F6\DB\00\00\87\00\00\B9\00\00\00\00\00haaddflukpemtm\00lxkxt\00\B3i\F6\DB\00\00\ED\00\00\DE\00\00\00\00\00qnhgcfraymewunyv\00kxt\00\B3i\F6\DB\00\00J\00\00\00\00\00\00\00anuedqtnbjqsyxbbfuc\00\00\B3i\F6\DB\00\00\93\00\00l\00\00\00\00\00fwebpjewkttqwkkmovdhvbk\00\DB\00\00\00\00\88%\00\00\00\00\00mpkrwjwayg\00qwkkmovdhvbk\00\DB\00\00b\00\00&\00\00\00\00\00qkaewns\00yg\00qwkkmovdhvbk\00\DB\00\00, \00\00\81\00\00\00\00\00ummduqsnbmkk\00kkmovdhvbk\00\DB\00\00L\00\00; CSV I think (The name of the books are random strings) – Zombie Jan 03 '15 at 18:14
  • 2
    @Dogbert `fread()` loads each file record into `struct book`. Zombie I suggest reading the records into an array of `struct book` and then using `qsort()`, you'll find plenty of examples I am sure. – Weather Vane Jan 03 '15 at 18:16
  • It appears that you may be loading a binary file, not an ASCII text file. Your `fopen` call should open the file in `"rb"` mode. Also, this is potentially dangerous as struct padding may be different on different systems, so this code is not portable. – Cloud Jan 03 '15 at 18:37
  • @Dogbert the "b" is ignored on all POSIX conforming systems, including Linux. How would `fread()` work differently in text or binary mode? – Weather Vane Jan 03 '15 at 19:26
  • @WeatherVane I stand corrected on the binary flag. Still, loading a binary file like this could still go awry if padding is different. – Cloud Jan 03 '15 at 21:25

2 Answers2

2

The easiest way is to use strcmp() on book.name to sort.

strcmp() works as follows :

syntax : int strcmp(const char *str1, const char *str2)

st1 and str2 are the strings to be compared

The function returns -1 if str1 is less than str2 and 0 if the strings are equal and 1 if str1 is greater than str2.

strcmp() uses lexicographic ordering, which means it sorts the words as it appears on the dictionary. Here's a question that discusses it.

Examples

strcmp("hello", "world")returns -1

strcmp("world", "hello") returns 1

stcmp("boo", "boo") returns 0

And here's a sorting function that does what you want (I haven't tested it) :

void sort_books_file(){

 //Assume you have only maximum 10 books
 struct book books[10]; 
 strct book b;

 //open files for reading and writing
 //..
 //..

int i = 0;
while (!feof(fp)){  

        fread(&b,sizeof(b),1,fp);
        books[i] = b;
        i++;
        if(feof(fp))
        {
        break;
        }
    }

//number of books
int len = i;
//bubble sort;
int j = 0;

//Bubble sort. Google for "bubble sort"
for(i=0; i<len; i++)
{
    for(j=0; j<len-1; j++)
    {
       //If the first book should come after the next book in the array
       if(strcmp(books[j].name, books[j+1].name) > 0)
        {
            //swap the books
            struct book temp;
            temp = books[j];
            books[j] = books[j+1];
            books[j+1] = temp;
        }
    }
}

//now write each book in the array "books" into the file one by one
}
Community
  • 1
  • 1
  • I completed the code with the code bellow but the name of the books are printed in the same way they were inserted: //now write each book in the array "books" into the file one by one int z; for(z=0; z – Zombie Jan 03 '15 at 19:12
  • Then something went wrong with the sorting. Use printf inside the if condition and check if the books are indeed swapped wherever necessary – Kevin Martin Jose Jan 03 '15 at 20:08
  • I used the printf inside the if condition and the swap isn't working. The order stays the same as inserted. – Zombie Jan 03 '15 at 21:05
  • I'm so sorry i made a mistake. The if statement is wrong. Replace > 1 with > 0. I will edit the answer – Kevin Martin Jose Jan 04 '15 at 05:29
2

I hope this will help:

void sort(struct book* books, int n)
{
    int j,i;

   for(i=1;i<n;i++)
   {
       for(j=0;j<n-i;j++)
       {
           if(books[j].name < books[j+1].name)
           {
               struct book temp = books[j];
               books[j] = books[j+1];
               books[j+1] = temp;
          }
      }
  }
}

Store Book info into an array of book structure. Then pass this array to sort function. This will do your job.

struct book LIST[n];
sort(LIST, n);
Shahriar
  • 13,460
  • 8
  • 78
  • 95