Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!ucbvax!pasteur!dog.ee.lbl.gov!nosc!humu!pilikia!art From: art@pilikia.pegasus.com (Arthur Neilson) Newsgroups: comp.unix.questions Subject: Re: How to separate numbers in three-digit groups in C Message-ID: <1991Jun25.051535.12678@pilikia.pegasus.com> Date: 25 Jun 91 05:15:35 GMT References: <1991Jun23.174550.14820@umbc3.umbc.edu> Organization: Pilikia, Honolulu Lines: 203 In article <1991Jun23.174550.14820@umbc3.umbc.edu> rouben@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 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@pilikia.pegasus.com Bank of Hawaii Tech Support | UUCP: uunet!ucsd!nosc!pilikia!art