Formating of floats using iostream

E

eriwik

I'm trying to write floats to a file following a specific format (8
characters/record, and some other rules) and seem to have solved all
but one problem. There is no way of telling the maximum characters to
output. For positive numbers this is no problem since I can specify the
precision (number of digits not counting the decimal-point), however
when the number is negative the minus-sign does not count towars the
precision (which it shouldn't really), which has the effect that a
value that is written as 8 characters when positive is 9 when negative.
The following illustrates the problem:

#include <iostream>
#include <ios>

int main()
{
std::cout.precision(7);
std::cout.setf(std::ios_base::showpoint);

std::cout << 54.325617 << " ";
std::cout << -54.325617 << " ";
std::cout << 45.545 << " ";
float f = 3434;
std::cout << f << " ";

return 0;
}

This outputs "54.32562 -54.32562 45.54500 3434.000".

All but the second number is 8 characters long, does anyone have a
solution to this or will I have to make a test before writing each
number and see if it's negative, and then reduce precision to 6?
 
M

mlimber

I'm trying to write floats to a file following a specific format (8
characters/record, and some other rules) and seem to have solved all
but one problem. There is no way of telling the maximum characters to
output. For positive numbers this is no problem since I can specify the
precision (number of digits not counting the decimal-point), however
when the number is negative the minus-sign does not count towars the
precision (which it shouldn't really), which has the effect that a
value that is written as 8 characters when positive is 9 when negative.
The following illustrates the problem:

#include <iostream>
#include <ios>

int main()
{
std::cout.precision(7);
std::cout.setf(std::ios_base::showpoint);

std::cout << 54.325617 << " ";
std::cout << -54.325617 << " ";
std::cout << 45.545 << " ";
float f = 3434;
std::cout << f << " ";

return 0;
}

This outputs "54.32562 -54.32562 45.54500 3434.000".

All but the second number is 8 characters long, does anyone have a
solution to this or will I have to make a test before writing each
number and see if it's negative, and then reduce precision to 6?

Use std::setw in <iomanip>.

Cheers! --M
 
E

eriwik

(e-mail address removed) wrote: [snip]
All but the second number is 8 characters long, does anyone have a
solution to this or will I have to make a test before writing each
number and see if it's negative, and then reduce precision to 6?

Use std::setw in <iomanip>.

Yeah, so I thought at first, but according to the standard that's the
same as doing std::cout.width(8), which in turn sets the _minimul_
field width, not max. So it basically just tells the stream how many
fill-characters to put in if the field is too small :-(
 
M

mlimber

(e-mail address removed) wrote: [snip]
All but the second number is 8 characters long, does anyone have a
solution to this or will I have to make a test before writing each
number and see if it's negative, and then reduce precision to 6?

Use std::setw in <iomanip>.

Yeah, so I thought at first, but according to the standard that's the
same as doing std::cout.width(8), which in turn sets the _minimul_
field width, not max. So it basically just tells the stream how many
fill-characters to put in if the field is too small :-(

If you must maintain the 8 character width, drop the precision by 1,
either universally or only on negative numbers:

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

class HardWidth
{
public:
HardWidth( const double f, const unsigned width=8 )
{
const unsigned prec = ( f < 0 ? width - 2 : width - 1 );
m_oss << showpoint << setw( width-1 ) << setprecision( prec ) << f;
}

friend inline std::eek:stream& operator<<( std::eek:stream &os, const
HardWidth &h )
{
return os << h.m_oss.str();
}

private:
ostringstream m_oss;
};

int main()
{
cout << HardWidth( 12.3456789 ) << " ";
cout << HardWidth( -12.3456789 ) << " ";
return 0;
}

// Output: 12.34568 -12.3457

You could also turn on the plus sign by using std::showpos.

Cheers! --M
 
R

red floyd

mlimber said:
(e-mail address removed) wrote: [snip]
All but the second number is 8 characters long, does anyone have a
solution to this or will I have to make a test before writing each
number and see if it's negative, and then reduce precision to 6?
Use std::setw in <iomanip>.
Yeah, so I thought at first, but according to the standard that's the
same as doing std::cout.width(8), which in turn sets the _minimul_
field width, not max. So it basically just tells the stream how many
fill-characters to put in if the field is too small :-(

If you must maintain the 8 character width, drop the precision by 1,
either universally or only on negative numbers:
Then I'd argue that's a flaw in iostream formatting. In printf (yes, I
know it's not typesafe), you can specify %X.Ylf format. The amount of
hoop-jumping needed for setting widths and formatting in iostreams is
excessive.

Mind you, I *LIKE* iostreams. They're very useful, and much cleaner
than printf .... EXCEPT for field formatting on primitive types.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top