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
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
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
mmm... to be consistent, all longs should be 'unsigned long'.
> 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
--
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)
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 */
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.")
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