linux下c/c++实例之十一简单的计算器程序

一、简介

      Linux下实现的简单的计算器程序。

二、详解

1、代码一

(1)caculator.c:

/*Linux下实现一个计算器程序, 它有如下的要求:
*1.  能识别英文数字:比如 three hundred and ninety two, 要能转换为392.
*2.  能识别英文的加减乘除: Add, minus, multiply, divide.
*3.  能识别符号的加减乘除: +, -, *, /
*
*例子如下:
*输入:three hundred and ninety two multiply 7
*结果:2744
*
*输入:12 minus 3
*结果: 9
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#define bool int
#define true 1
#define false 0
void ltrim(char *str, const char ch);
void rtrim(char *str, const char ch);
int caculate(const char *input, int *result);
char get_operant(char *data, int* op1, int* op2);
int skip_work(char *data);
jmp_buf jmp;

int main()
{
    int result;
    char input[1024] = {0};
    puts("***********self made english caculator*****************");
    puts("input exit to go out!");
    while(1)
    {
        setjmp(jmp);
        puts("please input an expression:");
        if(gets(input) == NULL)
        {
            puts("get input data failed!");
            return -1;
        }

        ltrim(input, ' ');
        rtrim(input, ' ');
        if(strcmp(input, "exit") == 0)
            break;
        if(skip_work(input) < 0)
            puts("skip failed!");
        if(caculate(input, &result) == 0)
        {
            printf("The result is:%s = %d\n", input, result);
        }
        else
        {
            printf("cannot caculate!\n");
        }

    }
    puts("out of the caculator!");
    return 0;
}

void ltrim(char *str, const char ch)
{
    char *ptr;
    for (ptr = str; *ptr; ptr ++)
    {
        if(*ptr != ch)
            break;
    }
    strcpy(str, ptr);
}
void rtrim(char *str, const char ch)
{
    int i;
    int len = strlen(str);
    for (i = len - 1; i >= 0; i--)
    {
        if(str[i] != ch)
            break;
    }
    str[i + 1] = '\0';
}
int caculate(const char *str, int *result)
{
    char *input = (char*)malloc(strlen(str) + 1);
    strcpy(input, str);
    int op1, op2;
    char op;
    float div;
    op = get_operant(input, &op1, &op2);

    free(input);
    input = NULL;
    switch(op)
    {
    case '+':
        *result = op1 + op2;
        break;
    case '-':
        *result = op1 - op2;
        break;
    case '*':
        *result = op1 * op2;
        break;
    case '/':
        if(op2 == 0)
        {
            puts("divisor illegal!");
            return -1;
        }
        else
            div = (float)op1 / op2;
        printf("The result is:%s = %0.3f\n", str, div);
        longjmp(jmp, 1);
        break;
    default:
        return -1;
    }
    return 0;
}
char get_operant(char *data, int* op1, int* op2)
{
    static const char *op_list[]={"+", "-", "*", "/"};
    int i;
    char *temp = data;
    char *change;
    char *tok = NULL;
    char *steptok = NULL;
    while(*temp != '\0')
    {
        if(*temp == ' ')
        {
            change = temp;
            while(*change != '\0')
            {
                *change = *(change + 1);
                change ++;
            }
        }
        temp++;
    }
    char data_mp[100] = {0};
    //char data_mp[100] = {0};
    int sum = 0;
    strcpy(data_mp, data);
    char tok_one[50] = {0};
    char tok_two[50] = {0};
    char tok_one_temp[50] = {0};
    char tok_two_temp[50] = {0};
    for (i = 0; i < 4; i++)
    {
        tok = strtok(data, op_list[i]);
        if (strcmp(data, data_mp) != 0)
            break;
    }
    strcpy(tok_one, tok);
    strcpy(tok_one_temp, tok);
    tok = strtok(NULL, op_list[i]);
    strcpy(tok_two, tok);
    strcpy(tok_two_temp, tok);
    //printf("tok_one:%s\n", tok_one);
    steptok = strtok(tok_one, "and");

    if(strcmp(tok_one_temp, steptok) != 0)
    {
        sum = atoi(steptok);
        steptok = strtok(NULL, "and");
        sum += atoi(steptok);
        *op1 = sum;
    }
    else
        *op1 = atoi(tok_one);
    steptok = strtok(tok_two, "and");
    if(strcmp(tok_two_temp, steptok) != 0)
    {
        sum = atoi(steptok);
        steptok = strtok(NULL, "and");
        sum += atoi(steptok);
        *op2 = sum;
    }
    else
        *op2 = atoi(tok_two);
    //printf("%d,%d,%c\n",*op1,*op2,*op_list[i]);
    return *op_list[i];
}
int skip_work(char *data)
{
    static const char *symbol[8]={
        "plus", "minus", "multiply", "divide", "+", "-", "*", "/"};
    static const char *link[8]={
        "hundred", "thousand", "million", "billion", "00", "000", "000000, 000000000"};
    static const char *decade[16] ={
        "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety",
        "20", "30", "40", "50", "60", "70", "80", "90"};
    static const char *digit[20]={
        "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine",
        "ten", "eleven", "twelve", "thirteen", "fourteen","fifteen", "sixteen",
        "seventeen", "eighteen", "nineteen"};
    bool flag = false;
    char *toks = " ";
    char *tok = strtok(data, toks);
    int i, j, m ,n;
    char temp_tok[20] = {0};
    char data_temp[50]= {0};
    while(tok)
    {
        for(i = 0; i < 20; i++)
            if(!strcmp(tok, digit[i]))
            {
                if(flag == true)
                {
                    i += atoi(decade[m + 8]);
                }
                sprintf(temp_tok, "%d", i);
                break;
            }
        for(j = 0; j < 4; j++)
        {
            if(!strcmp(tok, link[j]))
            {
                strcat(data_temp, link[j + 4]);
                //sprintf(temp_tok, i*atoi(j+4));
                break;
            }
        }
        if(j != 4)
        {
            tok = strtok(NULL, toks);
            continue;
        }
        for(m = 0; m < 8; m++)
        {
            if(!strcmp(tok, decade[m]))
            {
                flag = true;
                //strcat(data_temp, decade[m + 8]);
                break;
            }
        }
        if (m != 8)
        {
            tok = strtok(NULL, toks);
            continue;
        }
        for(n = 0; n < 4;n++)
            if(!strcmp(tok, symbol[n]))
            {
                strcpy(temp_tok, symbol[n+4]);
                break;
            }
        if(i == 20 && j == 4 && m == 8 && n == 4)
            strcpy(temp_tok, tok);
        //if (!strcmp(temp_tok, data))
        //        strcpy(data, temp_tok);
        //else
        //  printf("dddd11:%s\n", temp_tok);
        strcat(data_temp, temp_tok);
        tok = strtok(NULL, toks);
        flag = false;
    }

    strcpy(data, data_temp);
    return 0;
}
(2)编译运行

2、代码二

(1)caculator.c:
//Linux 下实现计算器程序
/* eng_cac.c */

/* english caculator */

#include <ctype.h>
#include <stdio.h>
#include <string.h>

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);
        }
    }
}
(2)编译运行

三、总结

(1)上述代码仅供参考,其中还有很多的问题需要修复。
(2)若有建议,请留言,在此先感谢!

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乌托邦2号

博文不易,支持的请给予小小打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值