Solved

C format specifer for doubles with leading 0's

Posted on 2014-04-14
12
325 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
  • 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 45

Assisted Solution

by:Kdo
Kdo earned 150 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
 
LVL 84

Assisted Solution

by:ozo
ozo earned 350 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
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
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 350 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 45

Expert Comment

by:Kdo
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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

This tutorial is posted by Aaron Wojnowski, administrator at SDKExpert.net.  To view more iPhone tutorials, visit www.sdkexpert.net. This is a very simple tutorial on finding the user's current location easily. In this tutorial, you will learn ho…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand opening and writing to files in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.

705 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now