Search code examples
cfopenfile-read

Why my code is printing last values retrieved from file instead of new one


I have the following code for reading files in C. It's reading from files but not like its supposed to be. It is showing up like this:

current output

instead of like this:

correct output

Although I am calling the same print function. We are taking records for 4 employees. I know it's a logical error but I am unable to solve it.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

struct employee {
    float hoursWorked, hourlyRate, federalTax, stateTax;
    char name[20];
};

struct calc
{
    float grosspay, fto, sto, np;

};

void print(struct employee s[], struct calc c[], int n)
{
    for (int i = 0; i < 4; i++)
    {
        printf("\n%s's gross pay: $%.02f\n", s[i].name, c[i].grosspay);
        printf("Federal tax owed: $%.02f\n", c[i].fto);
        printf("State tax owed: $%.02f\n", c[i].sto);
        printf("Net pay: $%.02f \n\n", c[i].np);
        printf("\n");
    }
}


void savetext(struct employee s[], struct calc c[], int n)
{
    FILE *f;
    f = fopen("employee.txt", "w");
    for (int i = 0; i < n; i++)
    {
        fprintf(f, "%s\n", s[i].name);
        fprintf(f, "%f %f %f %f\n", s[i].hoursWorked, s[i].hourlyRate, s[i].federalTax, s[i].stateTax);
        fprintf(f, "%.2f %.2f %.2f %.2f\n", c[i].grosspay, c[i].fto, c[i].sto, c[i].np);
    }
    fclose(f);
}

void retrievetext(struct employee s[], struct calc c[], int n)
{
    FILE *f;
    int length;
    f = fopen("employee.txt", "r");
    for (int i = 0; i < n; i++)
    {
        fgets(s[i].name, sizeof(s[i].name), f);
        length = (int)strlen(s[i].name);
        s[i].name[length - 1] = '\0';
        fscanf(f, "%f %f %f %f\n", &s[i].hoursWorked, &s[i].hourlyRate, &s[i].federalTax, &s[i].stateTax);
        fscanf(f, "%.2f %.2f %.2f %.2f\n", &c[i].grosspay, &c[i].fto, &c[i].sto, &c[i].np);

    }
    fclose(f);
}

void savebin(struct employee s[], int n)
{
    FILE *f;
    f = fopen("employee.bin", "wb");
    for (int i = 0; i < n; i++) {
        fwrite(&s, sizeof(s[n]), n, f);
    }
    fclose(f);
}

void retrievebin(struct employee s[], int n)
{
    FILE *f;
    f = fopen("employee.bin", "rb");

    for (int i = 0; i < n; i++) {
        fread(&s, sizeof(s[i]), n, f);
    }
    fclose(f);
}
int main(){

    savetext(st, c, 4);
    retrievetext(st, c, 4);
    printf("After reading text file");
    print(st, c, 4);

    savebin(st, 4);
    retrievebin(st, 4);
    printf("After reading bin file");
    print(st, c, 4);

    return 0;
}

Solution

  • You didn't get a warning here from this?

    fscanf(f, "%.2f %.2f %.2f %.2f\n", &c[i].grosspay, &c[i].fto, &c[i].sto, &c[i].np);
    

    fscanf() will eat any float you throw at it, specifying the %.2f format like this doesn't really work.

    https://en.wikipedia.org/wiki/Scanf_format_string

    Try using it like this:

    fscanf(f, "%f %f %f %f\n", &c[i].grosspay, &c[i].fto, &c[i].sto, &c[i].np);
    

    It was probably reading the file wrong, and then using the wrong line as an employee name.

    PS: Your print() might have a small error:

    for (int i = 0; i < 4; i++) // It should probably be i < n, instead of i < 4
    

    And try to include an example input file, so people can test the code. At main(), there is no definition of st, so it's hard for people to see what's really happening if they can't test it themselves.