c语言实现四则运算

前言

通过学习c语言实现简单的四则运算,加深栈的使用和逆波兰表达式的理解。利用栈来实现先乘除后加减这一逻辑。


原理

首先要学习逆波兰表达式,我们看下面两个例子。

中缀表达式逆波兰表达式
(1+2)*(3-4)12+34-*

中缀表达式简单来说就是把操作符放到操作数的中间。

而逆波兰表达式,又叫做后缀表达式, 顾名思义就是把操作符放到操作数后面。
具体的不再此叙述。

那么为什么要使用逆波兰表达式呢。
计算机不是人脑,无法像我们一样判断先后性,识别中缀表达式,而逆波兰表达式可以通过入栈弹出的操作,实现符号的优先性,便于计算机计算。

操作原理

一个这样逆波兰表达式:12+34-* —> 原型:(1+2)*(3-4)
计算机要利用栈操作来计算这个表达式的话,就要用到下面的原则:
-依次存入1和2,然后遇到操作符 ‘+’,就会把1 和 2 从栈里面取出来相加,然后把结果重新放到栈里面;
-再接着存入3 和 4,然后又遇到操作符 ‘-’ ,再把3和4取出来相加,结果存到栈里面;
-现在栈内已经有两个数了,接着存入,遇到 ‘ * ’,再把两个数取出来相乘,结果重新存到栈里,这样就可以得到整个表达式的结果了。

即用两个栈:
一个是数字栈:用于存放处理表达式过程中的操作数
一个是符号栈:用于存放处理表达式中的运算符。开始时先向栈底压入一个表达式的结束符#

计算机系统在处理表达式时,从左到右依次读出表达式中的各个符号(操作数或运算符),每读出一个符号后,根据运算规则做如下处理:

  • 假如读出的运算符的优先级高于运算符栈栈顶运算符的优先级,将其压入运算符栈,读取下一个符号。
  • 假如读出的运算符优先级等于运算符栈栈顶运算符的优先级,将栈顶运算符退栈即可。
  • 假如读出的运算符优先级低于运算符栈栈顶运算符的优先级,则从操作数栈连续退出两个操作数,从运算符栈中退出一个运算符,然后做相应运算,并将运算结果压入操作数栈,不读入下一个符号。
  • 假如读出的是表达式的结束符“#”,且运算符栈栈顶的运算符也是“#”,则表达式处理结束,最后的表达式的计算结果在操作数栈的栈顶位置。

实现思路

  • 设置两个栈,用来存储数字和计算符号。
  • 当数字存入数字栈时,注意将字符转换为十进制数字后再压入栈。
  • 设计比较函数和运算函数,进行计算和比较字符优先级。
  • 单独处理括号情况,遇到左括号直接入栈,直到遇到有括号结束。
#import <Foundation/Foundation.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>


int compare (char str) {
    if (str == '#') {
        return 0;
    } else if (str == '+' || str == '-') {
        return 1;
    } else if (str == '*' || str == '/') {
        return 2;
    } else {
        return -1;
    }
}

int calculate(int a, char str, int b) {
    int x = 0;
    if(str == '+') {
        x = a + b;
    } else if (str == '-') {
        x = a - b;
    } else if (str == '*') {
        x = a * b;
    } else if (str == '/') {
        x = a / b;
    }
    return x;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int numberStack[100] = {0};
        int numberTop = -1;
        char symbolStack[100] = {'#'};
        int symbolTop = 0;
        char str[100];
        int flag = -1;
        scanf("%s", str);
        int x = 0;
        int length = (int)strlen(str);
        str[length] = '#';
        length = length + 1;
        
        for (int i = 0; i < length; i++) {
            if (str[i] >= '0' && str[i] <= '9') {
                x = x * 10 + (str[i] - '0');
                flag = 1;
            } else {
                if (flag == 1) {
                    numberStack[++numberTop] = x;
                    x = 0;
                    flag = -1;
                }
                
                if (str[i] == '(') {//压入左括号
                    symbolStack[++symbolTop] = str[i];
                } else if (str[i] == ')') {//遇到右括号
                    while (symbolStack[symbolTop] != '(') {
                        int b = numberStack[numberTop--];
                        int a = numberStack[numberTop--];
                        char op = symbolStack[symbolTop--];
                        numberStack[++numberTop] = calculate(a, op, b);
                    }
                    symbolTop--; // 弹出左括号
                } else {
                    while (compare(symbolStack[symbolTop]) >= compare(str[i])) {
                        int b = numberStack[numberTop--];
                        int a = numberStack[numberTop--];
                        char op = symbolStack[symbolTop--];
                        numberStack[++numberTop] = calculate(a, op, b);
                    }
                    symbolStack[++symbolTop] = str[i];
                }
                
                if (str[i] == '#' && symbolTop == 0) {
                    break;
                }
            }
        }
        printf("最后的结果是:%d\n", numberStack[0]);
    }
    return 0;
}

结果:
请添加图片描述


总结

这是个比较简陋的四则运算,无法对负数平方等进行运算,在仿写计算器项目中继续学习吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值