How to separate numbers in three-digit groups in C

How to separate numbers in three-digit groups in C

Post by Rouben Rostami » Tue, 25 Jun 1991 02:45:50



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 wish the printf function had an option for such formatting, but
as far as I know, it doesn't.  

I guess the ideal solution would be to extend the format options
for the printf command.  Perhaps a Printf function may be defined which
accepts the standard formatting strings of the printf function, but which
also accepts additional conversion characters to print comma-separated
digits.  I do not wish to re-invent the wheel if someone has already done
this.  So please let me know if there is something similar available somewhere.

--
Rouben Rostamian                          Telephone: (301) 455-2458
Department of Mathematics and Statistics  e-mail:


 
 
 

How to separate numbers in three-digit groups in C

Post by Hopelessly in love w/Donna Re » Tue, 25 Jun 1991 08:40:54


[This should have been posted to comp.lang.c; I have directed followups there.]


Quote:

>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 wish the printf function had an option for such formatting, but
>as far as I know, it doesn't.  

This function will work.  It assumes the number is contained in a string
(which you can do by using sprintf()) --

    void commas (char *s)
    {
        char *p = index (s, '.');
        int count;

        if (p)
            *p = '\0';                  /* ignore fractional part for now */

        count = strlen (s);            

        while (count-- > 0) {
            putchar (*s++);
            if (count > 0 && count % 3 == 0)
                 putchar (',');
        }
        if (p)
            printf (".%s", p+1);              /* print out fractional part */
    }

Here's the output of the short program I wrote to test this:

Script started on Sun Jun 23 16:37:37 1991
manray% a.out
enter string: 123
123
enter string: 1234
1,234
enter string: 123456
123,456
enter string: 12345678901
12,345,678,901
enter string: 34.2732
34.2732
enter string: 35276.28321
35,276.28321
enter string: ^C
manray% exit
script done on Sun Jun 23 16:38:03 1991

"Let the fools have their tartar sauce."      |          Dave Stein



 
 
 

How to separate numbers in three-digit groups in C

Post by Arthur Neils » Wed, 26 Jun 1991 14:15:35


In article <1991Jun23.174550.14...@umbc3.umbc.edu> rou...@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: a...@pilikia.pegasus.com
Bank of Hawaii Tech Support     | UUCP: uunet!ucsd!nosc!pilikia!art