?
Solved

C format specifer for doubles with leading 0's

Posted on 2014-04-14
12
Medium Priority
?
339 Views
Last Modified: 2014-05-07
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
0
Comment
Question by:Stephen Kairys
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 2
12 Comments
 
LVL 84

Expert Comment

by:ozo
ID: 40000337
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
 
LVL 46

Assisted Solution

by:Kent Olsen
Kent Olsen earned 600 total points
ID: 40000339
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
 
LVL 4

Author Comment

by:Stephen Kairys
ID: 40000389
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
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 84

Assisted Solution

by:ozo
ozo earned 1400 total points
ID: 40000414
it looks to me like the WATCOM 11 compiler is not confoming to the ISO/IEC standard
0
 
LVL 4

Author Comment

by:Stephen Kairys
ID: 40000459
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
 
LVL 84

Expert Comment

by:ozo
ID: 40000553
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
 
LVL 4

Author Comment

by:Stephen Kairys
ID: 40000784
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
 
LVL 84

Accepted Solution

by:
ozo earned 1400 total points
ID: 40000844
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
 
LVL 4

Author Comment

by:Stephen Kairys
ID: 40001604
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
 
LVL 46

Expert Comment

by:Kent Olsen
ID: 40001637
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
 
LVL 4

Author Comment

by:Stephen Kairys
ID: 40001647
Kent,
Haven't tried this but, to the naked eye, looks pretty slick. Thanks.
0
 
LVL 4

Author Closing Comment

by:Stephen Kairys
ID: 40047544
Thanks, everyone for the help. I ended up using the FOR loop to convert my spaces to zeroes.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand and use pointers in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.
Suggested Courses

764 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question