Chinaunix首页 | 论坛 | 博客
  • 博客访问: 694679
  • 博文数量: 129
  • 博客积分: 2221
  • 博客等级: 大尉
  • 技术积分: 1620
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-09 11:27
个人简介

do{goodgoodstudy();daydayup();}while(!died)

文章分类

全部博文(129)

文章存档

2012年(26)

2011年(103)

分类: LINUX

2011-08-15 18:52:08

(集体内容详见ChinaUnix社区)
现在要在Linux下实现一个计算器程序, 它有如下的要求:
1.  能识别英文数字:比如 three hundred and ninety two, 要能转换为392.
2.  能识别英文的加减乘除: Add, minus, multiply, divide.
3.  能识别符号的加减乘除: +, -, *, /

例子如下:
输入:three hundred and ninety two multiply with 7
结果:2744

输入:12 minus 3
结果: 9


/* eng_cac.c */
/* english caculator */
#include
#include
#include
int skip_space(const char *p, int *io_index)
{
        int index;
        if (p == NULL || io_index == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        if (!isspace(p[index])) {
                return -1;
        }
        do {
                ++index;
        }while (isspace(p[index]));
        *io_index = index;
        return 0;
}
int get_word(const char *p, int *io_index, int *o_start, int *o_len)
{
        int index;
        if (p == NULL || io_index == NULL || o_start == NULL || o_len == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        if (isalpha(p[index])) {
                do {
                        ++index;
                }while (isalpha(p[index]));
                *o_start = *io_index;
                *o_len = index - *io_index;
                *io_index = index;
                return 0;
        }else if (ispunct(p[index])) {
                ++index;
                *o_start = *io_index;
                *o_len = 1;
                *io_index = index;
                return 0;
        }else {
                return -1;
        }
}
int get_token(const char *tok, int len, const char *tok_tab[], int tab_len)
{
        int i;
        if (tok == NULL || tok_tab == NULL) {
                return -1;
        }
        if (len <= 0 || tab_len <= 0) {
                return -1;
        }
        for (i = 0; i < tab_len; ++i) {
                if (strncmp(tok, tok_tab[i], len) == 0) {
                        if (tok_tab[i][len] == '\0') {
                                return i;
                        }
                }
        }
        return -1;
}
int skip_word(const char *p, int *io_index, const char *s)
{
        int index;
        int start, len;
        if (p == NULL || io_index == NULL || s == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (get_word(p, &index, &start, &len) == 0) {
                if (strncmp(p + start, s, len) == 0) {
                        *io_index = index;
                        return 0;
                }
        }
        return -1;
}
int get_english_number_bellow_twenty(const char *p, int *io_index, int *o_value)
{
        static const char *digit20[20] = {
                "zero",
                "one",
                "two",
                "three",
                "four",
                "five",
                "six",
                "seven",
                "eight",
                "nine",
                "ten",
                "eleven",
                "twelve",
                "thirteen",
                "fourteen",
                "fifteen",
                "sixteen",
                "seventeen",
                "eighteen",
                "nineteen",
        };
        int index;
        int start;
        int len;
        int tok;
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (get_word(p, &index, &start, &len) == 0) {
                tok = get_token(p + start, len, digit20, 20);
                if (tok != -1) {
                        *o_value = tok;
                        *io_index = index;
                        return 0;
                }
        }
        return -1;
}
int get_english_number_decade(const char *p, int *io_index, int *o_value)
{
        static const char *decades[8] = {
                "twenty",
                "thirty",
                "forty",
                "fifty",
                "sixty",
                "seventy",
                "eighty",
                "ninety",
        };
        int index;
        int start, len;
        int value;
        int retn;
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (get_word(p, &index, &start, &len) == 0) {
                retn = get_token(p + start, len, decades, 8);
                if (retn != -1) {
                        value = retn * 10 + 20;
                        *o_value = value;
                        *io_index = index;
                        return 0;
                }
        }
        return -1;
}
int get_english_number_bellow_hundred(const char *p, int *io_index, int *o_value)
{
        int index;
        int value;
        int digit;
        int decade_yes;
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        decade_yes = 0;
        if (get_english_number_decade(p, &index, &value) == -1) {
                value = 0;
        }else {
                decade_yes = 1;
        }
        if (get_english_number_bellow_twenty(p, &index, &digit) == 0) {
                if (decade_yes && digit == 0) {
                        return -1;
                }
                value += digit;
        }else {
                if (!decade_yes) {
                        return -1;
                }
        }
        *o_value = value;
        *io_index = index;
        return 0;
}
int get_english_number_base(const char *p, int *io_index, int *o_base)
{
        static const char *more[] = {
                "thousand",
                "million",
                "billion",
        };
        static const int base[] = {
                1000,
                1000000,
                1000000000,
        };
        int index;
        int start,len;
        int retn;
        if (p == NULL || io_index == NULL || o_base == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (get_word(p, &index, &start, &len) == 0) {
                retn = get_token(p + start, len, more, 4);
                if (retn != -1) {
                        *o_base = base[retn];
                        *io_index = index;
                        return 0;
                }
        }
        return -1;
}
int get_english_number_bellow_thousand(const char *p, int *io_index, int *o_value)
{
        int index;
        int value;
        int sum;
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        if (get_english_number_bellow_hundred(p, &index, &sum) == 0) {
                if (sum > 0 && sum < 10) {
                        if (skip_word(p, &index, "hundred") == 0) {
                                sum *= 100;
                                if (skip_word(p, &index, "and") == 0) {
                                        if (get_english_number_bellow_hundred(p, &index, &value) == -1) {
                                                return -1;
                                        }
                                        if (value == 0) {
                                                return -1;
                                        }
                                        sum += value;
                                }
                        }
                }
                *o_value = sum;
                *io_index = index;
                return 0;
        }else if (skip_word(p, &index, "a") == 0) {
                sum = 1;
                if (skip_word(p, &index, "hundred") == 0) {
                        sum *= 100;
                        if (skip_word(p, &index, "and") == 0) {
                                if (get_english_number_bellow_hundred(p, &index, &value) == -1) {
                                        return -1;
                                }
                                if (value == 0) {
                                        return -1;
                                }
                                sum += + value;
                        }
                }
                *o_value = sum;
                *io_index = index;
                return 0;
        }
        return -1;
}
int get_english_number(const char *p, int *io_index, int *o_value)
{
        int index;
        int value;
        int sum;
        int base;
       
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        sum = 0;
        for (;;) {
                if (get_english_number_bellow_thousand(p, &index, &value) == 0) {
                        if (value == 0) {
                                break;
                        }
                        if (get_english_number_base(p, &index, &base) == 0) {
                                value *= base;
                                if (sum > 0 && value >= sum) {
                                        return -1;
                                }
                                sum += value;
                                continue;
                        }
                        sum += value;
                }
                if (sum == 0) {
                        return -1;
                }
                break;
        }
        *o_value = sum;
        *io_index = index;
        return 0;
}
int get_operator1(const char *p, int *io_index, int *o_op)
{
        static const char *op_list[] = {
                "positive",
                "+",
                "negative",
                "-",
        };
        int index;
        int start, len;
        int retn;
       
        if (p == NULL || io_index == NULL || o_op == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (get_word(p, &index, &start, &len) == 0) {
                retn = get_token(p + start, len, op_list, 8);
                if (retn != -1) {
                        *o_op = retn / 2;
                        *io_index = index;
                        return 0;
                }
        }
        return -1;
}
int get_operator2(const char *p, int *io_index, int *o_op)
{
        static const char *op_list[] = {
                "plus",
                "+",
                "minus",
                "-",
                "multiply",
                "*",
                "divide",
                "/",
        };
        int index;
        int start, len;
        int retn;
        if (p == NULL || io_index == NULL || o_op == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (get_word(p, &index, &start, &len) == 0) {
                retn = get_token(p + start, len, op_list, 8);
                if (retn != -1) {
                        if ((retn & 1) == 0) {
                                skip_word(p, &index, "with");
                        }
                        *o_op = retn / 2;
                        *io_index = index;
                        return 0;
                }
        }
        return -1;
}
int get_arab_number(const char *p, int *io_index, int *o_value)
{
        int index;
        int value;
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (isdigit(p[index])) {
                value = 0;
                do {
                        value = value * 10 + p[index] - '0';
                        index++;
                }while (isdigit(p[index]));
                *o_value = value;
                *io_index = index;
                return 0;
        }
        return -1;
}
int get_number(const char *p, int *io_index, int *o_value)
{
        int index;
        int value;
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        if (get_english_number(p, &index, &value) == 0
                || get_arab_number(p, &index, &value) == 0) {
                *o_value = value;
                *io_index = index;
                return 0;
        }
        return -1;
}
int get_oprand(const char *p, int *io_index, int *o_value)
{
        int index;
        int op;
        int d1;
        int result;
        if (p == NULL || io_index == NULL || o_value == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        /* one oprand operation */
        if (get_operator1(p, &index, &op) == 0) {
                if (get_number(p, &index, &d1) != 0) {
                        return -1;
                }
                switch (op) {
                case 0:
                        result = d1;
                        break;
                case 1:
                        result = -d1;
                        break;
                default:
                        return -1;
                }
        }else {
                if (get_number(p, &index, &result) != 0) {
                        return -1;
                }
        }
        *o_value = result;
        *io_index = index;
        return 0;
}
int get_end(const char *p, int *io_index)
{
        int index;
        if (p == NULL || io_index == NULL) {
                return -1;
        }
        index = *io_index;
        if (index < 0) {
                return -1;
        }
        skip_space(p, &index);
        if (p[index] == '\0') {
                *io_index = index;
                return 0;
        }
        return -1;
}
int caculate(const char *exp, int *o_value)
{
        int op; /* operator */
        int d1, d2; /* oprand number */
        int result; /* store the expression result */
        int index;
        if (exp == NULL || o_value == NULL) {
                return -1;
        }
        index = 0;
        if (get_oprand(exp, &index, &result) == -1) {
                return -1;
        }
        /* conjunction operation */
        while (get_end(exp, &index) == -1) {
                /* two oprands operation */
                d1 = result;
                if (get_operator2(exp, &index, &op) == -1) {
                        return -1;
                }
                if (get_oprand(exp, &index, &d2) == -1) {
                        return -1;
                }
                switch (op) {
                case 0:
                        result = d1 + d2;
                        break;
                case 1:
                        result = d1 - d2;
                        break;
                case 2:
                        result = d1 * d2;
                        break;
                case 3:
                        if (d2 == 0) {
                                return -1;
                        }
                        result = d1 / d2;
                        break;
                default:
                        return -1;
                }
        }
        *o_value = result;
        return 0; /* end of conjunction */
}
int read_line(char *buff, int buf_len)
{
        int len;
        if (buff == NULL || buf_len <= 0) {
                return -1;
        }
        for (;;) {
                if (fgets(buff, buf_len, stdin) == NULL) {
                        return -1;
                }
                len = strlen(buff) - 1;
                if (buff[len] == '\n') {
                        buff[len] = '\0';
                        return 0;
                }
                /* check for last not terminated line in file */
                if (fgets(buff, buf_len, stdin) == NULL) {
                        return 0;
                }
                /* line length is greater than buffer */
                /* skip rest line content */
                for (;;) {
                        len = strlen(buff) - 1;
                        if (buff[len] == '\n') {
                                return -2; /* buffer overflow, skip the whole line */
                        }
                        if (fgets(buff, buf_len, stdin) == NULL) {
                                return -1;
                        }
                }
        }
}
int main(void)
{
        char cmd_line[1024];
        int result;
        puts("English Caculator");
        puts("Enter an expression");
        puts("Ctrl-Z to exit\n");
        for (;;) {
                printf(": ");
                switch (read_line(cmd_line, sizeof(cmd_line))) {
                case 0:
                        break;
                default:
                case -1:
                        puts("");
                        return 0;
                case -2:
                        puts("Buffer Overflow");
                        continue;
                }
                if (caculate(cmd_line, &result) == 0) {
                        printf("'%s' = %d\n", cmd_line, result);
                }else {
                        printf("'%s' = E, Invalid Expression\n", cmd_line);
                }
        }
}
阅读(3303) | 评论(0) | 转发(1) |
0

上一篇:牛人博客/网站

下一篇:牛人博客/网站

给主人留下些什么吧!~~