tags:

views:

265

answers:

7

Hey, if I had this code:

printf( "%8.2f" , .23 );

It outputs 0.23. How do I get it to simply output .23?

Thanks.

+15  A: 

The C standard says that for the f and F floating point format specifiers:

If a decimal-point character appears, at least one digit appears before it.

I think that if you don't want a zero to appear before the decimal point, you'll probably have to do something like use snprintf() to format the number into a string, and remove the 0 if the formatted string starts with "0." (and similarly for "-0."). Then pass that formatted string to our real output. Or something like that.

Michael Burr
+2  A: 

it is not possible to do it only using printf. The printf standard says :

f  - "double" argument is output in conventional form, i.e.
     [-]mmmm.nnnnnn
     The default number of digits after the decimal point is six,
     but this can be changed with a precision field. If a decimal point
     appears, at least one digit appears before it. The "double" value is
     rounded to the correct number of decimal places.

Note the If a decimal point appears, at least one digit appears before it

Therefore it seems you have to handcode your own formatter.

Jerome WAGNER
A: 

This'll do the trick:

double a;
printf( ".%d", (int)modf(0.23,&a) );
dmb
What's in b, since it was not initialized? I don't get it.
MJB
Nope, that doesn't work. `modf` will return the fractional part, but it's still a fraction, so casting it to `int` just turns it into a `0`.
tzaman
It's just a throw away parameter for modf. After this it points to a double that contains the integral portion of `0.23` (i.e. 0)
dmb
@tzaman right you are -- apologies, all!
dmb
I don't think this is a bad idea though, to use %d. You just did it wrong. You should be extracting the decimal portion by multiplying by 100 and then doing mod 100. Also, you need to be careful that a negative number displays a negative sign.
frankc
A: 
double f = 0.23;

assert(f < 1 && f >= 0);  
printf(".%u\n" , (unsigned)((f + 0.005) * 100));
J.F. Sebastian
A: 

There isn't any format string specifier to remove that leading 0, so you'll have to roll your own; This is the shortest thing I can think of:

char s[10];
sprintf(s, "%.2f", .23);
printf("%8s", (s[0] == '0' ? &s[1] : s));
tzaman
That won't work for negative numbers. Also, 10 chars may or may not be enough for floating point numbers depending on the actual platform's float representation so you should use snprintf() to avoid buffer overflows.
Adisak
A: 
#include <stdio.h>

static void printNoLeadingZeros(double theValue)
{
   char buffer[255] = { '\0' };

   sprintf(buffer, "%.2f", theValue);

   printf("%s\n", buffer + (buffer[0] == '0'));
}

int main()
{
   double values[] = { 0.23, .23, 1.23, 01.23, 001.23, 101.23 };
   int n           = sizeof(values) / sizeof(values[0]);
   int i           = 0;

   while(i < n)
      printNoLeadingZeros(values[i++]);

   return(0);
}
Won't the `sizeof(values)` return the size of the pointer, not the actual array?
Christian Mann
@ChristianMann: Depends on if you are in C or C++ mode of your compiler, I think.
Ben Voigt
A: 

It looks there is no easy solution. I would probably use something like code below. It is not the fastest method, however it should work with many different formats. It preserves number of char and position of dot too.

#include <stdio.h>

void fixprint(char *s)
{
        size_t i;
        i = 1;
        while (s[i]=='0' || s[i]==' ' || s[i]=='+' || s[i]=='-') {
                if (s[i]=='0') s[i]=' ';
                i++;
        }
}

int main()
{
        float x = .23;
        char s[14];
        sprintf(s,"% 8.2f",x);
        fixprint(s);
        printf("%s\n",s);
}
Michas