sscanf fails to read double hex
Asked Answered
B

1

2

I need to preserve the exact binary representation of some doubles in a text file with other ascii values, so I am using "%a" as suggested in this question.

fprintf (pFile, "Scale: %a, %a, %a\n", scale.x, scale.y, scale.z);

However, when I try to read it in with "%la" the scanf returns 0 items read.

double x=0, y=0, z=0;
fgets(buf, sizeof buf, pFile);
int test = sscanf (buf, "Scale: %la, %la, %la\n", &x, &y, &z);
// test is zero!

When I open up the debugger, I see that the string buffer is exactly as I expected it.

buf ... "Scale: 0x1.fc70e3p-1, 0x1.fc70e3p-1, 0x1.fc70e3p-1\n" ... char[1000]

So why can't it read it?

As requested by Nate Eldredge, here is my MCVE version:

#include <stdio.h>
int main(int argc, char *argv[])
{
    double x=0, y=0, z=0;
    const char* buf = "Scale: 0x1.fc70e3p-1, 0x1.fc70e3p-1, 0x1.fc70e3p-1\n";
    int test = sscanf(buf, "Scale: %la , %la , %la", &x, &y, &z);
    // test is zero!
}

Note: I am using MS Visual Studio 2013

Second Note: I need to send the source code and data files to a third party, who has his own compiler. So the save format has to be relatively platform-independent.

Bartle answered 1/5, 2019 at 1:49 Comment(15)
The code seems to work for me. Can you make an minimal reproducible example?Evans
I am not sure this is related, but shouldn't you nul-terminate buf?Evans
fgets stops at EOL or \0 So it's dependent on the data stored go read correctly.Elitism
Specifically, this code outputs 0.993049, 0.993049, 0.993049 which seems to be right.Evans
@NateEldredge I posted the MCVE and added a note about my compilerBartle
ok, I posted the entire main.cpp as requested @NateEldredge and I'd be grateful if you undo your close vote if that was youBartle
It wasn't me, I don't have enough reputation to cast close votes. One thing I noticed, the documentation at learn.microsoft.com/en-us/cpp/c-runtime-library/… does not actually say that %la is allowed...Evans
Just as a guess, if you change %la to %lf, what happens? I think the standard says that all of aeEfFgG are supposed to behave identically for scanf, including the handling of hex floats (en.cppreference.com/w/c/io/fscanf). The MS documentation I linked above doesn't mention handling hex floats with f, but maybe it will work anyway...Evans
This code works on gcc. This code works on clang.Subjoin
Possible Duplicate sscanf(“0X80.9”, “%f”, &value) sets value to a hex float not a float about VS13Coworker
@DavidC.Rankin thanks, although that one is trying to get 2013 behavior in 2015, whereas I am trying to get 2015 behavior in 2013. I am kinda shocked that they still had not implemented a compliant strtod in 2013. Now what? Write it myself?Bartle
The challenge is that your hex values are hex-float values, otherwise if they were simply hex, you could read as unsigned long and then use a union between double and unsigned long. With the hexfloat format you will have to piece it together yourself. Presumably the information can be translated into a sign-bit, a biased exponent and normalized mantissa. At that point it is just a matter of shifting bits.Coworker
@DavidC.Rankin by "union" you mean something equivalent to a reinterpret_cast, right? I need to send the source code and data files to a third party, who has his own compiler. And I assume I would lose platform-compatibility if I reinterpreted the double from raw bytes.Bartle
@PatrickParker Isn't it shocking that Microsoft doesn't want to make a C compiler for their platform <3Fai
@PatrickParker yes that is the basic gest, but use of a union is the way provided by the C standard to avoid the strict aliasing violation. You generally want to avoid a direct cast.Coworker
B
1

Microsoft VS2013 strtod, sscanf, and istringstream, etc. did not implement the c99 c++11 standard and they cannot parse hex floats or hex doubles.

Bartle answered 1/5, 2019 at 16:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.