Codeup[100000605]简单计算器

本文介绍了一种使用栈结构处理算术表达式的简易计算器实现方法。通过分析输入字符串中的数字和运算符,利用C语言实现了基本的四则运算。文章详细解释了如何处理不同优先级的运算符,并提供了一个具体示例。

题目要求如下:
在这里插入图片描述由于会输入1行的字符串,其中输入只有数字和运算符,因此可以使用C中的strtok函数按照空格将字符串拆分为多个片段,再读取每个片段中的内容。
这里我们定义了1个结构体Stack,其有4个成员,a表示前1个元素,b表示后1个元素,o表示操作符,而length是当前位置。
由于输入的字符串最多200个字符,除去前后元素及运算符,因此最多67组,这里直接向上舍入为70。
当读入数字字符串时,需要将字符串的值转换为对应的10进制数。
这个简单的计算器可以使用栈来轻松的解决,一般情况下会将中缀表达式转换为后缀表达式来轻松的解决。而这里直接简单粗暴,直接按照读取的顺序查看输入的值。
下面是对应的操作过程:

  • 当首次读取到数字字符串时,将其存储到结构体的a成员中
  • 当读取到运算符时,将其压入栈中o成员中。如果运算符是加法或减法,让length成员值加1表示压栈,并设置优先级变量priority的值为0。因为对于乘法和除法来说,其优先级更高,将其设置为0可以看成是重置其优先级。
  • 当读取到下1个数字字符串时,如果此时运算符符号为减法,那么让当前值为负数,并设置其运算符为加号。然后再将该值压入b成员中
  • 对于读取到数字字符串,如果运算符为乘法或除法,那么查看当前优先级变量priority的符号,如果该变量的值为0,表示之前没有出现过除法或乘法,而如果当前栈的长度大于1,那么将其优先级设置为1,并读取b成员中的元素。因为这说明之前元素是按加法或减法处理的,因此要对其符号进行修正。
    下面是实现的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
    double a[70];
    double b[70];
    char o[70];
    int length;
} Stack;

int main() {
    char line[201] = {0};
    while (gets(line) != NULL) {
        if(strcmp(line, "0")==0){
            break;
        }
        char *delimiter = " ";
        char *token = strtok(line, delimiter);
        int is_operator = 0;
        int priority = 0;
        Stack stack = {0};
        while (token) {
            if (token[0] >= '0' && token[0] <= '9') {
                // 字符串转数字
                int l = strlen(token);
                int total = 0, k = 1;
                for (int i = l - 1; i >= 0; --i) {
                    total += k * (token[i] - '0');
                    k *= 10;
                }
                // 乘法
                if (is_operator == 3) {
                    double tmp;
                    if (priority == 0 && stack.length > 1) {
                        priority = 1;
                        tmp = stack.b[stack.length - 1];
                    } else {
                        tmp = stack.a[stack.length - 1];
                    }
                    // 进行乘法处理
                    stack.a[stack.length - 1] = tmp * total;
                    // 上1个元素设置为0,已经已经被处理过了
                    stack.b[stack.length - 1] = 0;
                    if (stack.length>1){
                        // 设置当前运算符为1个元素的符号
                        stack.o[stack.length - 1] = stack.o[stack.length - 2];
                    }else{
                        // 设置为默认的加号
                        stack.o[stack.length - 1] = '+';
                    }
                } else if (is_operator == 4) {
                    // 除法
                    double tmp;
                    if (priority == 0 && stack.length > 1) {
                        priority = 1;
                        tmp = stack.b[stack.length - 1];
                    } else {
                        tmp = stack.a[stack.length - 1];
                    }
                    stack.a[stack.length - 1] = tmp / total;
                    stack.b[stack.length - 1] = 0;
                    if (stack.length>1){
                        stack.o[stack.length - 1] = stack.o[stack.length - 2];
                    }else{
                        stack.o[stack.length - 1] = '+';
                    }
                } else if (is_operator > 0) {
                     // 加法与减法
                    if (stack.o[stack.length-1]=='-'){
                        total = 0 - total;
                        stack.o[stack.length-1] = '+';
                    }
                    stack.b[stack.length - 1] = total;
                } else {
                    stack.a[stack.length++] = total;
                }
            } else {
                // 将操作符压入栈中
                if (strcmp(token, "+") == 0) {
                    is_operator = 1;
                    stack.length++;
                    priority = 0;
                    stack.o[stack.length - 1] = '+';
                } else if (strcmp(token, "-") == 0) {
                    is_operator = 2;
                    stack.length++;
                    priority = 0;
                    stack.o[stack.length - 1] = '-';
                } else if (strcmp(token, "*") == 0) {
                    is_operator = 3;
                    stack.o[stack.length - 1] = '*';
                } else if (strcmp(token, "/") == 0) {
                    is_operator = 4;
                    stack.o[stack.length - 1] = '/';
                }
            }
            token = strtok(NULL, delimiter);
        }
        double tmp = 0.0;
        for (int j = 0; j < stack.length; ++j) {
            char op = stack.o[j];
            // 根据操作符进行对应操作,此时只有加法或减法
            if (op == '+') {
                tmp += stack.a[j] + stack.b[j];
            } else {
                tmp += stack.a[j] - stack.b[j];
            }
        }
        printf("%.2f\n", tmp);
    }
    return 0;
}

实际上整个过程是将拆分的字符串使用结构体继续存储,使用加法对结果进行累加。其中的o用于后续整个过程完成后对前后运算的运算。
下面来看1个简单的例子:

30 / 90 - 26 + 97 - 5 - 6 - 13 / 88 * 6 + 51 / 29 + 79 * 87 + 57 * 92

首先读取30,接着读取/,当读入90时发现当前运算符为除法,那么将第1个元素读出除以后1个元素,将其值写入到第1个元素中,将其2个元素设置0。则第1组操作完成。
接着读入,发现是减号,将栈长度增加,此时a元素为0,再读入下1个元素26,发现运算符为减号,则b中存储是-26。
以此类推,直到13/88*6时,当读取除号,使用13/88,设置优先级为1,结果写入a成员中。读入数字6,由于之前优先级不为0,读取a成员中的值对其进行操作,并设置其操作符为之前的减号。
接着读取加号,对操作符进行重置。以此类推,直到整个过程完成。
其运算过程如下:

30/90 + 0
0 + -26
0 + 97
0 + -5
0 + -6
-13/88*6 + 0
51/29 + 0
79 * 87 + 0
57 ** 92 + 0

因此其最终结果为12178.21
最后是通过后的结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值