[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.16

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

CVSweb <webmaster@jp.NetBSD.org>