6

C++ has an I/O manipulator called 'fixed' to input/output floating-point numbers in fixed (non-scientific) form. It works fine for output, but I don't understand how to get input working properly.

Consider this example:

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

int main() {
    double value;
    istringstream("1.4e1") >> fixed >> value;
    cout << value << endl;
}

In my opinion, it should work like this. Input stream has some string. When we apply fixed manipulator on it and try to read a double/float, it should stop on a first character which is not a digit or a dot (dot is not accepted second/third/more times). So, correct output would be 1.4 (we stop processing input when we encounter 'e').

Instead, this code outputs 14. Why? How it works and what is the purpose of fixed for input streams? How can I read a double from input stream and stop at 'e' (leave it in input stream)?

LogicStuff
  • 19,397
  • 6
  • 54
  • 74
JIghtuse
  • 866
  • 5
  • 11
  • `std::fixed` has no purpose for input streams. None of the arithmetic formatting manipulators are meant to be used with input streams. – David G Apr 15 '15 at 17:35
  • @0x499602D2 ok, thanks. What about solution? Is there any easy way (without writing parser) to read a double, leaving `e` in input stream? – JIghtuse Apr 15 '15 at 17:40
  • There's apparently no easy way. I'm looking through the code for the extractor and there doesn't seem to be a way to prevent the parser from consuming `e` or `E`. You'll have to read it out into a string and parse yourself. – David G Apr 15 '15 at 18:25
  • @0x499602D2, can you post your comment as answer? – JIghtuse Apr 16 '15 at 13:50

3 Answers3

0

You should use std::scientific I tried like this:

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

int main() {
    double value;
    cin >> std::fixed>> std::scientific >> value;
    cout << std::scientific<<value << endl;
}

input: 1.4e1 output: 1.400000e+01

Steephen
  • 14,645
  • 7
  • 40
  • 47
0

This question is somewhat misleading. 1.4e1 = 1.4 * 10¹ = 1.4 * 10 = 14.

[...] it should stop on a first character which is not a digit or a dot (dot is not accepted second/third/more times).

Why would it? The e1 in 1.4e1 is part of the number: without it the meaning is different. You have to read it, if you want to parse it properly.

So, correct output would be 1.4 (we stop processing input when we encounter 'e').

This would apply if you were reading an integral type which "stops" the parsing when a non-digit character ([0-9]) is met or other conditions trigger (such as overflow or underflow).

edmz
  • 8,220
  • 2
  • 26
  • 45
  • If my assumptions are correct about your question, we might try to discuss a solution. – edmz Apr 15 '15 at 19:28
  • No, I want to read only `1.4` part and stop. Let's suppose we don't have final `1` and `e` is just a suffix to indicate some unit. So, input is `1.4e`, or `1.4euro`. I don't need to read any character after digits into my number, it will go to another variable. But I also need to read a double, not integer. Looks like there is no simple way to do that. – JIghtuse Apr 16 '15 at 11:45
  • I see, @JIghtuse. But `e` and `euro` are different! If you had `1.4 euro`, it would work. Since the exponent has to be next to the mantissa, a simple space between them would work, for example. – edmz Apr 16 '15 at 15:42
  • @Steephen It has nothing to do with UDLs. – edmz Apr 16 '15 at 17:53
  • yeah, I know that one space change everything. I was interested in reading double and char after that, so `e` in `euro` are the same in this case (i.e., I'm not interested in characters after the first one). – JIghtuse Apr 17 '15 at 03:34
0

I need to read a value as 1.4, leaving e in input stream. Is it possible?

There isn't a standard manipulator for this, I believe that there's a way to define a custom ones, but it would be too complex. I haven't found an answer on how to do that here on SO, I have only found a question about output stream modifier.

Let's move to at least some kind of solution. That would be parsing it yourself:

#include <iostream>
#include <sstream>
#include <string>
#include <cctype>

int main()
{
    std::istringstream iss("1.4e1");
    double value;

    {
        std::string s;

        while(iss.peek() != 'e' && !std::isspace(iss.peek()))
            s.push_back(iss.get());

        std::istringstream(s) >> value;
    }

    std::cout << value << std::endl;
}
Community
  • 1
  • 1
LogicStuff
  • 19,397
  • 6
  • 54
  • 74