Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Q: printing 23567 as 23,567??

1 view
Skip to first unread message

Jason Owen

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
Hello -- I have a situation where I need to print an integer
(on the screen) with the format of using commas -- like

98798798 ----> 98,798,798

The integers will range from 1 to 9 digits in length.

I can't find any formating available for this with the printf
statement, and I can't think of anyway way to do it aside from
picking off each digit, storing, and then printing them one
by one w/ the necessary commas on the screen. Note that I only
need to print the integer this way -- no other operations are needed
in this format.

Does anyone have some suggestions or canned routines?

Thanks,

Jason

Dann Corbit

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
"Jason Owen" <jo...@hopper.unh.edu> wrote in message
news:8abm1h$df9$1...@tabloid.unh.edu...

There is no format specifier for separating groups of powers of 3. There
may be something in snippets for that -- I have not looked. It seems pretty
trivial to write it, in any case.
--
C-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
"The C-FAQ Book" ISBN 0-201-84519-9
C.A.P. Newsgroup http://www.dejanews.com/~c_a_p
C.A.P. FAQ: ftp://38.168.214.175/pub/Chess%20Analysis%20Project%20FAQ.htm

-hs-

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
Jason Owen a écrit dans le message <8abm1h$df9$1...@tabloid.unh.edu>...

>Hello -- I have a situation where I need to print an integer
>(on the screen) with the format of using commas -- like
>
>98798798 ----> 98,798,798
>
>The integers will range from 1 to 9 digits in length.
>
>I can't find any formating available for this with the printf
>statement, and I can't think of anyway way to do it aside from
>picking off each digit, storing, and then printing them one
>by one w/ the necessary commas on the screen. Note that I only
>need to print the integer this way -- no other operations are needed
>in this format.
>
>Does anyone have some suggestions or canned routines?

Not so trivial:

#include <stdio.h>
#include <string.h>
#include <limits.h>

static void putcommas(char *const s,size_t len, long l)
{
#define MAX (1000*1000L)
char *ps=s;
unsigned long d=MAX;
int first=1;

*ps=0;

while(d)
{
char sz[20];

if (l/d)
{
if (first)
{
first=0;
sprintf(sz,"%lu",(long)(l/d)%1000L);
}
else
{
sprintf(sz,"%03lu",(long)(l/d)%1000L);
}
strncat(s,sz,len);
strncat(s,",",len);
}
d/=1000;
}
s[strlen(s)-1]=0;
}

int main (void)
{
unsigned long i;

for (i=123;i<LONG_MAX;i*=7)
{

char s[40];

putcommas(s,sizeof s, i);

printf("%lu %s\n"
,(long)i
,(char*)s
);
}
return 0;
}

123 123
861 861
6027 6,027
42189 42,189
295323 295,323
2067261 2,067,261
14470827 14,470,827
101295789 101,295,789
709070523 709,070,523
668526365 668,526,365
384717259 384,717,259


--
-hs-
CLC-FAQ: http://www.eskimo.com/~scs/C-faq/top.html
ISO-C Library: http://www.dinkum.com/htm_cl
"It's specified. But anyone who writes code like that should be
transmogrified into earthworms and fed to ducks." -- Chris Dollin CLC


-hs-

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
-hs- a écrit dans le message <8abph9$1r90$1...@news5.isdnet.net>...

mmm... to be consistent, all longs should be 'unsigned long'.

Steven Huang

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
Jason Owen (jo...@hopper.unh.edu) wrote:
> Hello -- I have a situation where I need to print an integer
> (on the screen) with the format of using commas -- like

> 98798798 ----> 98,798,798

> The integers will range from 1 to 9 digits in length.

[...]


> Does anyone have some suggestions or canned routines?

Here's a simple hack:

#include <stdio.h>

char *comma_insert(unsigned long number)
{
static char buf[12], *p;

sprintf(buf, "%03lu,%03lu,%03lu", number / 1000000L,
(number / 1000) % 1000, number % 1000);
for (p = buf; *p < '1' || *p > '9'; p++);

return p;
}

It contains a couple of significant problems, just in case you're
trying to get somebody else to do your homework.

Jason Owen

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
Thanks for everyone's help... BTW, I'm not a college
student, just a lowly assistant professor who never took
a C class for credit.

Jason
--
W. Jason Owen Assistant Prof. of Statistics
Dept. of Math. and Statistics jo...@math.unh.edu
University of New Hampshire http://www.math.unh.edu/~jowen
Durham, NH 03824 (603)862-4766 ...2-4096 (FAX)

Dann Corbit

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
"Jason Owen" <jo...@hopper.unh.edu> wrote in message
news:8abtvi$g9a$1...@tabloid.unh.edu...

> Thanks for everyone's help... BTW, I'm not a college
> student, just a lowly assistant professor who never took
> a C class for credit.

In that case, have a look at commafmt() from the Snippets collection:
/* +++Date last modified: 05-Jul-1997 */

/*
** COMMAFMT.C
**
** Public domain by Bob Stout, bug fixes by Mark Kamradt
**
** Notes: 1. Use static buffer to eliminate error checks on buffer
** overflow and reduce code size.
** 2. By making the numeric argument a long and prototyping it
** before use, passed numeric arguments will be implicitly
** cast to longs thereby avoiding int overflow.
** 3. Use the thousands grouping and thousands separator from
** the ANSI locale to make this more robust.
*/

#include <string.h>

