Article View: gnu.g++.lib.bug
Article #239Re: does it bug of ostream.form()
From: bothner
Date: Thu, 27 Aug 1992 14:10
Date: Thu, 27 Aug 1992 14:10
204 lines
6984 bytes
6984 bytes
> 1:
> The output of this tiny program is a little bit strange.
> Only when form() output 20.0, the format changes.
This was a problem in libg++/iostream/outfloat.C.
I've appended my curent version. I've no idea if how
compatible it is with libg++-2.2.
> 2:
> This is another bug. Because I don't want such a dirty format above, I
> changed the "cout << form()" to "printf()" then interesting accident ...
> I think everyone will expect the output below ...
No. stdout and cout are different objects, with different buffers.
They are not synchonized (unless you use the stdio implementation
in libg++/iostream/stdio - in whcih case you will get the
formatting bug with printf).
The same will happen for most implementations of iostreams.
--Per Bothner
Cygnus Support bothner@cygnus.com
// This is part of the iostream library, providing input/output for C++.
// Copyright (C) 1992 Per Bothner.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the Free
// Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "ioprivate.h"
// sign_mode == '+' : print "-" or "+"
// sign_mode == ' ' : print "-" or " "
// sign_mode == '\0' : print "-' or ""
int __outfloat(double value, streambuf *sb, char type,
int width, int precision, ios::fmtflags flags,
char sign_mode, char fill)
{
#define PUT(x) do {if (sb->sputc(x) < 0) goto error;} while (0)
#define PUTN(p, n) \
do {int __n=n;if (sb->sputn(p, __n) != __n) goto error;} while (0)
#define PADN(fill, n) do {if (sb->padn(fill, n) < 0) goto error;} while (0)
ios::fmtflags pad_kind = flags & (ios::left|ios::right|ios::internal);
int skip_zeroes = 0;
int show_dot = (flags & ios::showpoint) != 0;
int decpt;
int sign;
int mode;
#define EBUF_SIZE 12
#define EBUF_END &ebuf[EBUF_SIZE]
char ebuf[EBUF_SIZE];
char *end;
int exp = 0;
switch (type) {
case 'f':
mode = 3;
break;
case 'F':
exp = 'e';
mode = 0;
skip_zeroes = 1;
type = 'g';
break;
case 'e':
exp = 'e';
mode = 2;
precision++; // Add one to include digit before decimal point.
break;
case 'E':
exp = 'E';
mode = 2;
precision++; // Add one to include digit before decimal point.
break;
case 'g':
case 'G':
exp = type == 'g' ? 'e' : 'E';
if (precision == 0) precision = 1;
if (!(flags & ios::showpoint))
skip_zeroes = 1;
type = 'g';
mode = 2;
break;
}
/* Do the actual convension */
char *p = dtoa(value, mode, precision, &decpt, &sign, &end);
register int i;
int useful_digits = end-p;
char *exponent_start = EBUF_END;
// Check if we need to emit an exponent.
if (mode != 3 && decpt != 9999) {
i = decpt - 1;
if ((type != 'g' && type != 'F') || i < -4 || i >= precision) {
// Print the exponent into ebuf.
// We write ebuf in reverse order (right-to-left).
char sign;
if (i >= 0)
sign = '+';
else
sign = '-', i = -i;
/* Note: ANSI requires at least 2 exponent digits. */
do {
*--exponent_start = (i % 10) + '0';
i /= 10;
} while (i >= 10);
*--exponent_start = i + '0';
*--exponent_start = sign;
*--exponent_start = exp;
}
}
int exponent_size = EBUF_END - exponent_start;
if (mode == 1)
precision = 1;
/* If we print an exponent, always show just one digit before point. */
if (exponent_size)
decpt = 1;
if (decpt == 9999) { // Infinity or NaN
decpt = useful_digits;
precision = 0;
show_dot = 0;
}
// dtoa truncates trailing zeroes. Set the variable trailing_zeroes to
// the number of 0's we have to add (after the decimal point).
int trailing_zeroes = 0;
if (skip_zeroes)
trailing_zeroes = 0;
else if (type == 'f')
trailing_zeroes = useful_digits <= decpt ? precision
: precision-(useful_digits-decpt);
else if (exponent_size) // 'e' 'E' or 'g' format using exponential notation.
trailing_zeroes = precision - useful_digits;
else // 'g' format not using exponential notation.
trailing_zeroes = useful_digits <= decpt ? precision - decpt
: precision-useful_digits;
if (trailing_zeroes < 0) trailing_zeroes = 0;
if (trailing_zeroes != 0 || useful_digits > decpt)
show_dot = 1;
int print_sign;
if (sign_mode == 0)
print_sign = sign ? '-' : 0;
else if (sign_mode == '+')
print_sign = sign ? '-' : '+';
else /* if (sign_mode == ' ') */
print_sign = sign ? '-' : ' ';
// Calculate the width (before padding).
int unpadded_width =
(print_sign != 0) + trailing_zeroes + exponent_size + show_dot
+ useful_digits + (decpt > 0 ? 0 : 1 - decpt);
int padding = width > unpadded_width ? width - unpadded_width : 0;
if (padding > 0
&& pad_kind != (ios::fmtflags)ios::left
&& pad_kind != (ios::fmtflags)ios::internal) // Default (right) adjust.
PADN(fill, padding);
if (print_sign)
PUT(print_sign);
if (pad_kind == (ios::fmtflags)ios::internal && padding > 0)
PADN(fill, padding);
if (decpt > 0) {
if (useful_digits >= decpt)
PUTN(p, decpt);
else {
PUTN(p, useful_digits);
PADN('0', decpt-useful_digits);
}
if (show_dot) {
PUT('.');
// Print digits after the decimal point.
if (useful_digits > decpt)
PUTN(p + decpt, useful_digits-decpt);
}
}
else {
PUT('0');
if (show_dot) {
PUT('.');
PADN('0', -decpt);
// Print digits after the decimal point.
PUTN(p, useful_digits);
}
}
PADN('0', trailing_zeroes);
if (exponent_size)
PUTN(exponent_start, exponent_size);
if (pad_kind == (ios::fmtflags)ios::left && padding > 0) // Left adjustment
PADN(fill, padding);
return 0;
error:
return EOF;
}
Technical Details
Message-ID:
<9208280410.AA12879@rtl.cygnus.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!cygnus.com!bothnerReferences:
<ONIZUKA.92Aug27213819@psiux535.icot.or.jp>Show Full Headers
Complete Article Headers
Newsgroups: gnu.g++.lib.bug Path: arc1-ca.pugleaf.net!sparky!uunet!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!cygnus.com!bothner From: bothner@cygnus.com Subject: Re: does it bug of ostream.form() Message-ID: <9208280410.AA12879@rtl.cygnus.com> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet References: <ONIZUKA.92Aug27213819@psiux535.icot.or.jp> Distribution: gnu Date: Thu, 27 Aug 1992 14:10:13 GMT Approved: bug-lib-g++@prep.ai.mit.edu Lines: 205