Link to home
Start Free TrialLog in
Avatar of Stephen Kairys
Stephen KairysFlag for United States of America

asked on

C format specifer for doubles with leading 0's

In C:

The following statement (for a value of 12345.67 for a double:
printf("that is 09.2f: <%09.2f>\n", double_dollar_amount_with_cents);

outputs:
"that is 09.2f: < 12345.67>"

Why am I not getting the leading 0 likeI would for something like "%05ld"? Is it not supported for floats on all compilers?

Thanks,
Steve
Avatar of ozo
ozo
Flag of United States of America image

It may be reserving space for a - sign.
Did you try
printf("that is 09.2f: <%09.2f>\n", 123.45);
or
printf("that is 011.2f: <%011.2f>\n", 12345.67);
SOLUTION
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of Stephen Kairys

ASKER

Ozo and Kent - thanks for the quick reply.  I tried the below with the same odd behavior.

printf("HARDCODED:that is 09.2f: <%09.2f>\n", 123.45);
printf("HARDCODED:that is 011.2f: <%011.2f>\n", 12345.67);
------------------------
HARDCODED:that is 09.2f: <   123.45>
HARDCODED:that is 011.2f: <   12345.67>

FWIW, this is the WATCOM 11 compiler.
Steve
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well that was interesting...and fun. :)

I found this paragraph per this link. The emphasis is mine and I have added whitespace for readabiliy.

http://www.openwatcom.org/ftp/manuals/current/clib.pdf

"If no field width is specified, or if the value that is given is less than the number of characters in the converted value (subject to any precision value), a field of sufficient width to contain the converted value is used.  

"If the converted value has fewer characters than are specified by the field width, the value is padded on the left (or right, subject to the left-justification flag) with spaces or zero characters ("0").

" If the field width begins with "0" and no precision is specified, the value is padded with zeros; otherwise the value is padded with spaces.  

"If the field width is "*", a value of type int from the argument list is used (before a precision argument or a conversion argument) as the minimum field width.  A negative field width value is interpreted as a left-justification flag, followed by a positive field width."

So, per the above, do you still say that this is NOT per the ISO/IEC standard?
Thanks.
Steve
ISO/IEC says

0 For d, i, o, u, x, X, a, A, e, E, f, F, g, and G conversions, leading zeros
(following any indication of sign or base) are used to pad to the field width rather
than performing space padding, except when converting an infinity or NaN. If the
0 and - flags both appear, the 0 flag is ignored. For d, i, o, u, x, and X
conversions, if a precision is specified, the 0 flag is ignored. For other
conversions, the behavior is undefined.
OK, thanks for posting this. So if I understand correctly, the above says that my compler does NOT adhere to the standard, right?

That said, I suppose there would be a workaround. This is actually an sprintf() to build a key that has 4 components, one of them a double.

So I suppose I could say:

for (count = 0; count < strlen(buffer), ++count)
{
  if buffer[count] == ' '
    buffer[count] = '0'.
}

Thanks again.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ozo,

Our data will not have negative numbers. Each entry is the total price of items requested by a customer.   We are actually storing as implied decimal. e.g. $12.34 is 1234. You may ask why we don't use longs (32-bit)?  Reason is that the limit of 4 billion and change means we could not go over $40 million and change.

FWIW, you are write about padding for negatives:
 
e.g.
HARDCODED:that is 011.2f: <  -12345.67>

Thanks...this has been a fascinating discussion. ;)
Hi Steve,

printf, fprintf, and sprintf return the number of characters written.  It's kinda ugly, but since negative numbers aren't an issue to you, that can be used to roll-your-own leading zeros.

      float V = 12345.67;
      char Buffer[20];
      int Length;

      Length = sprintf (Buffer, "%.2f", V);
      printf ("%*.*s%s", 9-Length, 9-Length, "000000000", Buffer);
      return 0;

Sanity checks to ensure that the value of 9-Length is in range is a good idea.   :)


Good Luck,
Kent
Kent,
Haven't tried this but, to the naked eye, looks pretty slick. Thanks.
Thanks, everyone for the help. I ended up using the FOR loop to convert my spaces to zeroes.