comma formatted integer output (LONG POST)

S

silly

/*Thanks again to thos who helped with my
'more hand written integer pow() functions (LONG POST)' query.

I needed to write a function to write out integers and after looking at some
stuff
on the web I felt they look a bit code-heavy so...

A) If you think the code attached is reasonable, consider it a donation,
if not please lets have your comments!

The recursive pow() inspired my first attempt which looks pretty good
to me but if you see an improvement feel free. I have attempted to make
an iterative version. I wondered if there were some obvious ways of
making
it more concise.

B) An answer to the malloc query in comments in the code (after 'int
stack[3];')
would be helpful too.

Perhaps considering the following will show what I mean better...

slightly different scenario to the main code appended, here im looking
at strings. if you have:-

binstr ="101010101010101010....010101001111111"

and a function binstr_to_intstr() to create:-

intstr ="125663....137373077"

assuming you could fit intstr into an int and used pr_numi, how would
you accurately calculate the size of array needed based on the size of
binstr?
How would you declare/allocate/use the array/memory/pointer?

stack[0]=77
stack[1]=373
stack[2]=137
...
stack[n-1]=663
stack[n]=125
*/
/*--------------------start of code---------------*/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#define PR(x) printf(#x " = %d ",x)
#define NL putchar('\n')
#define SP putchar(' ')
#define DELIM ","
#define iabs(x) ( (x)>0?(x):-(x) )
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* recursive version...*/
void pr_numr( int x)
{
if (iabs(x)<1000)
printf("%3d", x);
else
{
pr_numr(x/1000);
printf(DELIM "%03d", iabs(x%1000));
}

return;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/* iterative version...*/
void pr_numi( int x)
{
int stack[3];
/*the '3' should be related to sizeof(int) (i.e. one less than?) or
some formula with lots of nice shifts?, use malloc?*/

int i=0;

if (iabs(x)<1000)
printf("%3d", x);
else
{
do {
stack[i++] =x%1000;
x/=1000;
} while (iabs(x)>1000);

printf("%3d", x);

while(--i>=0)
printf(DELIM "%03d", iabs(stack));
}

return;
}
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
int main(int argc, char **argv)
{
int x, i,m,t[] = {0, 1, 12, 123, 999,1000, 1234, 1034,
12034, 12009880, 1123034783, INT_MAX};

m= sizeof(t)/sizeof(int);

if (argc==1)
for(i=0;i<m;i++)
{
x=t;

printf("%20d: ", x);
pr_numr(x);
printf("\n%20s ", " ");
pr_numi(x);
NL;
NL;
/*now try the -ve*/
x=-x;

printf("%20d: ", x);
pr_numr(x);
printf("\n%20s ", " ");
pr_numi(x);
NL;
NL;
}
else
while(--argc>0)
{
printf("%20d: ", atol(*++argv));
pr_numr(atol(*argv));
printf("\n%20s ", " ");
pr_numi(atol(*argv));
NL;
}
return 0;
}
/*--------------------end of code-----------------*/
 
C

CBFalconer

silly said:
I needed to write a function to write out integers and after looking
at some stuff on the web I felt they look a bit code-heavy so...

.... snip code etc ...

I published the following here some time ago. Same general
purpose. Use as you see fit. It includes self testing code,
energised by defining TESTING.

#ifndef putnums_h_ /* --- file putnums.h --- */
# define putnums_h_

# ifdef __cplusplus
extern "C" {
# endif

/* Using binary as an example, code to ourput numbers
in a field, while injecting commas at intervals.

By C.B. Falconer. Put in public domain.
*/

/* ------------------- */

/* Negative field for left justification, 0 based */
/* clump is interval for group separator, 0 for none */
int putnum(FILE *fp, long v, int base,
int field, int clump);

/* ------------------- */

/* Negative field for left justification, 0 based */
/* clump is interval for group separator, 0 for none */
int putunum(FILE *fp, unsigned long v, int base,
int field, int clump);

/* Macros to ease use for decimal output */
#define putdnum(fp, v, field, clump) \
putnum(fp, v, 10, field, clump)
#define putudnum(fp, v, field, clump) \
putunum(fp, v, 10, field, clump)

# ifdef __cplusplus
}
# endif
#endif
/* --- end putnums.h --- */

/* --- file putnums.c ---

Using binary as an example, code to ourput numbers
in a field, while injecting commas at intervals.

By C.B. Falconer. Put in public domain.
*/
#include <stdio.h>
#include "putnums.h"

#ifdef TESTING /* Add in a demonstration driver */
# include <limits.h>

# define BASE 10 /* Try 2 through 16 here only */
# define GROUP 3 /* with 0, 4 or 3 here */
#endif

/* ------------------- */

/* The original call must pass in depth == 0 */
/* field is zero based, so 36 allows 37 chars */
static int putval(FILE *fp, unsigned long v, int base,
int field, int clump, int neg,
int depth)
{
int retval;
static char hexchars[16] = "0123456789abcdef";

if (depth && clump && ((depth % clump) == 0)) field--;
if ((v / base) > 0) {
retval = 1 + putval(fp, v/base, base, field,
clump, neg, depth+1);
}
else {
if (neg) field--;
while (field > depth) {
putc(' ', fp);
field--;
}
if (neg) {
putc('-', fp);
retval = 2;
}
else retval = 1;
}
/* Revise this for base value larger than 16 */
putc((v % base)[hexchars], fp);

if (depth && clump && ((depth % clump) == 0)) {
putc(',', fp);
retval++;
}
return retval;
} /* putval */

/* ------------------- */

/* Negative field for left justification, 0 based */
/* clump is interval for group separator, 0 for none */
int putnum(FILE *fp, long v, int base,
int field, int clump)
{
int retval;

if (v < 0) retval = putval(fp, -v, base, field, clump, 1, 0);
else retval = putval(fp, v, base, field, clump, 0, 0);
while ((field + retval) <= 0) {
field++;
putc(' ', fp);
}
return retval;
} /* putnum */

/* ------------------- */

/* Negative field for left justification, 0 based */
/* clump is interval for group separator, 0 for none */
int putunum(FILE *fp, unsigned long v, int base,
int field, int clump)
{
int retval;

retval = putval(fp, v, base, field, clump, 0, 0);
while ((field + retval) <= 0) {
field++;
putc(' ', fp);
}
return retval;
} /* putunum */

/* ------------------- */

#ifdef TESTING
int main(void)
{
int i, lgh;

for (i = 0; i < 50; i++) putchar('0' + i % 10);
putchar('\n');
for (i = 0; i < 12; i++) {
lgh = putnum(stdout, i, BASE, 36, GROUP);
putchar(' ');
lgh = putnum(stdout, lgh, BASE, 8, GROUP);
puts(".");
}
i = INT_MAX - 4;
do {
i++;
lgh = putnum(stdout, i, BASE, 36, GROUP);
putchar(' ');
lgh = putnum(stdout, lgh, BASE, 8, GROUP);
puts(".");
} while (i < INT_MAX);

i = INT_MIN + 4;
do {
i--;
lgh = putnum(stdout, i, BASE, 36, GROUP);
putchar(' ');
lgh = putnum(stdout, lgh, BASE, 8, GROUP);
puts(".");
lgh = putunum(stdout, (unsigned long)i, BASE, 36, 0);
putchar(' ');
lgh = putnum(stdout, lgh, BASE, 8, GROUP);
puts(".");
} while (i > INT_MIN);

lgh = putunum(stdout, 1, BASE, -36, GROUP);
putchar(' ');
lgh = putunum(stdout, lgh, BASE, 8, GROUP);
puts(".");

for (i = 0; i < 4; i++) {
lgh = putudnum(stdout, (unsigned long)-i, 36, GROUP);
putchar(' ');
lgh = putdnum(stdout, lgh, 8, GROUP);
puts(".");
lgh = putunum(stdout, (unsigned long)-i, 16, 36, 4);
putchar(' ');
lgh = putunum(stdout, lgh, BASE, -8, GROUP);
puts(".");
lgh = putunum(stdout, (unsigned long)-i, 2, -36, 4);
putchar(' ');
lgh = putunum(stdout, lgh, BASE, 8, GROUP);
puts(".");
}
return 0;
} /* main */
#endif
/* --- end putnums.c --- */
 
S

silly

silly said:
... snip code etc ...
I came up with this which is another alternative to
recursion and isnt too long...
Still prefer the recursive one though!

/*--------------------start of code---------------*/
#if (((INT_MAX/1024)/1024)/1024) == 0
/* this routine assumes INT_MAX == 2,147,483,647
* - 32 bit machines but will give a non delimited
* output for a bigger INT_MAX.
* for 16 bit, just need to delete a few lines!*/
#define pr_num_issue 9999999999999999999999999999
#else

#define K0 1
#define K1 1000
#define K2 (K1*K1)
#define K3 (K2*K1)

#define GP(x,y,z) iabs((x%y)/z)

void pr_numd(int x)
{
if(iabs(x)<K1)
printf("%3d", x);
else if(iabs(x)<K2)
printf("%3d,%03d", \
x/K1,GP(x,K1,K0));
else if(iabs(x)<K3)
printf("%3d,%03d,%03d", \
x/K2,GP(x,K2,K1),GP(x,K1,K0));
#if ((INT_MAX/K3)/K1) == 0
/* INT_MAX=2,147,483,647 for example - 32 bit machines */
/* INT_MAX=549,755,813,887 for example - 40 bit machines */
else
printf("%3d,%03d,%03d,%03d", \
x/K3,GP(x,K3,K2),GP(x,K2,K1),GP(x,K1,K0));
#else
#define K4 (K3*K1)
else if(iabs(x)<K4)
printf("%3d,%03d,%03d,%03d", \
x/K3,GP(x,K3,K2),GP(x,K2,K1),GP(x,K1,K0));
else /*cop out - enough recursion unwinding for now!*/
printf("%d", x);
#endif
#endif
}
/*--------------------end of code-----------------*/
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,528
Members
45,000
Latest member
MurrayKeync

Latest Threads

Top