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
LVL 4
Stephen KairysTechnical Writer - ConsultantAsked:
Who is Participating?
 
ozoConnect With a Mentor Commented:
I'd say that you can sprintf with space padding, then convert spaces to 0, except that with
negative numbers, I'd expect that WATCOM would put the spaces before the - instead of
0's after the -, which is what I understand the standard to be specifying.

Or, if WATCOM does do 0 padding when no precision is specified, then maybe you can handle the .67 part separately.  (Which may be a good practice anyway if you are trying to handle exact decimal quantities like money using approximate floating values)
0
 
ozoCommented:
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);
0
 
Kent OlsenConnect With a Mentor Data Warehouse Architect / DBACommented:
Hi Steve,

That looks like really bizarre behavior to me.  I would expect the results to be "012345.67".

Two quick things.

(I hate to ask this one.)  Are you sure that you're testing with "09.2f"?

Try it again with a larger format specifier.  "%010.2f" or "012.2f".  Or pass a value with fewer digits to the current test.  I'm wondering if the formatting might be forcing 1 space.


Kent
0
The Firewall Audit Checklist

Preparing for a firewall audit today is almost impossible.
AlgoSec, together with some of the largest global organizations and auditors, has created a checklist to follow when preparing for your firewall audit. Simplify risk mitigation while staying compliant all of the time!

 
Stephen KairysTechnical Writer - ConsultantAuthor Commented:
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
0
 
ozoConnect With a Mentor Commented:
it looks to me like the WATCOM 11 compiler is not confoming to the ISO/IEC standard
0
 
Stephen KairysTechnical Writer - ConsultantAuthor Commented:
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
0
 
ozoCommented:
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.
0
 
Stephen KairysTechnical Writer - ConsultantAuthor Commented:
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.
0
 
Stephen KairysTechnical Writer - ConsultantAuthor Commented:
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. ;)
0
 
Kent OlsenData Warehouse Architect / DBACommented:
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
0
 
Stephen KairysTechnical Writer - ConsultantAuthor Commented:
Kent,
Haven't tried this but, to the naked eye, looks pretty slick. Thanks.
0
 
Stephen KairysTechnical Writer - ConsultantAuthor Commented:
Thanks, everyone for the help. I ended up using the FOR loop to convert my spaces to zeroes.
0
All Courses

From novice to tech pro — start learning today.