[BACK]Return to number.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / games / number

Annotation of src/games/number/number.c, Revision 1.5

1.5     ! lukem       1: /*     $NetBSD: number.c,v 1.4 1997/01/07 12:16:57 tls Exp $   */
1.3       cgd         2:
1.1       cgd         3: /*
1.3       cgd         4:  * Copyright (c) 1988, 1993, 1994
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
1.5     ! lukem      36: #include <sys/cdefs.h>
1.1       cgd        37: #ifndef lint
1.5     ! lukem      38: __COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\n\
        !            39:        The Regents of the University of California.  All rights reserved.\n");
1.1       cgd        40: #endif /* not lint */
                     41:
                     42: #ifndef lint
1.3       cgd        43: #if 0
1.4       tls        44: static char sccsid[] = "@(#)number.c   8.3 (Berkeley) 5/4/95";
1.3       cgd        45: #else
1.5     ! lukem      46: __RCSID("$NetBSD$");
1.3       cgd        47: #endif
1.1       cgd        48: #endif /* not lint */
                     49:
1.3       cgd        50: #include <sys/types.h>
                     51:
                     52: #include <ctype.h>
1.4       tls        53: #include <err.h>
1.1       cgd        54: #include <stdio.h>
1.3       cgd        55: #include <stdlib.h>
                     56: #include <string.h>
1.4       tls        57: #include <unistd.h>
1.1       cgd        58:
1.3       cgd        59: #define        MAXNUM          65              /* Biggest number we handle. */
1.1       cgd        60:
                     61: static char    *name1[] = {
                     62:        "",             "one",          "two",          "three",
                     63:        "four",         "five",         "six",          "seven",
                     64:        "eight",        "nine",         "ten",          "eleven",
                     65:        "twelve",       "thirteen",     "fourteen",     "fifteen",
                     66:        "sixteen",      "seventeen",    "eighteen",     "nineteen",
                     67: },
                     68:                *name2[] = {
                     69:        "",             "ten",          "twenty",       "thirty",
                     70:        "forty",        "fifty",        "sixty",        "seventy",
                     71:        "eighty",       "ninety",
                     72: },
                     73:                *name3[] = {
                     74:        "hundred",      "thousand",     "million",      "billion",
                     75:        "trillion",     "quadrillion",  "quintillion",  "sextillion",
                     76:        "septillion",   "octillion",    "nonillion",    "decillion",
                     77:        "undecillion",  "duodecillion", "tredecillion", "quattuordecillion",
                     78:        "quindecillion",                "sexdecillion",
                     79:        "septendecillion",              "octodecillion",
                     80:        "novemdecillion",               "vigintillion",
                     81: };
                     82:
1.3       cgd        83: void   convert __P((char *));
1.5     ! lukem      84: int    main __P((int, char *[]));
1.3       cgd        85: int    number __P((char *, int));
                     86: void   pfract __P((int));
                     87: void   toobig __P((void));
                     88: int    unit __P((int, char *));
                     89: void   usage __P((void));
                     90:
                     91: int lflag;
                     92:
                     93: int
                     94: main(argc, argv)
                     95:        int argc;
                     96:        char *argv[];
                     97: {
                     98:        int ch, first;
                     99:        char line[256];
                    100:
                    101:        lflag = 0;
1.5     ! lukem     102:        while ((ch = getopt(argc, argv, "l")) != -1)
1.3       cgd       103:                switch (ch) {
                    104:                case 'l':
                    105:                        lflag = 1;
                    106:                        break;
                    107:                case '?':
                    108:                default:
                    109:                        usage();
                    110:                }
                    111:        argc -= optind;
                    112:        argv += optind;
                    113:
                    114:        if (*argv == NULL)
                    115:                for (first = 1;
                    116:                    fgets(line, sizeof(line), stdin) != NULL; first = 0) {
                    117:                        if (strchr(line, '\n') == NULL)
                    118:                                errx(1, "line too long.");
                    119:                        if (!first)
                    120:                                (void)printf("...\n");
                    121:                        convert(line);
1.1       cgd       122:                }
                    123:        else
1.3       cgd       124:                for (first = 1; *argv != NULL; first = 0, ++argv) {
                    125:                        if (!first)
                    126:                                (void)printf("...\n");
                    127:                        convert(*argv);
1.1       cgd       128:                }
                    129:        exit(0);
                    130: }
                    131:
1.3       cgd       132: void
1.1       cgd       133: convert(line)
1.3       cgd       134:        char *line;
1.1       cgd       135: {
1.5     ! lukem     136:        int flen, len, rval;
        !           137:        char *p, *fraction;
1.3       cgd       138:
1.5     ! lukem     139:        flen = 0;
1.3       cgd       140:        fraction = NULL;
                    141:        for (p = line; *p != '\0' && *p != '\n'; ++p) {
                    142:                if (isblank(*p)) {
                    143:                        if (p == line) {
                    144:                                ++line;
                    145:                                continue;
                    146:                        }
                    147:                        goto badnum;
                    148:                }
                    149:                if (isdigit(*p))
                    150:                        continue;
                    151:                switch (*p) {
                    152:                case '.':
                    153:                        if (fraction != NULL)
                    154:                                goto badnum;
                    155:                        fraction = p + 1;
                    156:                        *p = '\0';
                    157:                        break;
                    158:                case '-':
                    159:                        if (p == line)
1.1       cgd       160:                                break;
1.3       cgd       161:                        /* FALLTHROUGH */
                    162:                default:
                    163: badnum:                        errx(1, "illegal number: %s", line);
                    164:                        break;
                    165:                }
                    166:        }
                    167:        *p = '\0';
                    168:
                    169:        if ((len = strlen(line)) > MAXNUM ||
1.5     ! lukem     170:            (fraction != NULL && (flen = strlen(fraction)) > MAXNUM))
1.3       cgd       171:                errx(1, "number too large, max %d digits.", MAXNUM);
                    172:
1.1       cgd       173:        if (*line == '-') {
1.3       cgd       174:                (void)printf("minus%s", lflag ? " " : "\n");
1.1       cgd       175:                ++line;
                    176:        }
1.3       cgd       177:
                    178:        rval = len > 0 ? unit(len, line) : 0;
                    179:        if (fraction != NULL && flen != 0)
                    180:                for (p = fraction; *p != '\0'; ++p)
                    181:                        if (*p != '0') {
                    182:                                if (rval)
                    183:                                        (void)printf("%sand%s",
                    184:                                            lflag ? " " : "",
                    185:                                            lflag ? " " : "\n");
                    186:                                if (unit(flen, fraction)) {
                    187:                                        if (lflag)
                    188:                                                (void)printf(" ");
                    189:                                        pfract(flen);
                    190:                                        rval = 1;
1.1       cgd       191:                                }
                    192:                                break;
                    193:                        }
1.3       cgd       194:        if (!rval)
                    195:                (void)printf("zero%s", lflag ? "" : ".\n");
                    196:        if (lflag)
                    197:                (void)printf("\n");
1.1       cgd       198: }
                    199:
1.3       cgd       200: int
                    201: unit(len, p)
1.5     ! lukem     202:        int len;
        !           203:        char *p;
1.1       cgd       204: {
1.5     ! lukem     205:        int off, rval;
1.1       cgd       206:
1.3       cgd       207:        rval = 0;
1.1       cgd       208:        if (len > 3) {
                    209:                if (len % 3) {
                    210:                        off = len % 3;
                    211:                        len -= off;
1.3       cgd       212:                        if (number(p, off)) {
                    213:                                rval = 1;
                    214:                                (void)printf(" %s%s",
                    215:                                    name3[len / 3], lflag ? " " : ".\n");
1.1       cgd       216:                        }
1.3       cgd       217:                        p += off;
1.1       cgd       218:                }
1.3       cgd       219:                for (; len > 3; p += 3) {
1.1       cgd       220:                        len -= 3;
1.3       cgd       221:                        if (number(p, 3)) {
                    222:                                rval = 1;
                    223:                                (void)printf(" %s%s",
                    224:                                    name3[len / 3], lflag ? " " : ".\n");
1.1       cgd       225:                        }
                    226:                }
                    227:        }
1.3       cgd       228:        if (number(p, len)) {
                    229:                if (!lflag)
                    230:                        (void)printf(".\n");
                    231:                rval = 1;
1.1       cgd       232:        }
1.3       cgd       233:        return (rval);
1.1       cgd       234: }
                    235:
1.3       cgd       236: int
                    237: number(p, len)
1.5     ! lukem     238:        char *p;
1.3       cgd       239:        int len;
1.1       cgd       240: {
1.5     ! lukem     241:        int val, rval;
1.1       cgd       242:
1.3       cgd       243:        rval = 0;
                    244:        switch (len) {
1.1       cgd       245:        case 3:
1.3       cgd       246:                if (*p != '0') {
                    247:                        rval = 1;
                    248:                        (void)printf("%s hundred", name1[*p - '0']);
1.1       cgd       249:                }
1.3       cgd       250:                ++p;
                    251:                /* FALLTHROUGH */
1.1       cgd       252:        case 2:
1.3       cgd       253:                val = (p[1] - '0') + (p[0] - '0') * 10;
1.1       cgd       254:                if (val) {
1.3       cgd       255:                        if (rval)
                    256:                                (void)printf(" ");
1.1       cgd       257:                        if (val < 20)
1.3       cgd       258:                                (void)printf("%s", name1[val]);
1.1       cgd       259:                        else {
1.3       cgd       260:                                (void)printf("%s", name2[val / 10]);
1.1       cgd       261:                                if (val % 10)
1.3       cgd       262:                                        (void)printf("-%s", name1[val % 10]);
1.1       cgd       263:                        }
1.3       cgd       264:                        rval = 1;
1.1       cgd       265:                }
                    266:                break;
                    267:        case 1:
1.3       cgd       268:                if (*p != '0') {
                    269:                        rval = 1;
                    270:                        (void)printf("%s", name1[*p - '0']);
1.1       cgd       271:                }
                    272:        }
1.3       cgd       273:        return (rval);
1.1       cgd       274: }
                    275:
1.3       cgd       276: void
1.1       cgd       277: pfract(len)
1.3       cgd       278:        int len;
1.1       cgd       279: {
1.3       cgd       280:        static char *pref[] = { "", "ten-", "hundred-" };
1.1       cgd       281:
                    282:        switch(len) {
                    283:        case 1:
1.3       cgd       284:                (void)printf("tenths.\n");
1.1       cgd       285:                break;
                    286:        case 2:
1.3       cgd       287:                (void)printf("hundredths.\n");
1.1       cgd       288:                break;
                    289:        default:
1.3       cgd       290:                (void)printf("%s%sths.\n", pref[len % 3], name3[len / 3]);
                    291:                break;
1.1       cgd       292:        }
                    293: }
                    294:
1.3       cgd       295: void
                    296: usage()
1.1       cgd       297: {
1.3       cgd       298:        (void)fprintf(stderr, "usage: number [# ...]\n");
                    299:        exit(1);
1.1       cgd       300: }

CVSweb <webmaster@jp.NetBSD.org>