3

Given double foo I can assign it from a hex format string using sscanf like this:

sscanf("0XD", "%lg", &foo)

But I cannot seem to get an istringstream to behave the same way. All of these just write 0 to foo:

  1. istringstream("0XD") >> foo
  2. istringstream("0XD") >> hex >> foo
  3. istringstream("D") >> hex >> foo

This is particularly concerning when I read here that the double istream extraction operator should:

The check is made whether the char obtained from the previous steps is allowed in the input field that would be parsed by std::scanf given the conversion specifier

Why can't I read hex from an istream? I've written some test code here if it would be helpful in testing.

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • Apply a cast may be? – πάντα ῥεῖ May 26 '16 at 13:17
  • @πάνταῥεῖ Can you help me understand what you're suggesting? I don't wand to read in an integer and cast to a `double`, if that's what you're saying, I'm just extracting something simple for the sake of clarity here. – Jonathan Mee May 26 '16 at 13:24
  • It doesn't look like streams were made to do this. I wonder if it comes from the fact that hex literals are treated as int's so the stream library treas hex input the same way. – NathanOliver May 26 '16 at 13:26
  • @NathanOliver Not that I'd suggest it's authoritative but: http://en.cppreference.com/w/cpp/locale/num_get/get says that I should be able to use hexadecimal characters in my input field. – Jonathan Mee May 26 '16 at 13:39
  • 1
    It's not available, at least not yet. [The reference](http://en.cppreference.com/w/cpp/language/floating_literal) also says that in C++17 the exponent character for hex float will be `P`. But P is not in the list of `0123456789abcdefABCDEFxX+-` used by the streams. Might get fixed before next standard release, or not? – Bo Persson May 26 '16 at 14:27
  • @molbdnilo You say: "the input is first filtered as if `scanf` would read it in decimal." Yet [this](http://en.cppreference.com/w/cpp/locale/num_get/get) is saying that `"0123456789abcdefxABCDEFX+-"` are accepted which work fine, integer or decimal. – Jonathan Mee May 26 '16 at 14:29
  • @BoPersson Good comment. I hadn't actually noticed that. Maybe that's why nothing conforms to this yet? Cause they couldn't get the exponent right? – Jonathan Mee May 26 '16 at 14:30
  • @molbdnilo The point is that we're working with the `%lg` modifier from Stage 1, which would allow the hex characters. In any event, I think that the actual guard on the allowed characters is [`hexfloat`](http://en.cppreference.com/w/cpp/io/manip/fixed), when that is specified everything is peachy. – Jonathan Mee May 26 '16 at 14:49
  • @BoPersson It looks like when [`hexfloat`](http://en.cppreference.com/w/cpp/io/manip/fixed) is used "p" and "P" *are* accepted... – Jonathan Mee May 26 '16 at 14:51
  • @JonathanMee Yeah, I was completely confused (I even managed to write a botched test program to "prove" my confusion was correct ). I'm removing my inane ramblings. Sorry for being a time-waster. – molbdnilo May 27 '16 at 05:15
  • @molbdnilo Not a problem at all. I appreciate you taking the time to consider my issues! – Jonathan Mee May 27 '16 at 10:49

2 Answers2

2

What you're looking for is the hexfloat modifier. The hex modifier is for integers.

On compliant compilers this will solve your problem.

#include <cstdio>
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;

int main() {
    double foo;

    sscanf("0xd", "%lg", &foo);
    cout << foo << endl;

    istringstream("0xd") >> hexfloat >> foo;
    cout << foo << endl;

    istringstream("d") >> hexfloat >> foo;
   cout << foo << endl; 
}

Using Visual Studio 2015 will produce:

13
13
13

Using libc++ will produce:

13
13
0

So I'm not sure of the legitimacy of istringstream("d") >> hexfloat >> foo

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • 1
    Nice.. but is there a difference between your second and third test cases 'istringstream("0xd") >> hexfloat >> foo;'? If so my eyes are not seeing it. – Dale Wilson May 26 '16 at 15:06
  • @DaleWilson Well, said, I was so excited about finding `hexfloat` that I just straight edited the code from the question without thinking. I've fixed it. – Jonathan Mee May 26 '16 at 15:26
0

This, including loopback seems to work fine with two recent compilers and at least c++17, for example:

MSVC 16.7.0 Preview 2 C++ std /latest

Clang 10.0.0 -std=c++2a

but fails for GCC, for example:

GCC 10.0.1 -std=c++2a using libstd++

This bug is suspended awaiting a decision by the C++ standards WG21

https://gcc.gnu.org/bugzilla//show_bug.cgi?id=81122

Bug 81122 - [DR 2381] parsing f stopped after '0' when reading std::hexfloat >> f;

https://cplusplus.github.io/LWG/issue2381 Last modified: 2018-08-24

and appears to have stalled for reasons unclear :-(