Reputation: 51
Right, so after many attempts i have finally got some code that can take integer values from file, and sort them next to their respective names.
For example:
User file____________ Score file___________--
User1 4
User2 6
User3 2
User4 3
My program has the ability to sort the score file into a descending order, while keeping the first intact.
This produces:
User2 6
User1 4
User4 3
User3 2
Now, this isn't my problem, the code functions perfectly. However, as an extended assignment. the scores are now floating points.
My inital thinking was: Easy, Just change all the score integer variables into floats. That works, except it doesn't sort them after the decimal place.
Rather than give the "Dumb" code, i'm going to give the perfect code and mark my changes.
#include <stdio.h> /* printf */
#include <stdlib.h> /* qsort */
struct Element
{
int userId;
int score;
};
int ascendingSortCompareFunction (const void * a, const void * b)
{
return (((struct Element *)a)->score - ((struct Element *)b)->score);
}
int descendingSortCompareFunction (const void * a, const void * b)
{
return -ascendingSortCompareFunction(a, b);
}
void readFromFile(const char *const filename, struct Element **elements, size_t *count)
{
FILE *file;
void *auxiliary;
int index;
int score;
char line[512];
if ((elements == NULL) || (count == NULL))
return;
*elements = NULL;
file = fopen("TIStotS.txt", "r");
if (file == NULL)
return;
index = 0;
while (fgets(line, sizeof(line), file) != NULL)
{
if (sscanf(line, "%d", &score) == 1)
{ //^^Changed to %f
auxiliary = realloc(*elements, (1 + *count) * sizeof(struct Element));
if (auxiliary == NULL)
{
free(*elements);
fclose(file);
*elements = NULL;
return;
}
*elements = auxiliary;
(*elements)[*count].userId = 1 + index;
(*elements)[*count].score = score;
*count += 1;
index += 1;
}
}
fclose(file);
}
int main ()
{
size_t count;
size_t n;
struct Element *elements;
size_t size;
elements = NULL;
size = sizeof(struct Element);
count = 0;
readFromFile("TIStotS.txt", &elements, &count);
if ((elements != NULL) && (count > 0))
{
qsort(elements, count, size, descendingSortCompareFunction);
printf ("UserID\tScore (Descending Sort)\n");
for (n = 0 ; n < count ; n++)
{
int end, loop, line;
char str[512];
FILE *fd = fopen("PDfirstN.txt", "r");
if (fd == NULL)
{
printf("Failed to open file\n");
getch();
}
line=elements[n].userId;
for(end = loop = 0;loop<line;++loop){
if(0==fgets(str, sizeof(str), fd)){//include '\n'
end = 1;//can't input (EOF)
break;
}
}
if(!end)
printf("%s",str);
printf("%d\n",elements[n].score);
//^^ changed to %.2f
fclose(fd);
}
free(elements);
}
getchar();
return 0;
}
This gives the code for integer sorting, when i change all score variables from %d to %f., it sorts in file like:
4.23
3.75
3.78
3.23
2.25
Where the values are not sorted correctly, and only done to their first significant figure
Edit: I have already turned int score into float score etc, it doesn't fix the sort
Upvotes: 0
Views: 153
Reputation: 53006
Change the score variable type to float
.
struct Element
{
int userId;
float score; /* instead of int score;
};
and here
int index;
float score; /* instead of int score; */
char line[512];
and finally
if (sscanf(line, "%f", &score) == 1) /* instead of if (sscanf(line, "%d", &score) == 1) */
And fix the compare functions
if (((struct Element *)a)->score == ((struct Element *)b)->score)
return 0;
return (((struct Element *)a)->score < ((struct Element *)b)->score) ? -1 : 1
by not changing the type of the score
member and score
variable passed to scanf
the value was truncated making 3.75
and 3.78
-> 3 == 3
when truncated, and hence the sort order you observed.
Upvotes: 2
Reputation: 1
You need also to change the datatypes (of score variables and fields) from int
s to double
s
BTW, several compilers are able to warn you about that mistake (e.g. GCC if compiling with gcc -Wall -Wextra -g
) on scanf
Upvotes: 4