[net.sources] Number

jrife@fthood (09/13/85)

Well, I felt it was time to inflict some of my useless work upon net.sources,
in the form of a slight variation on the already relatively useless "number"
program, in most games directories.  The manual explains most of what you need
to know, but one of the differences is the ability to use it for slightly
useful purposes.

Declare:
char words[BUFSIZ];
as a global, and now you, too, can interface this function with other useless
programs.  Have fun.


--

					*********************************
					*				*
					* Jeff Rife			*
					* ihnp4!uiucuxc!fthood!jrife	*
					*				*
					* "Gene Simmons never had a	*
					*  personal computer when	*
					*  he was a kid."		*
					*	    --Berke Breathed	*
					*				*
					*********************************

-----Cut Here-----Cut Here-----Cut Here-----Cut Here-----
#!/bin/sh
# shar:	Shell Archiver
#	Run the following text with /bin/sh to create:
#	number.c
#	number.l
sed 's/^X//' << '(c)1985  K.S.A.F. Ltd.' > number.c
X#include <stdio.h>
X
X#define	    TRUE	1
X#define	    FALSE	0
X
Xchar words[BUFSIZ];
Xstatic char Sccsid[] = "@(#)number.c	1.0(fthood!jrife)   09/11/85";
X
Xmain(argc,argv)
Xint  argc;
Xchar *argv[];
X{
Xdouble n;			    /* Holds number for pass to ftow */
Xchar *numb;			    /* Pointer to return from number */
Xint thend;			    /* Flag for ordinal numbers */
X
Xextern char *ftow();
Xextern double atof();
X
Xif (argc < 2)			    /* Got to name something on command line */
X    {
X    fprintf(stderr,"number: Usage \"number [-o] n1 [-o] [n2 ...]\"\n");
X    exit(-1);
X    }
X
Xwhile (--argc)				/* While there are arguments left */
X    {
X    if (argv[1][0] == '-')		/* Simple test for only option */
X	{
X	if (argv[1][1] != 'o')
X	    {
X	    fprintf(stderr,"number: Usage \"number [-o] n1 [-o] [n2 ...]\"\n");
X	    exit(-1);
X	    }
X	else
X	    {
X	    thend = TRUE;		/* Ordinal numbers wanted */
X	    ++argv;			/* Get next arg */
X	    --argc;
X	    }
X	}
X    else
X	thend = FALSE;			/* Normal stuff */
X
X    n = atof(argv[1]);			/* Get a float for ftow */
X    numb = ftow(n,thend);		/* Generate the words */
X    printf("%s\n",numb);		/* Print it */
X    ++argv;				/* Next arg */
X    }
Xexit(0);				/* We gone bye-bye */
X}
X
Xstatic char *units[] =			/* Table for name of each */
X    {					/*  three-digit group */
X    " Trillion",
X    " Billion",
X    " Million",
X    " Thousand",
X    "\0\0\0\0\0"
X    };
X
Xstatic char *numbers[] =		/* Names of numbers that are unique */
X    {
X    "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
X    "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen",
X    "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty",
X    "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
X    };
X
Xstatic char *ord[] =			/* Ordinal number coding table */
X    {
X    "+th","First","Second","Third","+th","Fifth","+th","+th","+h",
X    "Ninth","+th","+th","+th","+th","+th","+th","+th","+th","+th","+th"
X    };
X
X
X/*
X    Routine to convert the number to words
X    Entry:
X	x = double precision number to convert
X	ordflag = do you want ordinal numbers? (0 = no, !0 = yes)
X    Returns:
X	A character pointer to the words
X*/
Xchar *ftow(x,ordflag)
Xdouble x;
Xint ordflag;
X{
Xregister int i;				/* Loop counter */
Xchar numb[25];				/* Holds printf'ed number */
Xchar hold[30];				/* Gets 3 digit grouping */
Xint  negflag = FALSE;			/* Is number negative? */
Xint  n;					/* All around number */
X
Xextern void thcon();			/* Convert each thousands group */
X
Xwords[0] = '\0';			/* Initialize for strcat */
X
Xif (x >= 1e15)				/* More than one quadrillion */
X    {
X    strcpy(words,"Overflow");
X    return(words);
X    }
X
Xif (x < 0)				/* Just tack "Negative" on, */
X    {
X    strcpy(words,"Negative ");
X    x = -x;				/*  and convert the positive */
X    negflag = TRUE;			/* But let rest of the routine know */
X    }
X
Xsprintf(numb,"%23.7f",x);		/* Put number into printable form */
Xfor (i = 0; numb[i] == ' '; ++i)	/* Tack on leading zeros */
X    numb[i] = '0';
X
Xif (x < 1)
X    strcat(words,numbers[0]);		/* Add a "Zero" if it is less than 1 */
Xelse
X    {
X    for (i = 0; i < 5; i++)		/* Loop through each thousands group */
X	{
X	sscanf(&numb[i*3],"%3d",&n);	/* Get number less than one thousand */
X	thcon(hold,n);			/* Convert it */
X	if (*hold != '\0')		/* If it isn't zero */
X	    {
X	    if (words[0] != '\0')	/* If it isn't the first word */
X		{
X		if (!negflag)		/* If the last word wasn't "Negative" */
X		    strcat(words,", "); /* Add a comma */
X		strcat(words,hold);	/* Then add the words */
X		negflag = FALSE;	/* No more "Negative" */
X		}
X	    else
X		strcpy(words,hold);	/* Use copy if it is the first word */
X	    strcat(words,units[i]);	/* And tack on the "Million", etc */
X	    }
X	}
X    }
Xsscanf(&numb[16],"%d",&n);		/* Check for stuff after the decimal */
Xif (n != 0)				/* If there is stuff */
X    {
X    strcat(words," Point");		/* Add decimal point */
X    for (i = 16; numb[i] != '\0'; i++)	/* Get to end of number */
X	;
X    i--;
X    while (numb[i] == '0')		/* Strip off trailing zeros */
X	i--;
X    numb[i+1] = '\0';
X    for (i= 16; numb[i] != '\0'; i++)	/* Pull off one digit at a time */
X	{
X	strcat(words," ");		/* Add the space */
X	n = numb[i] - '0';		/* And convert to decimal */
X	strcat(words,numbers[n]);	/* Tack on the right number */
X	}
X    }
Xelse					/* If there ain't no decimals */
X    {
X    if (ordflag)			/* And you want ordinals */
X	{
X	for (i = 0; words[i] != '\0'; ++i)  /* Get to end of words */
X	    ;
X	i--;
X	if (words[i] == 'y')		/* If it is a "Twenty", etc */
X	    {
X	    words[i] = '\0';		/* Change the "y" to "ieth" */
X	    strcat(words,"ieth");
X	    }
X	else				/* Search for beginning of last word */
X	    {
X	    while(words[i-1] != ' ' && words[i-1] != '-' && i > 0)
X		i--;
X	    for (n = 0; n < 20; n++)	/* Find out what the last word is */
X		if (strcmp(&words[i],numbers[n]) == 0)
X		    break;
X	    if (n > 19)			/* If we can't figure out what it is */
X		strcat(words,"th");	/*  just add a "th" */
X	    else
X		{
X		if (ord[n][0] == '+')	/* Plus = cat the rest of the string */
X		    strcat(words,&ord[n][1]);
X		else			/* Otherwise make an entire replace */
X		    {
X		    words[i] = '\0';
X		    strcat(words,ord[n]);
X		    }
X		}
X	    }
X	}
X    }
X
Xfor (n = 0; ; n = i)			/* Divide words up into < 80 byte */
X    {					/*  sections separated by a newline */
X    for (i = n; i < n+80; ++i)
X	if (words[i] == '\0')
X	    return(words);
X    while (words[i] != ' ')
X	--i;
X    words[i] = '\n';
X    }
X}
X
X/*
X    Routine to convert a number less than one thousand into words.  Basic
X    routine, because all groups of three digits similar.
X    Entry:
X	buf = a place to put the converted number
X	z = the number to convert
X    Return:
X	Nothing
X*/
X
Xvoid thcon(buf,z)
Xregister int z;
Xchar buf[];
X{
Xregister int d;			    /* The divided down number */
Xregister int spflag = FALSE;	    /* Do we need a space catted? */
X
Xbuf[0] = '\0';			    /* Initialize */
X
Xif (z != 0)			    /* Converting zero is easy */
X    {
X    d = z / 100;		    /* Find out if we need and hundreds */
X    if (d != 0)
X	{
X	strcat(buf,numbers[d]);	    /* Tack them on */
X	strcat(buf," Hundred");
X	spflag = TRUE;		    /* Need a space afterward */
X	}
X
X    z %= 100;			    /* The < 100 stuff */
X    if (z != 0)			    /* Is there any? */
X	{
X	if (spflag)		    /* Need a separator */
X	    strcat(buf," ");
X	if (z > 19)		    /* Simple "Forty-Four" type construct */
X	    {
X	    d = z / 10 + 18;	    /* Get the "Forty" part into d */
X	    z %= 10;		    /* Get the "Four" part into z */
X	    strcat(buf,numbers[d]); /* Cat the stuff */
X	    if (z != 0)
X		{
X		strcat(buf,"-");
X		strcat(buf,numbers[z]);
X		}
X	    }
X	else			    /* Just use "One" to "Nineteen" */
X	    strcat(buf,numbers[z]);
X	}
X    }
Xreturn;
X}
(c)1985  K.S.A.F. Ltd.
echo 'Orignal Sum -> 21571 14 number.c'
echo -n 'Current Sum -> '
sum number.c
sed 's/^X//' << '(c)1985  K.S.A.F. Ltd.' > number.l
X.TH NUMBER 6L local
X.SH NAME
Xnumber \- convert Arabic numerals to English
X.SH SYNOPSIS
X.B /usr/local/games/number
X[
X.B \-o
X]
X.B n1
X[
X.B \-o
X]
X[
X.B n2 ...
X]
X.ig
X.br
X..
X.SH DESCRIPTION
X.I Number
Xis similar to the program of the same name in
X.B /usr/games.
XThe program takes its numeric arguments and echoes them
Xto the stadnard output, changing each decimal number
Xto a fully spelled out version.
X.PP
XThe
X.B \-o
Xoption will return ordinal numerals, instead of cardinal ones.
X.PP
XEach number can be separately chosen to be either
Xordinal or cardinal.
X.SH "SEE ALSO"
Xnumber(6)
(c)1985  K.S.A.F. Ltd.
echo 'Orignal Sum -> 47889 2 number.l'
echo -n 'Current Sum -> '
sum number.l
exit 0