home *** CD-ROM | disk | FTP | other *** search
/ Mac-Source 1994 July / Mac-Source_July_1994.iso / C and C++ / Entertainment / NumTalk ƒ / number.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-08-10  |  8.5 KB  |  345 lines  |  [TEXT/KAHL]

  1. /*
  2. *Program name:  Number Talk
  3. *
  4. *Author:  The guts of this program come from an unknown Unix machine.  
  5. *          There was no documentation, so the author is unknown.  I did
  6. *          a quick port to the Mac (and Lightspeed C), and added the 
  7. *          speech feature.  Ted C. Johnson, August 10, 1988.  As far as
  8. *          I know, the program is Public Domain (FreeWare).  Have fun!
  9. *
  10. *Compilation instructions:  use Lightspeed C, v. 2.15.  This program does
  11. *                            NOT use a resource file.  It was tested on a
  12. *                            Mac SE HD20, running System/Finder 4.1/5.5.
  13. *
  14. *Summary:  This program translates a number (e.g., -123.454) into English 
  15. *           ("Negative One Hundred Twenty-Three Point Four Five Four"),
  16. *           and speaks it.  Number Talk handles positive and negative 
  17. *           integers and floating point numbers, but does not accept commas.
  18. *
  19. *           Number Talk will translate the number to either a cardinal 
  20. *           number (e.g., 4 becomes "Four") or an ordinal number (e.g.,
  21. *           4 becomes "Fourth".
  22. *  
  23. *           Type "o" for ordinal mode.
  24. *           Type "c" for cardinal mode.
  25. *           Type "q" to quit.
  26. *            Type a number, hit carriage return, and Number Talk will
  27. *           spell it and then speak it.
  28. *
  29. *NOTE:  You must have the MacinTalk driver in your System Folder to
  30. *        run this program!
  31. */
  32.  
  33. #include <stdio.h>
  34. #include <strings.h>
  35. #include <MacTypes.h>
  36. #include <MacinTalk.h>
  37.  
  38.  
  39.  
  40. #define        TRUE    1
  41. #define        FALSE    0
  42.  
  43. char words[BUFSIZ];
  44. Str255 s;
  45.  
  46. SpeechHandle theSpeech;
  47. Handle theText;
  48.  
  49.  
  50.  
  51. main(argc,argv)
  52. int  argc;
  53. char *argv[];
  54. {
  55. double n;                /* Holds number for pass to ftow */
  56. char *numb;                /* Pointer to return from number */
  57. int thend;                /* Flag for ordinal numbers */
  58. extern char *ftow();
  59. extern double atof();
  60. int quit = FALSE;
  61.  
  62.     thend = FALSE;
  63.     
  64.     SpeechOn("",&theSpeech);
  65.     theText = NewHandle(0);
  66.     
  67.     printf("Welcome to \"Number Talk\"\n");
  68.     say("Welcome to Number Talk", FALSE);
  69.     say("(a public domain program ported by Ted C Johnson)", TRUE);
  70.     printf("\n");
  71.     say("Enter any number, and I will spell it and speak it", TRUE);
  72.     say("Please don't use commas!", TRUE);
  73.     say("Type c for cardinal mode", TRUE);
  74.     say("Type o for ordinal mode", TRUE);
  75.     say("Type q to quit", TRUE);
  76.     printf("\n");
  77.     say("Here we go", TRUE);
  78.     
  79.     printf("\n\n");
  80.     
  81.     for (;!quit;) {
  82.         say("Enter a number",FALSE);
  83.         printf("Enter a number (or a command)-->");
  84.         gets(s);
  85.         
  86.         switch(s[0]) {
  87.             case 'q':
  88.                 quit = TRUE;
  89.                 break;
  90.                 
  91.             case 'o':
  92.                 thend = TRUE;/*ordinal numbers wanted*/
  93.                 break;
  94.                 
  95.             case 'c':
  96.                 thend = FALSE;
  97.                 break;
  98.                 
  99.             default:
  100.                   n = atof(s);            /* Get a float for ftow */
  101.                 numb = ftow(n,thend);        /* Generate the words */
  102.                 
  103.                 if (n < 0) {
  104.                     say("negative", FALSE);
  105.                 }
  106.                 
  107.                 say(s, FALSE);
  108.                 say("in words is", FALSE);
  109.                 printf("%s\n",numb);        /* Print it */
  110.                 say(numb, FALSE);
  111.  
  112.                 break;
  113.             }
  114.        }/*for*/
  115.        
  116.        SpeechOff(theSpeech);
  117. }
  118.  
  119.  
  120.  
  121. say(s, printit)
  122. Str255 s;
  123. int printit;
  124. {
  125.     if (printit) {
  126.         printf("%s\n", s);
  127.     }
  128.     Reader(theSpeech, s, (long)strlen(s), theText);
  129.     MacinTalk(theSpeech, theText);
  130. }
  131.  
  132. /* Table for name of each three-digit group */
  133. static char *units[] =            
  134.     {                    
  135.     " Trillion",
  136.     " Billion",
  137.     " Million",
  138.     " Thousand",
  139.     "\0\0\0\0\0"
  140.     };
  141.     
  142.     
  143.     
  144. /* Names of numbers that are unique */
  145. static char *numbers[] =        
  146.     {
  147.     "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
  148.     "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen",
  149.     "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty",
  150.     "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
  151.     };
  152.     
  153.     
  154.     
  155. /* Ordinal number coding table */
  156. static char *ord[] =            
  157.     {
  158.     "+th","First","Second","Third","+th","Fifth","+th","+th","+h",
  159.     "Ninth","+th","+th","+th","+th","+th","+th","+th","+th","+th","+th"
  160.     };
  161.  
  162.  
  163.  
  164. /*
  165. *Routine to convert the number to words
  166. *Entry:
  167. *x = double precision number to convert
  168. *ordflag = do you want ordinal numbers? (0 = no, !0 = yes)
  169. *Returns:
  170. *A character pointer to the words
  171. */
  172. char *ftow(x,ordflag)
  173. double x;
  174. int ordflag;
  175. {
  176. register int i;                /* Loop counter */
  177. char numb[25];                /* Holds printf'ed number */
  178. char hold[30];                /* Gets 3 digit grouping */
  179. int negflag = FALSE;            /* Is number negative? */
  180. int n;                    /* All around number */
  181.  
  182. extern void thcon();            /* Convert each thousands group */
  183.  
  184.     words[0] = '\0';            /* Initialize for strcat */
  185.     
  186.     /* More than one quadrillion */
  187.     if (x >= 1e15) {
  188.         strcpy(words,"Overflow");
  189.         return(words);
  190.       }
  191.       
  192.     /* Just tack "Negative" on, */
  193.     if (x < 0) {
  194.         strcpy(words,"Negative ");
  195.         x = -x;                /*  and convert the positive */
  196.         negflag = TRUE;            /* But let rest of the routine know */
  197.     }
  198.  
  199.     sprintf(numb,"%23.7f",x);        /* Put number into printable form */
  200.     for (i = 0; numb[i] == ' '; ++i) {    /* Tack on leading zeros */
  201.         numb[i] = '0';
  202.     }
  203.     
  204.     
  205.     if (x < 1) {
  206.         strcat(words,numbers[0]);        /* Add a "Zero" if it is less than 1 */
  207.     }
  208.     else {
  209.         for (i = 0; i < 5; i++)    {    /* Loop through each thousands group */
  210.             sscanf(&numb[i*3],"%3d",&n);    /* Get number less than one thousand */
  211.             thcon(hold,n);            /* Convert it */
  212.             
  213.             /* If it isn't zero */
  214.             if (*hold != '\0') {
  215.                 if (words[0] != '\0') {    /* If it isn't the first word */
  216.                     if (!negflag)        /* If the last word wasn't "Negative" */
  217.                     strcat(words,", "); /* Add a comma */
  218.                     strcat(words,hold);    /* Then add the words */
  219.                     negflag = FALSE;    /* No more "Negative" */
  220.                 }
  221.             else {
  222.                 strcpy(words,hold);    /* Use copy if it is the first word */
  223.             }
  224.             strcat(words,units[i]);    /* And tack on the "Million", etc */
  225.             }
  226.     }
  227.     }
  228. sscanf(&numb[16],"%d",&n);        /* Check for stuff after the decimal */
  229. if (n != 0)                /* If there is stuff */
  230.     {
  231.     strcat(words," Point");        /* Add decimal point */
  232.     for (i = 16; numb[i] != '\0'; i++)    /* Get to end of number */
  233.     ;
  234.     i--;
  235.     while (numb[i] == '0')        /* Strip off trailing zeros */
  236.     i--;
  237.     numb[i+1] = '\0';
  238.     for (i= 16; numb[i] != '\0'; i++)    /* Pull off one digit at a time */
  239.     {
  240.     strcat(words," ");        /* Add the space */
  241.     n = numb[i] - '0';        /* And convert to decimal */
  242.     strcat(words,numbers[n]);    /* Tack on the right number */
  243.     }
  244.     }
  245. else                    /* If there ain't no decimals */
  246.     {
  247.     if (ordflag)            /* And you want ordinals */
  248.     {
  249.     for (i = 0; words[i] != '\0'; ++i)  /* Get to end of words */
  250.         ;
  251.     i--;
  252.     if (words[i] == 'y')        /* If it is a "Twenty", etc */
  253.         {
  254.         words[i] = '\0';        /* Change the "y" to "ieth" */
  255.         strcat(words,"ieth");
  256.         }
  257.     else                /* Search for beginning of last word */
  258.         {
  259.         while(words[i-1] != ' ' && words[i-1] != '-' && i > 0)
  260.         i--;
  261.         for (n = 0; n < 20; n++)    /* Find out what the last word is */
  262.         if (strcmp(&words[i],numbers[n]) == 0)
  263.             break;
  264.         if (n > 19)            /* If we can't figure out what it is */
  265.         strcat(words,"th");    /*  just add a "th" */
  266.         else
  267.         {
  268.         if (ord[n][0] == '+')    /* Plus = cat the rest of the string */
  269.             strcat(words,&ord[n][1]);
  270.         else            /* Otherwise make an entire replace */
  271.             {
  272.             words[i] = '\0';
  273.             strcat(words,ord[n]);
  274.             }
  275.         }
  276.         }
  277.     }
  278.     }
  279.  
  280. for (n = 0; ; n = i)            /* Divide words up into < 80 byte */
  281.     {                    /*  sections separated by a newline */
  282.     for (i = n; i < n+80; ++i)
  283.     if (words[i] == '\0')
  284.         return(words);
  285.     while (words[i] != ' ')
  286.     --i;
  287.     words[i] = '\n';
  288.     }
  289. }
  290.  
  291.  
  292.  
  293. /*
  294. *Routine to convert a number less than one thousand into words.  Basic
  295. *routine, because all groups of three digits similar.
  296. *Entry:
  297. *buf = a place to put the converted number
  298. *z = the number to convert
  299. *Return:
  300. *Nothing
  301. */
  302.  
  303. void thcon(buf,z)
  304. register int z;
  305. char buf[];
  306. {
  307. register int d;                /* The divided down number */
  308. register int spflag = FALSE;        /* Do we need a space catted? */
  309.  
  310.     buf[0] = '\0';    /* Initialize */
  311.     
  312.      /* Converting zero is easy */
  313.     if (z != 0) {
  314.         d = z / 100; /* Find out if we need and hundreds */
  315.         
  316.         if (d != 0){
  317.             strcat(buf,numbers[d]);     /* Tack them on */
  318.             strcat(buf," Hundred");
  319.             spflag = TRUE;            /* Need a space afterward */
  320.         }
  321.  
  322.             z %= 100;                /* The < 100 stuff */
  323.              /* Is there any? */
  324.         if (z != 0)     {
  325.             if (spflag)    {        /* Need a separator */
  326.                 strcat(buf," ");
  327.             }
  328.             /* Simple "Forty-Four" type construct */
  329.             if (z > 19)     {
  330.                     d = z / 10 + 18;        /* Get the "Forty" part into d */
  331.                 z %= 10;            /* Get the "Four" part into z */
  332.                 strcat(buf,numbers[d]); /* Cat the stuff */
  333.                 if (z != 0) {
  334.                 strcat(buf,"-");
  335.                 strcat(buf,numbers[z]);
  336.                 }
  337.             }
  338.             else {                /* Just use "One" to "Nineteen" */
  339.                 strcat(buf,numbers[z]);
  340.             }
  341.         }
  342.     }
  343.     return;
  344. }
  345.