Code:
#include<string.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
FILE *fp;
typedef struct book{
double rating;
double price;
double relevance;
int ID;
}B;
B *list;
/*
ignore this - this is a bug fix only for Turbo C failing to link in the floating point formats
automatically. It has no other purpose.
*/
static void force_fpf()
{
float x, *y; /* Just declares two variables */
y = &x; /* Forces linkage of FP formats */
x = *y; /* Suppress warning message about x */
}
int read_file(char* infile, int N)
{
int c;
if((fp=fopen(infile, "rb")) != NULL)
{
fscanf(fp, "%*s\t%*s\t%*s\t%*s\n");
c=0;
while((!feof(fp))&&(c<N))
{
fscanf(fp, "%lf\t%lf\t%lf\t%d\n", &list[c].rating, &list[c].price, &list[c].relevance, &list[c].ID);
c++;
}
fclose(fp);
}
else
{
fprintf(stderr,"%s did not open. Exiting.\n",infile);
exit(-1);
}
return(c);
}
int comp_on_rating(const void *a, const void *b)
{
if ((*(B *)a).rating < (*(B *)b).rating)
return -1;
else if ((*(B *)a).rating > (*(B *)b).rating)
return 1;
else
return 0;
}
int comp_on_relev(const void *a, const void *b)
{
if ((*(B *)a).relevance < (*(B *)b).relevance)
return -1;
else if ((*(B *)a).relevance > (*(B *)b).relevance)
return 1;
else
return 0;
}
int comp_on_price(const void *a, const void *b)
{
if ((*(B *)a).price < (*(B *)b).price)
return 1;
else if ((*(B *)a).price > (*(B *)b).price)
return -1;
else
return 0;
}
/* This code is taken and adapted from
http://en.allexperts.com/q/C-1587/Merge-Sort-C.htm
and http://paste-it.net/public/d2c2d20
The merge sort works by taking the items that need to be sorted,
splitting the list into two (each about the same size) and
recursively sorting each sublist, by recursively calling the merge
sort on each sublist, which resulting in smaller and smaller lists.
One the sublists have all been sorted, they are all merged together
into one sorted list. */
void merge(B* a, int low, int high, int mid, int(*compar)(const void *, const void *))
{
int i, j, k;
B* c = (B *)malloc((high - low + 1) * sizeof(B));
i=low;
j=mid+1;
k=0;
<=high is needed for rating sort. < no = is needed for relevance! ;-)
while((i<=mid)&&(j<=high)) // <<< this is the immediate problem
{
if(compar(&a[i],&a[j]) <= 0)
{
c[k]=a[i];
k++;
if(k > 20) printf("\nk1 in merge!! \a\a\n");
i++;
if(i > 20) printf("\ni1 in merge!! \a\a\n");
}
else //allows j to go to 21
{
c[k]=a[j]; //and here's the problem with that
k++;
if(k > 20) printf("\nk2 in merge!! \a\a\n");
j++;
if(j > 20) printf("\nj2 in merge! \a\a\n");
}
}
while(i<=mid)
{
c[k]=a[i];
k++;
if(k > 20) printf("\nk3 in merge!! \a\a\n");
i++;
if(i > 20) printf("\ni2 in merge!! \a\a\n");
}
while(j<=high)
{
c[k]=a[j];
k++;
if(k > 20) printf("\nk3 in merge!! \a\a\n");
j++;
if(j > 20) printf("\nj3 in merge!! \a\a\n");
}
memcpy(a + low, c, (high - low + 1) * sizeof(B));
free(c);
}
void mergesort(B* a, int low, int high, int(*compar)(const void *, const void *))
{
int mid;
if(low<high)
{
mid=(low+high)/2;
mergesort(a,low,mid,compar);
mergesort(a,mid+1,high,compar);
merge(a,low,high,mid,compar);
}
}
char *getUserInput() {
/* Create and allocate space for the users response. */
int responseLength;
char* userResponse = malloc(200);
fgets(userResponse, 100, stdin);
/* Remove the carry line character and replace it with a 0. */
responseLength = strlen(userResponse);
userResponse[(responseLength - 1)] = 0;
/* Return the result. */
return userResponse;
}
void user_interface(int N)
{
// For Part 1 this function calls the sort function to sort on Price only
// mergesort(list, 0, N, comp_on_price);
// For Part 2 this function
// (1) asks the user if they would like to sort their search results
// (2) asks for the most important field (or key), the next most etc
// (3) calls your sort function
char *numberOfFields;
char* mostImportantField;
//char* mostImportantField;
//char* mostImportantField;
char* secondMostImportantField;
//char* secondMostImportantField;
char* thirdMostImportantField;
int noOfFields;
printf("How many fields would like to sort by? (Maximum of 3)\n");
printf("> ");
numberOfFields = getUserInput();
noOfFields = atoi(numberOfFields);
while(noOfFields > 3 || noOfFields < 1)
{
printf("The number of fields to sort by must be 1, 2 or 3, please try again.\n");
printf("> ");
numberOfFields = getUserInput();
noOfFields = atoi(numberOfFields);
}
if(noOfFields == 1)
{
printf("Which field is the most important for you to sort by?\n");
printf("> ");
mostImportantField = getUserInput();
if(strcmp(mostImportantField,"price") == 0)
{
mergesort(list, 0, N, comp_on_price);
}
else if(strcmp(mostImportantField,"relevance") == 0)
{
mergesort(list, 0, N, comp_on_relev);
}
else if(strcmp(mostImportantField,"rating") == 0)
{
mergesort(list, 0, N, comp_on_rating);
}
}
else if(noOfFields == 2)
{
printf("Which field is the 2nd most important for you to sort by?\n");
printf("> ");
secondMostImportantField = getUserInput();
if(strcmp(secondMostImportantField,"price") == 0)
{
mergesort(list, 0, N, comp_on_price);
}
else if(strcmp(secondMostImportantField,"relevance") == 0)
{
mergesort(list, 0, N, comp_on_relev);
}
else if(strcmp(secondMostImportantField,"rating") == 0)
{
mergesort(list, 0, N, comp_on_rating);
}
printf("Which field is the most important for you to sort by?\n");
printf("> ");
mostImportantField = getUserInput();
if(strcmp(mostImportantField,"price") == 0)
{
mergesort(list, 0, N, comp_on_price);
}
else if(strcmp(mostImportantField,"relevance") == 0)
{
mergesort(list, 0, N, comp_on_relev);
}
else if(strcmp(mostImportantField,"rating") == 0)
{
mergesort(list, 0, N, comp_on_rating);
}
}
else if(noOfFields == 3)
{
printf("Which field is the 3rd most important for you to sort by?\n");
printf("> ");
thirdMostImportantField = getUserInput();
if(strcmp(thirdMostImportantField,"price") == 0)
{
mergesort(list, 0, N, comp_on_price);
}
else if(strcmp(thirdMostImportantField,"relevance") == 0)
{
mergesort(list, 0, N, comp_on_relev);
}
else if(strcmp(thirdMostImportantField,"rating") == 0)
{
mergesort(list, 0, N, comp_on_rating);
}
printf("Which field is the 2nd most important for you to sort by?\n");
printf("> ");
secondMostImportantField = getUserInput();
if(strcmp(secondMostImportantField,"price") == 0)
{
mergesort(list, 0, N, comp_on_price);
}
else if(strcmp(secondMostImportantField,"relevance") == 0)
{
mergesort(list, 0, N, comp_on_relev);
}
else if(strcmp(secondMostImportantField,"rating") == 0)
{
mergesort(list, 0, N, comp_on_rating);
}
printf("Which field is the most important for you to sort by?");
printf("> ");
mostImportantField = getUserInput();
if(strcmp(mostImportantField,"price") == 0)
{
mergesort(list, 0, N, comp_on_price);
}
else if(strcmp(mostImportantField,"relevance") == 0)
{
mergesort(list, 0, N, comp_on_relev);
}
else if(strcmp(mostImportantField,"rating") == 0)
{
mergesort(list, 0, N, comp_on_rating);
}
}
}
void print_results(int N)
{
int i;
//if((fp=fopen("top20.txt","w")) != NULL)
// {
for(i=N-1;i>=0;i--) //N-20?
{
printf("%g %g %g %d\n", list[i].rating, list[i].price, list[i].relevance, list[i].ID);
// don't print to the input file - when it's not right!
// fprintf(fp, "%g %g %g %d\n", list[i].rating, list[i].price, list[i].relevance, list[i].ID);
}
//fclose(fp);
/* }
else
{
fprintf(stderr,"Trouble opening output file top20.txt\n");
exit(-1);
}
*/
}
int main() //int argc, char *argv[])
{
int N;
/* if(argc!=3)
{
fprintf(stderr, "./exec <input_size> <filename>\n");
exit(-1);
}
N=atoi(argv[1]);
*/
N = 20;
list = malloc(N*sizeof(B)); //removed cast of malloc's pointer
N=read_file("top20.txt", N); //argv[2], N);
user_interface(N);
print_results(N);
getch();
return(0);
}
/*
Stars Price Relv ID
4.5 12.49 7.9 1
5 7.99 7.6 2
2 16.99 6.2 3
2.5 15.49 9.1 4
3.5 20.99 6 5
1 9.99 8 6
1.5 13.99 1 7
5 8.49 8.3 8
3.5 10.49 5.2 9
3 27.99 7.7 10
3 22.99 8.9 11
2 11.49 9.1 12
1 26.49 0.8 13
1.5 19.49 3.4 14
1 3.99 0.6 15
2 27.49 8.5 16
2 16.99 7.6 17
3 19.49 0.3 18
2.5 26.49 7.2 19
2 21.49 3.5 20
*/