size_t
commafmt (char *buf, /* Buffer for formatted string */
int bufsize, /* Size of buffer */
long N)
{ /* Number to convert */
int len = 1, posn = 1, sign = 1;
char *ptr = buf + bufsize - 1;

if (2 > bufsize)
{
ABORT:
*buf = 0;
return 0;
}
*ptr-- = 0;
--bufsize;
if (0L > N)
{
sign = -1;
N = -N;
}
for (; len <= bufsize; ++len, ++posn)
{
*ptr-- = (char) ((N % 10L) + '0');
if (0L == (N /= 10L))
break;
if (0 == (posn % 3))
{
*ptr-- = ',';
++len;
}
if (len >= bufsize)
goto ABORT;
}

if (0 > sign)
{
if (len >= bufsize)
goto ABORT;
*ptr-- = '-';
++len;
}
memmove (buf, ++ptr, len + 1);
return (size_t) len;
}

#ifdef UNIT_TEST

#include <stdio.h>
#include <stdlib.h>

int main (int argc, char *argv[])
{
size_t len;
char buf[20];
long N;
int retval = EXIT_SUCCESS;
if (argc > 1)
{
N = strtol (argv[1], NULL, 10);
len = commafmt (buf, 20, N);
printf ("%s converts to %s and returned %d\n", argv[1], buf, len);
}
else
{
retval = EXIT_FAILURE;
puts ("Usage: commafmt <number>");
}
return retval;
}

#endif /* TEST */

Dann Corbit

unread,
Mar 10, 2000, 3:00:00 AM3/10/00
to
"Gregory Pietsch" <gk...@flash.net> wrote in message
news:38C9A217...@flash.net...

> Jason Owen wrote:
> >
> > Hello -- I have a situation where I need to print an integer
> > (on the screen) with the format of using commas -- like
> >
> > 98798798 ----> 98,798,798
> >
> > The integers will range from 1 to 9 digits in length.
> >
> > I can't find any formating available for this with the printf
> > statement, and I can't think of anyway way to do it aside from
> > picking off each digit, storing, and then printing them one
> > by one w/ the necessary commas on the screen. Note that I only
> > need to print the integer this way -- no other operations are needed
> > in this format.
> >
> > Does anyone have some suggestions or canned routines?
> >
> > Thanks,
> >
> > Jason
>
> Here's a quick hack. Study it very carefully so you can figure out how
> it does what it does:
>
> #include <stdio.h>
> #include <string.h>
>
> #define STATIC_CHAR_BUFSIZ 16 /* for a little extra */
>
> char *ulfmt(unsigned long x)
> {
> static char retbuf[STATIC_CHAR_BUFSIZ];
> char rawbuf[STATIC_CHAR_BUFSIZ];
> char *p = rawbuf, *q = retbuf;
> size_t len;
>
> sprintf(p, "%lu", x);
> len = strlen(p); /* don't trust sprintf's return value */
> switch (len % 3) {
> do {
> *q++ = ',';
> case 0: *q++ = *p++;
> case 2: *q++ = *p++;
> case 1: *q++ = *p++;
> } while (*p);
> }
> *q = '\0';
> return retbuf;
> }
I suspect that this example will be quite a puzzle for someone who does not
immediately know how to insert a comma into a string every 3 places. I did
go to the web site he listed and he really is an assistant professor, so
it's not just some goon trying to weasel out of a homework assignment. I
suppose the professor could be taking a class, but he gave his real name so
I doubt it.

This question (from the C FAQ) will help understand "Duff's comma insertion
device" {above}:

20.35: What is "Duff's Device"?

A: It's a devastatingly deviously unrolled byte-copying loop,
devised by Tom Duff while he was at Lucasfilm. In its "classic"
form, it looks like:

register n = (count + 7) / 8; /* count > 0 assumed */
switch (count % 8)
{
case 0: do { *to = *from++;
case 7: *to = *from++;
case 6: *to = *from++;
case 5: *to = *from++;
case 4: *to = *from++;
case 3: *to = *from++;
case 2: *to = *from++;
case 1: *to = *from++;
} while (--n > 0);
}

where count bytes are to be copied from the array pointed to by
from to the memory location pointed to by to (which is a memory-
mapped device output register, which is why to isn't
incremented). It solves the problem of handling the leftover
bytes (when count isn't a multiple of 8) by interleaving a
switch statement with the loop which copies bytes 8 at a time.
(Believe it or not, it *is* legal to have case labels buried
within blocks nested in a switch statement like this. In his
announcement of the technique to C's developers and the world,
Duff noted that C's switch syntax, in particular its "fall
through" behavior, had long been controversial, and that "This
code forms some sort of argument in that debate, but I'm not
sure whether it's for or against.")

Gregory Pietsch

unread,
Mar 11, 2000, 3:00:00 AM3/11/00
to

Gregory Pietsch

unread,
Mar 11, 2000, 3:00:00 AM3/11/00
to
Dann Corbit wrote:
>
> "Gregory Pietsch" <gk...@flash.net> wrote in message
> news:38C9A217...@flash.net...

Dann, you broke the code! Don't you know you're supposed to make the
answers as cryptic and as Zen-like as possible so that the newbies have
an intellectual challenge? ;-)

I discovered a couple of years ago that Duff's Device could be used for
comma insertion, as the switch part simply tells where in the loop to
start. I showed this to a couple of newbies and got a response like I
was an insane coder. I then showed them the Duff's Device page on the
Lysator site as prior art and instantly everyone was enlightened. It
helps to read the FAQ every once in a while....

Later, Gregory Pietsch

0 new messages