There is not a function within the standard library to handle this.
Formatting currency strings is a rather complicated thing to do correctly
due to the format differing wildly from one locale to another. Some
operating systems provide functions to format currencies based on locale
but that is a little OT. If you are doing a platform specific thing then
ask some of the gurus in the newsgroup for your platform. Here is a general
function that formats unsigned numbers based on grouping and a separator.
It could be extended to handle currencies pretty easily; however, if you
have to handle localized currencies, then read your documentation on
setlocale() and localeconv(). These standard functions will provide you
with enough information to format currencies, numbers, dates, and times
with respect to a specific locale.
Anyway, here is a function that will format numbers into a buffer for
you.
void
number_to_buffer (unsigned long n, char *buffer, int digits_per_segment,
char separator)
{
unsigned long multiple; /* the multiple of 10 to use */
long int cursegment; /* largest power of multiple < n */
char *p; /* insertion pointer into buffer */
long int digits; /* current segment */
int nsegments; /* number of three digit segments */
char formatstr[32]; /* the format string for each segment */
/* Set up our parameters. */
p = buffer;
*p = '\0';
multiple = pow(10, digits_per_segment);
/* Set up a printf-style format string to handle zero padding
* each segment (i.e., formatstr = "%03d").
*/
sprintf(formatstr, "%%0%dd", digits_per_segment);
/* Figure out how many segments we have in n. */
nsegments = ((int)log10((double)n)) / digits_per_segment;
if (nsegments > 0) {
/*
* `n'' requires more than one segment, so handle each
* segment separately within a loop. We have to handle the
* first segment separately since it doesn't require zero
* padding. We also prime ``cursegment'' as the highest
* power of ``multiple'' that is less than or equal to
* ``n'' here.
*/
cursegment = pow(multiple, nsegments);
digits = n / cursegment;
p += sprintf(p, "%ld", digits);
*p++ = separator;
n -= (digits * cursegment);
cursegment /= multiple;
--nsegments;
/* Spin for the remaining powers of 1000 within n. */
while (nsegments != 0) {
digits = n / cursegment;
p += sprintf(p, formatstr, digits);
*p++ = separator;
n -= (digits * cursegment);
cursegment /= multiple;
--nsegments;
}
/* Place the final trailing digits on. */
sprintf(p, formatstr, n);
} else {
/* n only requires one segment so no leading zeros are
* necessary.
*/
sprintf(p, "%ld", n);
}
}
It isn't exactly the safest function in the world since it will gladly
clobber buffers that are too short, but it does the job. Here is a little
example of using it:
number_to_buffer(12012012UL, buffer, 3, ',');
printf("%s\n", buffer);
/* prints 12,012,012 */
You'll have to extend it to handle negative numbers (if necessary). Also
note that -1.23 dollars is usually displayed as ``($1.23)'' as opposed
to ``-$1.23''. I guess the handling will depend on how technically correct
you have to be.
On Windows, you can also use GetNumberFormat to format numbers
TCHAR szBuff[20];
TCHAR szNum[] = "10000";
NUMBERFMT nf;
nf.NumDigits = 0; // no decimal
nf.LeadingZero = 0;
nf.Grouping = 3;
nf.lpDecimalSep = ".";
nf.lpThousandSep = ","; // Thousand separator
nf.NegativeOrder = 0; // This will display as (10,000) if it is a -ve
value. See LCTYPE constants for more info.
int iRet = GetNumberFormat(NULL, 0, szNum, &nf, szBuff, sizeof(szBuff) );
TRACE("Return Value : %d Buffer: %s\n", iRet, szBuff);
You can use the GetLocaleInfo API to determine the thousand separator.
TCHAR szThousandSep[10];
GetLocaleInfo(LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szThousandSep,
sizeof(szThousandSep));