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.

Patrick Parker
  • 4,863
  • 4
  • 19
  • 51
  • 2
    The code seems to work for me. Can you make an [mcve]? – Nate Eldredge May 01 '19 at 01:56
  • I am not sure this is related, but shouldn't you nul-terminate `buf`? – Nate Eldredge May 01 '19 at 01:56
  • `fgets` stops at EOL or `\0` So it's dependent on the data stored go read correctly. – doug May 01 '19 at 01:58
  • Specifically, [this code](https://pastebin.com/qcRgef9V) outputs `0.993049, 0.993049, 0.993049` which seems to be right. – Nate Eldredge May 01 '19 at 01:59
  • @NateEldredge I posted the MCVE and added a note about my compiler – Patrick Parker May 01 '19 at 02:03
  • ok, I posted the entire main.cpp as requested @NateEldredge and I'd be grateful if you undo your close vote if that was you – Patrick Parker May 01 '19 at 02:08
  • 2
    It wasn't me, I don't have enough reputation to cast close votes. One thing I noticed, the documentation at https://learn.microsoft.com/en-us/cpp/c-runtime-library/scanf-width-specification?view=vs-2019 does not actually say that `%la` is allowed... – Nate Eldredge May 01 '19 at 02:11
  • 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 (https://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... – Nate Eldredge May 01 '19 at 02:15
  • 1
    This code [works on gcc](https://wandbox.org/permlink/3mFxZf49Pobly5cG). This code [works on clang](https://wandbox.org/permlink/vHmtuZPGNBwVeYAC). – L. F. May 01 '19 at 02:17
  • Possible Duplicate [sscanf(“0X80.9”, “%f”, &value) sets value to a hex float not a float](https://stackoverflow.com/questions/47464440/sscanf0x80-9-f-value-sets-value-to-a-hex-float-not-a-float) about VS13 – David C. Rankin May 01 '19 at 02:27
  • @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? – Patrick Parker May 01 '19 at 16:24
  • 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. – David C. Rankin May 01 '19 at 17:51
  • @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. – Patrick Parker May 01 '19 at 19:35
  • 1
    @PatrickParker Isn't it shocking that Microsoft doesn't want to make a *C* compiler for their platform <3 – Antti Haapala -- Слава Україні May 01 '19 at 19:51
  • @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. – David C. Rankin May 01 '19 at 23:07

1 Answers1

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.

Patrick Parker
  • 4,863
  • 4
  • 19
  • 51