cfile-iobinaryfilesrandomaccessfile

Why data read from the random access file and print twice of last line of the table on screen ? (Got picture)


can I know why the last line of the table below will print twice? Everything is executed well and just has the problem stated above.

The type of file used is a random access file and data written into a binary file named toyota.txt.

Anyone can teach me what is the problem there? Thank you so much!

The code is shown below:

/*program 1 write the data into file toyota.txt*/

#include<stdio.h>

struct vehicledata{
    char vnum[100];
    int cnum;
    float f50;
    float f100;
    float f200;
    float f400;
    float f800;
};

int main()
{
    FILE *fptr;
    struct vehicledata toyota;
    if((fptr = fopen("toyota.txt","wb")) == NULL)
    {
        printf("Error! File fail opened!");
    }
    else
    {
        printf("This program can create a text file named toyota.txt \n");
        printf("and save the value of car noise level(dB) with\ndifferent frequency and vehicle numbers into file\n\n");
        printf("======================================================================\n");
        printf("Enter car number(1 to 10, enter 0 to end input)\n");
        printf("? ");
        scanf("%d", &toyota.cnum);

        while (toyota.cnum != 0)
        {
            printf("\nEnter Vehicle number\n");
            printf("? ");
            scanf("%s", toyota.vnum);
            printf("Enter car noise level(dB) at 50Hz, 100Hz, 200Hz, 400Hz and 800Hz\n");
            printf("? ");
            scanf("%f %f %f %f %f", &toyota.f50, &toyota.f100, &toyota.f200, &toyota.f400, &toyota.f800);
            fseek(fptr, (toyota.cnum - 1) * sizeof(struct vehicledata), SEEK_SET);
            fwrite(&toyota, sizeof(struct vehicledata), 1, fptr);
            printf("\n======================================================================\n");
            printf("\nEnter car number (1 to 100, 0 to end input) \n");
            printf("? ");
            scanf("%d", &toyota.cnum);
        }
    }
    fclose(fptr);
    return 0;
}
/*program 2 reads the data from the file toyota.txt and find
the car that emanates the minimum noise at 200Hz*/
#include <stdio.h>
#include <stdlib.h>

struct vehicledata{
    char vnum[100];
    int cnum;
    float f50;
    float f100;
    float f200;
    float f400;
    float f800;
};
char name[10];
float min;
int i, m;
int main()
{
    FILE *fptr;
    struct vehicledata toyota;
    if ((fptr = fopen("toyota.txt","rb")) == NULL)//open and read data in the file
    {
        printf("Error! File fail opened!");
    }
    else
    {
        printf("This program can read and display the data from the toyota.txt\n and find car that have minimum noise in 200Hz\n\n");
        printf("\nThe information in the toyota.txt are shown at below:\n");
        printf("\n\t\t\t\tCar Noise Level(dB)\t\t\t");
        printf("\n=======================================================================\n");
        printf("%s\t\t%s\t%s\t%s\t%s\t%s\t\n","Vehicle Number","50Hz","100Hz","200Hz","400Hz","800Hz");
        printf("=======================================================================\n");
        char name[10];
        float min=100;
        while(!feof(fptr))
        {
            fread(&toyota, sizeof(struct vehicledata), 1, fptr);
            if(toyota.f200 < min)
           {
               min=toyota.f200;
               for(int i=0 ; i<10 ; i++)
                {
                    name[i]=toyota.vnum[i];
                }
           }
            if(toyota.cnum != 0)
            {
                printf("%s\t\t\t%.2f\t%.2f\t%.2f\t%.2f\t%.2f\n", toyota.vnum, toyota.f50, toyota.f100, toyota.f200, toyota.f400, toyota.f800);
            }
        }
        printf("=======================================================================\n");
        printf("\n\n+++++++++++++++++++++++++++++++++Result+++++++++++++++++++++++++++++++++\n");
        printf("\nVehicle number of car with minimum noise in 200Hz is %s at %.2f dB\n", name, min);
    }
    fclose(fptr);
    return 0;
}

The data that need to enter output


Solution

  • The problem is in program 2. In the section below you assume that your fread will be OK since you are not att the EOF. This is not the case.

    while(!feof(fptr))
    {
        fread(&toyota, sizeof(struct vehicledata), 1, fptr);
    

    What happens is that you check for EOF in your loop and being at the very end of the file the last fread is indeed read one more time but fails. Since you don't check for it and fread did not have toyota overwritten (since the read failed) you have a duplicate that you print out. After that you now check for EOF and leave the loop.

    A better loop would look like this:

    while (fread(&toyota, sizeof(struct vehicledata), 1, fptr)) {
    

    Since the documentation for fread states, "If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).", in your case we are not really checking for errors and we are at EOF.

    But if you want to figure out that the loop ended due to EOF or an error then "callers must use feof(3) and ferror(3) to determine which occurred.".