Thread View: comp.sources.mac
1 messages
1 total messages
Started by Ted Johnson
Tue, 18 Oct 1988 17:00
Number Talk Source
Author: Ted Johnson
Date: Tue, 18 Oct 1988 17:00
Date: Tue, 18 Oct 1988 17:00
386 lines
10917 bytes
10917 bytes
[Number Talk Source]
This is a program called Number Talk. If you type in a number
(e.g., "-234.35"), Number Talk will spell it ("Negative Two
Hundred Thirty-Four Point Three Five") and will also speak it,
provided you have a MacinTalk driver in your System Folder.
Have fun!
-Ted C. Johnson
[Moderator's Note: The binary for this program has been posted to
comp.binaries.mac.]
---
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#
# number.c
#
# This archive created: Tue Oct 18 09:35:23 1988
# By: Roger L. Long (bytebug@dhw68k.cts.com)
#
export PATH; PATH=/bin:$PATH
echo shar: extracting "'number.c'" '(8687 characters)'
if test -f 'number.c'
then
echo shar: will not over-write existing file "'number.c'"
else
sed 's/^X//' << \SHAR_EOF > 'number.c'
X/*
X*Program name: Number Talk
X*
X*Author: The guts of this program come from an unknown Unix machine.
X* There was no documentation, so the author is unknown. I did
X* a quick port to the Mac (and Lightspeed C), and added the
X* speech feature. Ted C. Johnson, August 10, 1988. As far as
X* I know, the program is Public Domain (FreeWare). Have fun!
X*
X*Compilation instructions: use Lightspeed C, v. 2.15. This program does
X* NOT use a resource file. It was tested on a
X* Mac SE HD20, running System/Finder 4.1/5.5.
X*
X*Summary: This program translates a number (e.g., -123.454) into English
X* ("Negative One Hundred Twenty-Three Point Four Five Four"),
X* and speaks it. Number Talk handles positive and negative
X* integers and floating point numbers, but does not accept commas.
X*
X* Number Talk will translate the number to either a cardinal
X* number (e.g., 4 becomes "Four") or an ordinal number (e.g.,
X* 4 becomes "Fourth".
X*
X* Type "o" for ordinal mode.
X* Type "c" for cardinal mode.
X* Type "q" to quit.
X* Type a number, hit carriage return, and Number Talk will
X* spell it and then speak it.
X*
X*NOTE: You must have the MacinTalk driver in your System Folder to
X* run this program!
X*/
X
X#include <stdio.h>
X#include <strings.h>
X#include <MacTypes.h>
X#include <MacinTalk.h>
X
X
X
X#define TRUE 1
X#define FALSE 0
X
Xchar words[BUFSIZ];
XStr255 s;
X
XSpeechHandle theSpeech;
XHandle theText;
X
X
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 */
Xextern char *ftow();
Xextern double atof();
Xint quit = FALSE;
X
X thend = FALSE;
X
X SpeechOn("",&theSpeech);
X theText = NewHandle(0);
X
X printf("Welcome to \"Number Talk\"\n");
X say("Welcome to Number Talk", FALSE);
X say("(a public domain program ported by Ted C Johnson)", TRUE);
X printf("\n");
X say("Enter any number, and I will spell it and speak it", TRUE);
X say("Please don't use commas!", TRUE);
X say("Type c for cardinal mode", TRUE);
X say("Type o for ordinal mode", TRUE);
X say("Type q to quit", TRUE);
X printf("\n");
X say("Here we go", TRUE);
X
X printf("\n\n");
X
X for (;!quit;) {
X say("Enter a number",FALSE);
X printf("Enter a number (or a command)-->");
X gets(s);
X
X switch(s[0]) {
X case 'q':
X quit = TRUE;
X break;
X
X case 'o':
X thend = TRUE;/*ordinal numbers wanted*/
X break;
X
X case 'c':
X thend = FALSE;
X break;
X
X default:
X n = atof(s); /* Get a float for ftow */
X numb = ftow(n,thend); /* Generate the words */
X
X if (n < 0) {
X say("negative", FALSE);
X }
X
X say(s, FALSE);
X say("in words is", FALSE);
X printf("%s\n",numb); /* Print it */
X say(numb, FALSE);
X
X break;
X }
X }/*for*/
X
X SpeechOff(theSpeech);
X}
X
X
X
Xsay(s, printit)
XStr255 s;
Xint printit;
X{
X if (printit) {
X printf("%s\n", s);
X }
X Reader(theSpeech, s, (long)strlen(s), theText);
X MacinTalk(theSpeech, theText);
X}
X
X/* Table for name of each three-digit group */
Xstatic char *units[] =
X {
X " Trillion",
X " Billion",
X " Million",
X " Thousand",
X "\0\0\0\0\0"
X };
X
X
X
X/* Names of numbers that are unique */
Xstatic char *numbers[] =
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
X
X
X/* Ordinal number coding table */
Xstatic char *ord[] =
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/*
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
X words[0] = '\0'; /* Initialize for strcat */
X
X /* More than one quadrillion */
X if (x >= 1e15) {
X strcpy(words,"Overflow");
X return(words);
X }
X
X /* Just tack "Negative" on, */
X if (x < 0) {
X strcpy(words,"Negative ");
X x = -x; /* and convert the positive */
X negflag = TRUE; /* But let rest of the routine know */
X }
X
X sprintf(numb,"%23.7f",x); /* Put number into printable form */
X for (i = 0; numb[i] == ' '; ++i) { /* Tack on leading zeros */
X numb[i] = '0';
X }
X
X
X if (x < 1) {
X strcat(words,numbers[0]); /* Add a "Zero" if it is less than 1 */
X }
X else {
X for (i = 0; i < 5; i++) { /* Loop through each thousands group */
X sscanf(&numb[i*3],"%3d",&n); /* Get number less than one thousand */
X thcon(hold,n); /* Convert it */
X
X /* If it isn't zero */
X if (*hold != '\0') {
X if (words[0] != '\0') { /* If it isn't the first word */
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 }
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
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
X buf[0] = '\0'; /* Initialize */
X
X /* Converting zero is easy */
X if (z != 0) {
X d = z / 100; /* Find out if we need and hundreds */
X
X if (d != 0){
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 /* Is there any? */
X if (z != 0) {
X if (spflag) { /* Need a separator */
X strcat(buf," ");
X }
X /* Simple "Forty-Four" type construct */
X if (z > 19) {
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 strcat(buf,"-");
X strcat(buf,numbers[z]);
X }
X }
X else { /* Just use "One" to "Nineteen" */
X strcat(buf,numbers[z]);
X }
X }
X }
X return;
X}
SHAR_EOF
if test 8687 -ne "`wc -c < 'number.c'`"
then
echo shar: error transmitting "'number.c'" '(should have been 8687 characters)'
fi
fi # end of overwriting check
# End of shell archive
exit 0
---
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads