Why isn't fread reading in the correct integer

2019-06-14 18:32发布

问题:

This question was just to clarify why the correct output(year) isn't being printed correctly, given the following code.

For future readers, the issue was that the fget() function read off a byte that was supposed to be a byte that belonged to year, causing the year to not be printed correctly.

Here is my code Car structure

      typedef struct carType Car;
struct carType {
   int vehicleID;
   char make[20];
   char model[20];
   int year;
   int mileage;
   double cost;
   Car *next;
};

Code to write to binary file

  void writeBinFile(Car *headPointer)
{
     char fileName[20];
     //prompt user for name of textfile to print to 
    scanf("%s", fileName);
    FILE *ftp;
    Car *start =  headPointer->next;
    ftp = fopen(fileName, "wb");
    char separator = '0';
    while(start != NULL)
    {
       //write out 1 cell of data, cell contains 4 bytes
        fwrite(&start->year,sizeof(int), 1, ftp);
        fwrite(start->make,sizeof(char), strlen(start->make), ftp);
        fwrite(&separator, sizeof(char), 1, ftp); 
        fwrite(start->model, sizeof(char), strlen(start->make), ftp);
        fwrite(&separator, sizeof(char), 1, ftp);
        fwrite(&start->cost, sizeof(float), 1, ftp);
        fwrite(&start->mileage, sizeof(float),1,ftp);
        fwrite(&start->vehicleID, sizeof(int), 1, ftp);
        start = start->next;
    }
    fclose(ftp);
}

And code to read in a binary file

   void readFromBinFile(Car *headPointer)
{
      char fileName[20];
     //prompt user for name of textfile to print to 
    scanf("%s", fileName);
    FILE *ftp;
    Car *previous =  headPointer;
    ftp = fopen(fileName, "rb");
    Car *current;

    //go until the end of file is reached
    int c;
    while((c = fget(ftp)) != EOF)
    {
            current = (Car *)malloc(sizeof(Car));
            previous->next = current;
             //program receives 1 cell, that cell contains 4 bytes
             fread(&current->year, sizeof(int),1,ftp);
             printf("%d\n",current->year);
             char make[25];
             int count = 0;
             char oneAtATime= 'a';
             while(oneAtATime != '0') 
             { 
                    fread(&oneAtATime, sizeof(char),1,ftp);
                   if(oneAtATime!='0')
                   {
                      make[count] = oneAtATime;
                        count++;
                   }
            } 
            make[count] = 0;
           strcpy(current->make, make);
             char model[25];
              count = 0;
              oneAtATime= 'a';
             while(oneAtATime != '0') 
             { 
                    fread(&oneAtATime, sizeof(char),1,ftp);
                   if(oneAtATime!='0')
                   {
                      model[count] = oneAtATime;
                        count++;
                   }
            } 
            model[count] = 0;
           strcpy(current->model, model);
           fread(&current->cost, sizeof(float),1, ftp);
           fread(&current->mileage, sizeof(int),1,ftp);
           fread(&current->vehicleID, sizeof(int),1,ftp);
         previous = previous->next;
    } 
    fclose(ftp);
} 

Here is my data that I am trying to write/read from bin file.(loaded this from the read/write to text which works)

2014 Toyota Rav4 cost:$40000 mileage:3000, vehicleID:1
2014 Toyota Celica cost:$3220 mileage:2222, vehicleID:3

In the read binary method, I use this line of code for debugging purposes

   printf("%d\n",current->year);

Which should print 2014 in both instances. However when i try running the code, this is what gets printed

1275068423
1811939335

Is there something i am missing in my read and my write method that is causing the year to be so off?

回答1:

You have a logic error. The line

while((c = fgetc(ftp)) != EOF) // Assuming you meant to use fgetc not fget

reads the first character from ftp that is supposed to be part of the current->year. When you execute

         fread(&current->year, sizeof(int),1,ftp);

you are reading the wrong data. If sizeof(int) is 4 in your platform, you are picking up 3 bytes of data from the saved year and one byte from the saved make.

My suggestion to fix it:

int year;
while(1)
{
        if ( fread(&year, sizeof(int),1,ftp) != 1 )
        {
           // No more data to read.
           break;
        }

        current = (Car *)malloc(sizeof(Car));
        previous->next = current;

        current->year = year;

        // Proceed with reading the rest of the data.
        // Make sure you check the return value of every call
        // to `fread` before proceeding to the next line of code.


标签: c file struct