简体   繁体   中英

Converting binary serialization to human-readable serialization

I'm converting a program that used to do a binary dump of a struct to file and read that binary struct back in using fread. I want to convert it to creating and reading human readable data files, which of course means I need to format the data and such.

The creation of the data files in ascii went without a hitch. I switched from using fwrite to using fprintf with a format specified ending with \\n for new line.

FPFPF = fopen( flightStr, "w+" );

    if (FPFPF != NULL)
    {
        for ( i = 0; i < FlightInfo[flightnum].endFrameIndex; i++)
        {
            FlightEntries[flightnum][i].local_z += DeltaAlt;

            //if (fwrite (&FlightEntries[flightnum][i], sizeof (FLIGHT_ENTRY_TYPE), 1, FPFPF) !=1)
            if (fprintf (FPFPF, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
                FlightEntries[flightnum][i].local_x,
                FlightEntries[flightnum][i].local_y,
                FlightEntries[flightnum][i].local_z,
                FlightEntries[flightnum][i].pitch,
                FlightEntries[flightnum][i].roll,
                FlightEntries[flightnum][i].heading,
                FlightEntries[flightnum][i].gearpos,
                FlightEntries[flightnum][i].flappos,
                FlightEntries[flightnum][i].speedbrakepos,
                FlightEntries[flightnum][i].canopypos,
                FlightEntries[flightnum][i].afterburnerOn,
                FlightEntries[flightnum][i].kias,
                FlightEntries[flightnum][i].time) !=1)
            {
                WE++;
            }
        }

        fclose( FPFPF );
    }

This worked just fine. you can see the old fwrite is commented out now.

I was hoping that reading the file would be just as easy, but it doesn't seem to be working, and I'm unable to debug it because I have a weird memory leak with Freetype in debug builds that prevents me from stepping into this code. Here's the code that reads from the file.

if (load)
        {
            for ( i = 0; i < MAX_FLIGHT_ENTRIES; i++)
            {               
                // If the file end is found before it should be, set values to defaults
                // and save the file
                if (feof(pFile))
                {
                    FlightInfo[fileIndex].endFrameIndex = i - 1;
                    break;
                }
                else
                {
                    //fread (&FlightEntries[fileIndex][i], sizeof (FLIGHT_ENTRY_TYPE), 1, pFile);

                    fscanf (pFile, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n",
                        &FlightEntries[fileIndex][i].local_x,
                        &FlightEntries[fileIndex][i].local_y,
                        &FlightEntries[fileIndex][i].local_z,
                        &FlightEntries[fileIndex][i].pitch,
                        &FlightEntries[fileIndex][i].roll,
                        &FlightEntries[fileIndex][i].heading,
                        &FlightEntries[fileIndex][i].gearpos,
                        &FlightEntries[fileIndex][i].flappos,
                        &FlightEntries[fileIndex][i].speedbrakepos,
                        &FlightEntries[fileIndex][i].canopypos,
                        &FlightEntries[fileIndex][i].afterburnerOn,
                        &FlightEntries[fileIndex][i].kias,
                        &FlightEntries[fileIndex][i].time);
                }
            }

            FlightInfo[fileIndex].endFrameIndex = i - 1;

        }

There's a bit of other checking before pFile is opened and load is a bool that is set if we're going to do more than just see if a file exists. If it matters, all the values of the FlightInfo struct are float except for local_x, local_y, and local_z which are double. Is there something that stands out as obviously wrong here? It compiles and runs without error until this block of code is called, then it just crashes.

It does not matter to fprintf whether you pass a float or a double due to the default promotions performed for variadic arguments.

But it matters very much for fscanf whether you pass a float* or double* :

See http://man7.org/linux/man-pages/man3/scanf.3.html for the flags:

The following type modifier characters can appear in a conversion specification:

l Indicates either that the conversion will be one of d, i, o, u, x, X, or n and the next pointer is a pointer to a long int or unsigned long int (rather than int), or that the conversion will be one of e, f, or g and the next pointer is a pointer to double (rather than float) . Specifying two l characters is equivalent to L. If used with %c or %s, the corresponding parameter is considered as a pointer to a wide character or wide-character string respectively.

Actually, you should read that whole man-page, there are other interesting pitfalls.

As an aside, the l -modifier has no effect for fprintf with a floating-point-specifier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM