akash_c
akash_c

Reputation: 173

Reading space separated values file in c++ error

I am trying to get float values out of a file to use them in my program. I used the following forum to construct the program Read file line by line.
But the values obtained by doing so appear to be truncated at the end.

My code

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

int main()
{

ifstream file;
file.open("test_file.ssv");
string line;
while(file.good() && (getline(file, line)))
{
    istringstream iss(line);
    double a, b, c;
    iss >> a >> b >>c ;
    cout << a <<endl;
}
file.close();
return (0);
}

The output that I obtain is

9292.31
32432.2

While my file has the following data

9292.3123 4234.66 342.25423
32432.2423 3423.656 341.67841

Any suggestions to improve upon this?

Upvotes: 2

Views: 3569

Answers (4)

user152949
user152949

Reputation:

Your standard stream may have a low floating point precision and you therefore only see a few of the decimals when outputing a float with std::cout. Use std::ios_base::precision to increase the precision and look into using std:: ios::floatfield to output fixed or scientific precision , example:

// modify precision
#include <iostream>     // std::cout, std::ios

    int main () {
      double f = 3.14159;
      std::cout.unsetf ( std::ios::floatfield );                // floatfield not set
      std::cout.precision(5);
      std::cout << f << '\n';
      std::cout.precision(10);
      std::cout << f << '\n';
      std::cout.setf( std::ios::fixed, std:: ios::floatfield ); // floatfield set to fixed
      std::cout << f << '\n';
      return 0;
    }

Outputs:

3.1416 3.14159 3.1415900000

Upvotes: 2

James Kanze
James Kanze

Reputation: 153899

Nothing has been truncated. You can't truncate a double; it always has the same number of bits and the same format. But you're outputting using the default precision (6) and the default format, which will always output 6 significant digits, and no more.

There are two issues here. The first is simple: what format and precision do you want? There are three possible formats: the default (which will use either fixed or scientific, depending on the value, and for which the precision signifies the maximun number of significant digits), fixed , or scientific (where the precision signifies the number of digits after the decimal). Thus, with a precision of 6, depending on the format, your first value will be:

default:    9292.31
fixed:      9292.312300
scientific: 9.292312E03

For the values you show, fixed would seem most appropriate; but if you have very small values, it will display less digits, and for very large values, you can get some very long strings.

The usual way of handling this is to define a manipulator for whatever the values represent; in this case, I'll just call it values, because I don't know anything more precise about your application, but you should probably find a more meaningful name:

class value
{
    mutable std::ostream* myOwner;
    mutable std::ios_base::fmtflags myFlags;
    mutable int myPrecision;
    void capture( std::ostream& owner )
    {
        if ( myOwner == NULL ) {
            myOwner = &owner;
            myFlags = myOwner->fmtflags();
            myPrecision= myOwner->precision();
        }
    }
public:
    value() : myOwner( NULL ) {}
    ~value()
    {
        if ( myOwner != NULL ) {
            myOwner->flags( myFlags );
            myOwner->precision( myPrecision );
        }
    }
    friend std::ostream& operator<<( std::ostream& dest, value const& manip )
    {
        manip.capture( dest );
        dest.setf( std::ios_base::fixed, std::ios_base::floatfield );
        dest.precision( 6 );
    }
};

This will also restore the formatting status at the end of the full expression (since it should only be used as a temporary); this is generally a good idea becaues it prevents surprises in later code. If you're doing any significant output, you'll create a base class for the save and restore, and derive your actual manipulator from that.

Once you have this, you can write:

std::cout << value() << a << " " << b << " " << c << std::endl;

All of the values after value() in the statement will be output with the desired format.

More generally, do you understand how machine floating point works? The actual values stored in your doubles will not be those that you see in the file, because those that you see in the file are not representable in the usual double format. For the number of digits you enter, you should not see any difference if you output the same number of digits, or even one or two more, but if you output a very large number of digits (say about 17) you could.

Upvotes: 0

jtuki
jtuki

Reputation: 415

Use the code below will make some improvement.

std::cout << std::setprecision(10) << a << std::endl;

Reference to the two links below for more information:
http://www.cplusplus.com/reference/ios/ios_base/precision/
http://www.cplusplus.com/reference/iomanip/setprecision/

Happy coding with C++. ;-)

Upvotes: 0

Kyle_the_hacker
Kyle_the_hacker

Reputation: 1434

This is a problem in the precision of the cout. Try to test the comparison:

cout << "Stand.: " << a << "  Prec.: " << fixed << setprecision(10) << a << endl;

Upvotes: 0

Related Questions