ThatBlueJuice
ThatBlueJuice

Reputation: 51

Sorting floating points from file in C

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

Answers (2)

Iharob Al Asimi
Iharob Al Asimi

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

You need also to change the datatypes (of score variables and fields) from ints to doubles

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

Related Questions