How to separate numbers in three-digit groups in C
Arthur Neilson
art at pilikia.pegasus.com
Tue Jun 25 15:15:35 AEST 1991
In article <1991Jun23.174550.14820 at umbc3.umbc.edu> rouben at math16.math.umbc.edu (Rouben Rostamian) writes:
>
>I need help with printing numbers (floating or integer) in C. I would like
>to display the numbers in three-digit comma-separated format. For instance,
>the integer 12345678 should be printed as 12,345,678. The floating point
>number 1234.56789 may be printed as 1,234.5678 or as 1,234.567,8.
I use the function below quite a bit, it formats doubles in a char buffer
according to a picture clause type specification. I didn't write it, I
got it off the net a long time ago and forget where it came from.
-----8<----- cut here -----8<----- cut here -----8<----- cut here -----8<-----
/*
* f o r m a t
*
* Format double value as char string in buffer based
* on the picture format passed in the format string.
*
* Recognised format characters:
*
* * Digit or asterisk prefix
* $ Digit or dollar-sign prefix
* - Digit or minus-sign prefix if negative
* + Digit or sign prefix
* ( Digit or left-parenthesis prefix if negative
* # Digit or blank prefix
* & Digit or zero prefix
* ) Right-parenthesis suffix if negative
* . Decimal point
* , Comma or space prefix
* < Digit or space appended after format (left justification)
*
* This function uses only fabs(), fmod(), and floor(),
* it should be compatible with any system that has a
* standard C math library.
*/
#include <math.h>
char *
format(buf, fmt, val)
char *buf;
char *fmt;
double val;
{
double decval;
int didlead, didsign, pad, signum, overflow;
register char *fmtp, *bufp, *decp;
char tbuf[1024];
char *retp = buf;
signum = (val < 0.0);
val = fabs(val);
for (decp = fmt; *decp; decp++)
if (*decp == '.')
break;
/*
* Make a first pass to calculate a rounding value.
*/
decval = 0.5;
for (fmtp = decp; *fmtp; fmtp++) {
switch (*fmtp) {
case '*':
case '$':
case '-':
case '+':
case '(':
case '#':
case '&':
case '<':
decval /= 10.0;
break;
}
}
val += decval;
fmtp = decp;
decval = val - floor(val);
val = floor(val);
pad = 0;
didlead = 0;
didsign = 0;
bufp = tbuf;
while (fmtp != fmt) {
switch (*--fmtp) {
case '#':
case '<':
if (val < 1.0) {
if (*fmtp == '<')
pad++;
else
*bufp++ = ' ';
break;
}
/* FALLTHROUGH */
case '&':
*bufp++ = (int) fmod(val, 10.0) + '0';
val /= 10.0;
break;
case '*':
if (val >= 1.0) {
*bufp++ = (int) fmod(val, 10.0) + '0';
val /= 10.0;
break;
}
*bufp++ = (didlead ? ' ' : '*');
didlead = 1;
break;
case '$':
if (val >= 1.0) {
*bufp++ = (int) fmod(val, 10.0) + '0';
val /= 10.0;
break;
}
*bufp++ = (didlead ? ' ' : '$');
didlead = 1;
break;
case '-':
if (val >= 1.0) {
*bufp++ = (int) fmod(val, 10.0) + '0';
val /= 10.0;
break;
}
*bufp++ = (didsign ? ' ' : (signum ? '-' : ' '));
didsign = 1;
break;
case '+':
if (val >= 1.0) {
*bufp++ = (int) fmod(val, 10.0) + '0';
val /= 10.0;
break;
}
*bufp++ = (didsign ? ' ' : (signum ? '-' : '+'));
didsign = 1;
break;
case '(':
if (val >= 1.0) {
*bufp++ = (int) fmod(val, 10.0) + '0';
val /= 10.0;
break;
}
*bufp++ = (didsign ? ' ' : (signum ? '(' : ' '));
didsign = 1;
break;
case ')':
*bufp++ = (signum ? ')' : ' ');
break;
case ',':
*bufp++ = (val < 1.0 ? ' ' : ',');
break;
default:
*bufp++ = *fmtp;
}
}
overflow = (val >= 1.0);
while (bufp-- != tbuf)
*buf++ = (overflow ? '*' : *bufp);
/*
* Decimals turn out to be easy, since we can parse forward and all
* the potential digit chars can be treated as "&". Also, extracting
* digits is done via (decval *= 10.0; floor(decval)) instead of slow
* fmod().
*/
while (*decp) {
if (overflow)
*buf++ = '*';
else {
switch (*decp) {
case '*':
case '$':
case '-':
case '+':
case '(':
case '#':
case '&':
case '<':
decval *= 10.0;
*buf++ = (int) floor(decval) + '0';
decval -= floor(decval);
break;
case ')':
*buf++ = (signum ? ')' : ' ');
break;
default:
*buf++ = *decp;
break;
}
}
decp++;
}
while (pad--)
*buf++ = (overflow ? '*' : ' ');
*buf = '\0';
return (retp);
}
-----8<----- cut here -----8<----- cut here -----8<----- cut here -----8<-----
--
Arthur W. Neilson III | INET: art at pilikia.pegasus.com
Bank of Hawaii Tech Support | UUCP: uunet!ucsd!nosc!pilikia!art
More information about the Comp.unix.questions
mailing list