views:

89

answers:

4

I'm converting a double to a char string:

char txt[10];
double num;

num = 45.344322345

sprintf(txt, "%.1f", num);

and using ".1f" to truncate the decimal places, to the tenths digit.
i.e. - txt contains 45.3

I usually use precision in sprintf to ensure the char buffer is not overflowed. How can I do that here also truncating the decimal, without using snprintf?

(i.e. if num = 345694876345.3 for some reason)

Thanks

EDIT If num is > buffer the result no longer matters, just do not want to crash. Not sure what would make the most sense in that case.

EDIT2 I should have made it more clear than in just the tag, that this is a C program. I am having issues using snprintf in a C program. I don't want to add any 3rd party libraries.

+1  A: 

Why do you want to do it without snprintf? You should be using snprintf regardless of whether your format string contains a double, another string or anything else, really. As far as I can see, there's no reason not to.

Dean Harding
+5  A: 

Use snprintf() , which will tell you how many bytes were not printed. In general, you should size your array to be large enough to handle the longest string representation of the target integer type. If not known in advance, use malloc() (or asprintf(), which is non-standard, but present on many platforms).

Edit

snprintf() will fail gracefully if the format exceeds the given buffer, it won't overflow. If you don't need to handle that, then simply using it will solve your problem. I can't think of an instance where you would not want to handle that, but then again, I'm not working on whatever you are working on :)

Tim Post
+1  A: 

If you absolutely must do it on your own, count the digits in the number before trying to convert:

int whole = num;
int wholeDigits = 0;
do {
    ++wholeDigits;
}
while (whole /= 10);

double fraction = num - (int) num;
int decimallDigits = 0;
while (fraction > 0) {
    ++decimalDigits;
    fraction *= 10;
    fraction = fraction - (int) fraction;
}

int totalLength = decimalDigits ? wholeDigits + decimalDigits + 1 : wholeDigits;

You should probably verify that this ad-hoc code works as advertised before relying on it to guard against crashes. I recommend that you use snprintf or something similar instead of my code, as others have said.

Jon
+3  A: 

Why not just make your buffer big enough to hold the largest possible string representation of a double?

Assuming a 64-bit double using the IEEE standard for floating point arithmetic, which uses 52 bits for a mantissa: 2^52 = 4,503,599,627,370,500. So we need 16 characters to hold all the digits before and after the decimal point. 19 considering the decimal point, sign character and null terminator.

I would just use a buffer size of at least 20 characters and move on.

If you need to print a double using scientific notation, you will need to add enough space for the exponent. Assuming a 11 bit signed exponent, that's another 4 characters for the exponent plus a sign for the exponent and the letter 'E'. I would just go with 30 characters in that case.

Ferruccio
I'd just make it 40 and move on. Unless it's an array, that 40 bytes is a lot cheaper than your time. But I like snprintf too.
progrmr