home *** CD-ROM | disk | FTP | other *** search
- /*
- *Program name: Number Talk
- *
- *Author: The guts of this program come from an unknown Unix machine.
- * There was no documentation, so the author is unknown. I did
- * a quick port to the Mac (and Lightspeed C), and added the
- * speech feature. Ted C. Johnson, August 10, 1988. As far as
- * I know, the program is Public Domain (FreeWare). Have fun!
- *
- *Compilation instructions: use Lightspeed C, v. 2.15. This program does
- * NOT use a resource file. It was tested on a
- * Mac SE HD20, running System/Finder 4.1/5.5.
- *
- *Summary: This program translates a number (e.g., -123.454) into English
- * ("Negative One Hundred Twenty-Three Point Four Five Four"),
- * and speaks it. Number Talk handles positive and negative
- * integers and floating point numbers, but does not accept commas.
- *
- * Number Talk will translate the number to either a cardinal
- * number (e.g., 4 becomes "Four") or an ordinal number (e.g.,
- * 4 becomes "Fourth".
- *
- * Type "o" for ordinal mode.
- * Type "c" for cardinal mode.
- * Type "q" to quit.
- * Type a number, hit carriage return, and Number Talk will
- * spell it and then speak it.
- *
- *NOTE: You must have the MacinTalk driver in your System Folder to
- * run this program!
- */
-
- #include <stdio.h>
- #include <strings.h>
- #include <MacTypes.h>
- #include <MacinTalk.h>
-
-
-
- #define TRUE 1
- #define FALSE 0
-
- char words[BUFSIZ];
- Str255 s;
-
- SpeechHandle theSpeech;
- Handle theText;
-
-
-
- main(argc,argv)
- int argc;
- char *argv[];
- {
- double n; /* Holds number for pass to ftow */
- char *numb; /* Pointer to return from number */
- int thend; /* Flag for ordinal numbers */
- extern char *ftow();
- extern double atof();
- int quit = FALSE;
-
- thend = FALSE;
-
- SpeechOn("",&theSpeech);
- theText = NewHandle(0);
-
- printf("Welcome to \"Number Talk\"\n");
- say("Welcome to Number Talk", FALSE);
- say("(a public domain program ported by Ted C Johnson)", TRUE);
- printf("\n");
- say("Enter any number, and I will spell it and speak it", TRUE);
- say("Please don't use commas!", TRUE);
- say("Type c for cardinal mode", TRUE);
- say("Type o for ordinal mode", TRUE);
- say("Type q to quit", TRUE);
- printf("\n");
- say("Here we go", TRUE);
-
- printf("\n\n");
-
- for (;!quit;) {
- say("Enter a number",FALSE);
- printf("Enter a number (or a command)-->");
- gets(s);
-
- switch(s[0]) {
- case 'q':
- quit = TRUE;
- break;
-
- case 'o':
- thend = TRUE;/*ordinal numbers wanted*/
- break;
-
- case 'c':
- thend = FALSE;
- break;
-
- default:
- n = atof(s); /* Get a float for ftow */
- numb = ftow(n,thend); /* Generate the words */
-
- if (n < 0) {
- say("negative", FALSE);
- }
-
- say(s, FALSE);
- say("in words is", FALSE);
- printf("%s\n",numb); /* Print it */
- say(numb, FALSE);
-
- break;
- }
- }/*for*/
-
- SpeechOff(theSpeech);
- }
-
-
-
- say(s, printit)
- Str255 s;
- int printit;
- {
- if (printit) {
- printf("%s\n", s);
- }
- Reader(theSpeech, s, (long)strlen(s), theText);
- MacinTalk(theSpeech, theText);
- }
-
- /* Table for name of each three-digit group */
- static char *units[] =
- {
- " Trillion",
- " Billion",
- " Million",
- " Thousand",
- "\0\0\0\0\0"
- };
-
-
-
- /* Names of numbers that are unique */
- static char *numbers[] =
- {
- "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
- "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen",
- "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty",
- "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
- };
-
-
-
- /* Ordinal number coding table */
- static char *ord[] =
- {
- "+th","First","Second","Third","+th","Fifth","+th","+th","+h",
- "Ninth","+th","+th","+th","+th","+th","+th","+th","+th","+th","+th"
- };
-
-
-
- /*
- *Routine to convert the number to words
- *Entry:
- *x = double precision number to convert
- *ordflag = do you want ordinal numbers? (0 = no, !0 = yes)
- *Returns:
- *A character pointer to the words
- */
- char *ftow(x,ordflag)
- double x;
- int ordflag;
- {
- register int i; /* Loop counter */
- char numb[25]; /* Holds printf'ed number */
- char hold[30]; /* Gets 3 digit grouping */
- int negflag = FALSE; /* Is number negative? */
- int n; /* All around number */
-
- extern void thcon(); /* Convert each thousands group */
-
- words[0] = '\0'; /* Initialize for strcat */
-
- /* More than one quadrillion */
- if (x >= 1e15) {
- strcpy(words,"Overflow");
- return(words);
- }
-
- /* Just tack "Negative" on, */
- if (x < 0) {
- strcpy(words,"Negative ");
- x = -x; /* and convert the positive */
- negflag = TRUE; /* But let rest of the routine know */
- }
-
- sprintf(numb,"%23.7f",x); /* Put number into printable form */
- for (i = 0; numb[i] == ' '; ++i) { /* Tack on leading zeros */
- numb[i] = '0';
- }
-
-
- if (x < 1) {
- strcat(words,numbers[0]); /* Add a "Zero" if it is less than 1 */
- }
- else {
- for (i = 0; i < 5; i++) { /* Loop through each thousands group */
- sscanf(&numb[i*3],"%3d",&n); /* Get number less than one thousand */
- thcon(hold,n); /* Convert it */
-
- /* If it isn't zero */
- if (*hold != '\0') {
- if (words[0] != '\0') { /* If it isn't the first word */
- if (!negflag) /* If the last word wasn't "Negative" */
- strcat(words,", "); /* Add a comma */
- strcat(words,hold); /* Then add the words */
- negflag = FALSE; /* No more "Negative" */
- }
- else {
- strcpy(words,hold); /* Use copy if it is the first word */
- }
- strcat(words,units[i]); /* And tack on the "Million", etc */
- }
- }
- }
- sscanf(&numb[16],"%d",&n); /* Check for stuff after the decimal */
- if (n != 0) /* If there is stuff */
- {
- strcat(words," Point"); /* Add decimal point */
- for (i = 16; numb[i] != '\0'; i++) /* Get to end of number */
- ;
- i--;
- while (numb[i] == '0') /* Strip off trailing zeros */
- i--;
- numb[i+1] = '\0';
- for (i= 16; numb[i] != '\0'; i++) /* Pull off one digit at a time */
- {
- strcat(words," "); /* Add the space */
- n = numb[i] - '0'; /* And convert to decimal */
- strcat(words,numbers[n]); /* Tack on the right number */
- }
- }
- else /* If there ain't no decimals */
- {
- if (ordflag) /* And you want ordinals */
- {
- for (i = 0; words[i] != '\0'; ++i) /* Get to end of words */
- ;
- i--;
- if (words[i] == 'y') /* If it is a "Twenty", etc */
- {
- words[i] = '\0'; /* Change the "y" to "ieth" */
- strcat(words,"ieth");
- }
- else /* Search for beginning of last word */
- {
- while(words[i-1] != ' ' && words[i-1] != '-' && i > 0)
- i--;
- for (n = 0; n < 20; n++) /* Find out what the last word is */
- if (strcmp(&words[i],numbers[n]) == 0)
- break;
- if (n > 19) /* If we can't figure out what it is */
- strcat(words,"th"); /* just add a "th" */
- else
- {
- if (ord[n][0] == '+') /* Plus = cat the rest of the string */
- strcat(words,&ord[n][1]);
- else /* Otherwise make an entire replace */
- {
- words[i] = '\0';
- strcat(words,ord[n]);
- }
- }
- }
- }
- }
-
- for (n = 0; ; n = i) /* Divide words up into < 80 byte */
- { /* sections separated by a newline */
- for (i = n; i < n+80; ++i)
- if (words[i] == '\0')
- return(words);
- while (words[i] != ' ')
- --i;
- words[i] = '\n';
- }
- }
-
-
-
- /*
- *Routine to convert a number less than one thousand into words. Basic
- *routine, because all groups of three digits similar.
- *Entry:
- *buf = a place to put the converted number
- *z = the number to convert
- *Return:
- *Nothing
- */
-
- void thcon(buf,z)
- register int z;
- char buf[];
- {
- register int d; /* The divided down number */
- register int spflag = FALSE; /* Do we need a space catted? */
-
- buf[0] = '\0'; /* Initialize */
-
- /* Converting zero is easy */
- if (z != 0) {
- d = z / 100; /* Find out if we need and hundreds */
-
- if (d != 0){
- strcat(buf,numbers[d]); /* Tack them on */
- strcat(buf," Hundred");
- spflag = TRUE; /* Need a space afterward */
- }
-
- z %= 100; /* The < 100 stuff */
- /* Is there any? */
- if (z != 0) {
- if (spflag) { /* Need a separator */
- strcat(buf," ");
- }
- /* Simple "Forty-Four" type construct */
- if (z > 19) {
- d = z / 10 + 18; /* Get the "Forty" part into d */
- z %= 10; /* Get the "Four" part into z */
- strcat(buf,numbers[d]); /* Cat the stuff */
- if (z != 0) {
- strcat(buf,"-");
- strcat(buf,numbers[z]);
- }
- }
- else { /* Just use "One" to "Nineteen" */
- strcat(buf,numbers[z]);
- }
- }
- }
- return;
- }
-