利用栈实现简易计算器(含代码)

思路:

计算器的简单实现

实现计算机的加、减、乘、除操作

eg:3+2*4-20/4 = 3+8-5 = 6

1.定义index对表达式进行扫描; 创建两个栈,一个栈存放数字,称为数栈(numStack);一个栈存放符号,称为符号栈(symbolStack);

2.当遇到数字时,入数栈;(注意字符位数,数字有可能是多位数

        2.1若是字符串最后一个的时候,直接入数栈

        2.2若不是最后一个字符,需要再往后判断一位,若后一位不是符号,继续遍历,并将该字符拼接;若是则进数栈 

3.当遇到符号时,入符号栈

  3.1如果符号栈为空,则直接入栈

  3.2如果符号栈不为空;则需要判断优先级;

      3.2.1判断优先级,若当前符号的优先级小于栈顶符号的优先级,则栈顶符号出栈,

      同时数栈中两个数字出栈;进行计算,得出的结果入数栈,当前符号入栈。

      3.2.2若优先级大于前一个符号,则继续进行入栈操作

4.当表达式遍历完后,则两个数字、一个符号依次出栈,进行操作,最后栈中剩的最后一个数为结果

  • 实现栈的基本功能,先进后出,栈的插入、删除(返回栈顶并删除栈顶元素)、以及返回栈的栈顶操作(不删除栈顶元素)
class ArrayStack1<E>{  // 头插法时间复杂度为o(n), 尾插尾删的时间复杂度为O(1).
    private E[] Array;
    private int top; //有效个数
    private static final int INITSIZE = 4;

    public ArrayStack1() {
        Array = (E[])new Object[INITSIZE];
    }
    public boolean isEmpty(){
        return top == 0;
    }
    //  栈插入元素
    public void push(E value) {   //插入
        //top从0开始,插入元素后有效个数加1,当top == INITSIZE时,说明栈满,扩容
        Array[top] = value;
        top++;
        if (top == INITSIZE) {
            Array = Arrays.copyOf(Array, Array.length + (Array.length >> 1));
        }
    }
    //从栈顶删除元素
    public E pop() {  //删除
        if (top == 0) {
            return null;
        }
        E Top = Array[top-1];
        Array[--top] = null;
        return Top;
//        Array[top -1] = null;
//        top--;
    }
    // 获取栈顶元素
    public E peek() { //获取栈顶元素
        if (top == 0) {
            throw new EmptyStackException(); // 空栈异常
        }
        return Array[top - 1];
    }
  • 判断扫描到的字符是否为 + - * /这四种操作
 public boolean isSymbol(char value){
        return value == '+'|| value == '-'|| value == '*' || value == '/';
  •  判断优先级的大小,操作符优先级由程序员掌控,返回值越大,优先级越高
 public int priority(char symbol){
        if(symbol == '*' || symbol == '/'){
            return 1;
        }else if(symbol == '+'||symbol == '-'){
            return 0;
        }else {
            return -1;
        }
    }
  • + - * / 的运算过程,num1 num2 symbol 三个变量,注意num1 和 num2 的先后顺序
public float method(float num1,float num2,char symbol) {
        float res = 0;
        switch (symbol) {
            case ('+'):
                res = num1 + num2;
                break;
            case ('-'):
                res = num2 - num1;
                break;
            case ('*'):
                res = num1 * num2;
                break;
            case ('/'):
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
  •  计算过程,根据上述思路,进行计算的过程
    public void CountMethod(String str,ArrayStack1 numStack,ArrayStack1 symbolStack){
        int index = 0; // 用来遍历表达式
        float num1 = 0;
        float num2 = 0;
        char symbol = 0;
        char ch = 0; // 用来存放遍历的字符
        float res = 0;
        String keepCh = ""; // 用作多位数字的字符拼接
        while(true){
            // 得到字符串的字符
            ch = str.substring(index,index+1).charAt(0);
            // 当遇到符号时,入符号栈
            if(symbolStack.isSymbol(ch)){
                // 如果符号栈为空,则直接入栈
                if(symbolStack.isEmpty()){
                    symbolStack.push(ch);
                    index++;
                }else{
                    // 判断优先级,若当前符号的优先级小于栈顶符号的优先级,则栈顶符号出栈,
                    // 同时数栈中两个数字出栈;进行计算,得出的结果入数栈,当前符号入栈。
                    // 若优先级大于前一个符号,则继续进行入栈操作
                    if(symbolStack.priority(ch) < symbolStack.priority((char) symbolStack.peek())){
                        symbol = (char)symbolStack.pop();
                        num1 = (float)numStack.pop();
                        num2 = (float) numStack.pop();
                        res = symbolStack.method(num1,num2,symbol);
                        numStack.push(res);
                    }else{
                        symbolStack.push(ch);
                        index++;
                    }
                }
            }else{
                keepCh += ch;
                // 当遇到数字时,入数栈;
                // 若是字符串最后一个的时候,直接入数栈
                // 若不是最后一个字符,需要再往后判断一位,若后一位不是符号,继续遍历,并将该字符拼接;若是则进数栈
                if(index == str.length()-1) {
                    numStack.push((float)Integer.parseInt(keepCh));
                    index++;
                }else{
                    while (true) {
                        ch = str.substring(index + 1, index + 2).charAt(0);
                        if (symbolStack.isSymbol(ch)) { // 下一个是符号,则入栈
                            numStack.push((float)Integer.parseInt(keepCh));
                            keepCh = "";
                            index++;
                            break;
                        }
                        keepCh += ch;
                        index++;
                    }
                }
            }

            if(index >= str.length()){ //
                break;
            }
        }
        //当表达式遍历完后,则两个数字、一个符号依次出栈,进行操作,最后栈中剩的最后一个数为结果(symbolStack为空)
        while (true){
            if(symbolStack.isEmpty()){
                break;
            }
            symbol = (char)symbolStack.pop();
            num1 = (float)numStack.pop();
            num2 = (float) numStack.pop();
            res = symbolStack.method(num1,num2,symbol);
            numStack.push(res);
        }

    }
  • 测试代码
    public static void main(String[] args) {

        // 输入表达式
        String str = "32+245*4-20/5";
        // 创建数栈和符号栈
        ArrayStack1 numStack = new ArrayStack1();
        ArrayStack1 symbolStack = new ArrayStack1();
        numStack.CountMethod(str,numStack,symbolStack);
        System.out.println("表达式:"+str+"="+numStack.peek());
    }
  • 测试结果 

 

  • 完整代码:(已测,运行成功)
import java.util.Arrays;
import java.util.EmptyStackException;

public class Calculator {  // 利用中缀表达式
    public static void main(String[] args) {

        // 输入表达式
        String str = "32+245*4-20/5";
        // 创建数栈和符号栈
        ArrayStack1 numStack = new ArrayStack1();
        ArrayStack1 symbolStack = new ArrayStack1();
        numStack.CountMethod(str,numStack,symbolStack);
        System.out.println("表达式:"+str+"="+numStack.peek());
    }
}
class ArrayStack1<E>{  // 头插法时间复杂度为o(n), 尾插尾删的时间复杂度为O(1).
    private E[] Array;
    private int top; //有效个数
    private static final int INITSIZE = 4;

    public ArrayStack1() {
        Array = (E[])new Object[INITSIZE];
    }
    public boolean isEmpty(){
        return top == 0;
    }
    //  栈插入元素
    public void push(E value) {   //插入
        //top从0开始,插入元素后有效个数加1,当top == INITSIZE时,说明栈满,扩容
        Array[top] = value;
        top++;
        if (top == INITSIZE) {
            Array = Arrays.copyOf(Array, Array.length + (Array.length >> 1));
        }
    }
    //从栈顶删除元素
    public E pop() {  //删除
        if (top == 0) {
            return null;
        }
        E Top = Array[top-1];
        Array[--top] = null;
        return Top;
//        Array[top -1] = null;
//        top--;
    }
    // 获取栈顶元素
    public E peek() { //获取栈顶元素
        if (top == 0) {
            throw new EmptyStackException(); // 空栈异常
        }
        return Array[top - 1];
    }
    public void show(){
        for(int i = 0;i < Array.length;i++){
            if(Array[i] != null) {
                System.out.println("栈内元素为" + Array[i] + "  ");
            }
        }
    }
   

    /**
     *
     * @param value  输入一个字符,判断当前符号是数字还是符号
     * @return  返回 true ,是符号
     */
    public boolean isSymbol(char value){
        return value == '+'|| value == '-'|| value == '*' || value == '/';
    }

    /**
     * 判断优先级的大小,操作符优先级由程序员掌控
     * @param symbol
     * @return 返回值越高优先级越大
     */
    public int priority(char symbol){
        if(symbol == '*' || symbol == '/'){
            return 1;
        }else if(symbol == '+'||symbol == '-'){
            return 0;
        }else {
            return -1;
        }
    }
    /**
     * 运算方式
     * @param num1  数字1
     * @param num2  数字2
     * @param symbol  操作符号
     * @return   操作结果
     */
    public float method(float num1,float num2,char symbol) {
        float res = 0;
        switch (symbol) {
            case ('+'):
                res = num1 + num2;
                break;
            case ('-'):
                res = num2 - num1;
                break;
            case ('*'):
                res = num1 * num2;
                break;
            case ('/'):
                res = num2 / num1;
                break;
            default:
                break;
        }
        return res;
    }
    public void CountMethod(String str,ArrayStack1 numStack,ArrayStack1 symbolStack){
        int index = 0; // 用来遍历表达式
        float num1 = 0;
        float num2 = 0;
        char symbol = 0;
        char ch = 0; // 用来存放遍历的字符
        float res = 0;
        String keepCh = ""; // 用作多位数字的字符拼接
        while(true){
            // 得到字符串的字符
            ch = str.substring(index,index+1).charAt(0);
            // 当遇到符号时,入符号栈
            if(symbolStack.isSymbol(ch)){
                // 如果符号栈为空,则直接入栈
                if(symbolStack.isEmpty()){
                    symbolStack.push(ch);
                    index++;
                }else{
                    // 判断优先级,若当前符号的优先级小于栈顶符号的优先级,则栈顶符号出栈,
                    // 同时数栈中两个数字出栈;进行计算,得出的结果入数栈,当前符号入栈。
                    // 若优先级大于前一个符号,则继续进行入栈操作
                    if(symbolStack.priority(ch) < symbolStack.priority((char) symbolStack.peek())){
                        symbol = (char)symbolStack.pop();
                        num1 = (float)numStack.pop();
                        num2 = (float) numStack.pop();
                        res = symbolStack.method(num1,num2,symbol);
                        numStack.push(res);
                    }else{
                        symbolStack.push(ch);
                        index++;
                    }
                }
            }else{
                keepCh += ch;
                // 当遇到数字时,入数栈;
                // 若是字符串最后一个的时候,直接入数栈
                // 若不是最后一个字符,需要再往后判断一位,若后一位不是符号,继续遍历,并将该字符拼接;若是则进数栈
                if(index == str.length()-1) {
                    numStack.push((float)Integer.parseInt(keepCh));
                    index++;
                }else{
                    while (true) {
                        ch = str.substring(index + 1, index + 2).charAt(0);
                        if (symbolStack.isSymbol(ch)) { // 下一个是符号,则入栈
                            numStack.push((float)Integer.parseInt(keepCh));
                            keepCh = "";
                            index++;
                            break;
                        }
                        keepCh += ch;
                        index++;
                    }
                }
            }

            if(index >= str.length()){ //
                break;
            }
        }
        //当表达式遍历完后,则两个数字、一个符号依次出栈,进行操作,最后栈中剩的最后一个数为结果(symbolStack为空)
        while (true){
            if(symbolStack.isEmpty()){
                break;
            }
            symbol = (char)symbolStack.pop();
            num1 = (float)numStack.pop();
            num2 = (float) numStack.pop();
            res = symbolStack.method(num1,num2,symbol);
            numStack.push(res);
        }

    }
}

  • 3
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,以下是C++实现简易计算器代码: ```c++ #include <iostream> #include <stack> #include <string> using namespace std; int main() { stack<int> numStack; // 存储数字的 stack<char> opStack; // 存储运算符的 string expression; // 表达式字符串 cin >> expression; int len = expression.length(); for (int i = 0; i < len; i++) { char ch = expression[i]; if (ch >= '0' && ch <= '9') { // 如果是数字,入数字 numStack.push(ch - '0'); } else { // 如果是运算符 if (opStack.empty() || ch == '(') { // 如果运算符为空或者当前运算符是左括号,直接入 opStack.push(ch); } else if (ch == ')') { // 如果当前运算符是右括号,弹出运算符中的元素直到遇到左括号 while (opStack.top() != '(') { int num2 = numStack.top(); numStack.pop(); int num1 = numStack.top(); numStack.pop(); char op = opStack.top(); opStack.pop(); int result; if (op == '+') { result = num1 + num2; } else if (op == '-') { result = num1 - num2; } else if (op == '*') { result = num1 * num2; } else { result = num1 / num2; } numStack.push(result); } opStack.pop(); // 弹出左括号 } else { // 如果当前运算符是加减乘除 while (!opStack.empty() && opStack.top() != '(' && ((ch == '*' || ch == '/') || (opStack.top() == '+' || opStack.top() == '-'))) { int num2 = numStack.top(); numStack.pop(); int num1 = numStack.top(); numStack.pop(); char op = opStack.top(); opStack.pop(); int result; if (op == '+') { result = num1 + num2; } else if (op == '-') { result = num1 - num2; } else if (op == '*') { result = num1 * num2; } else { result = num1 / num2; } numStack.push(result); } opStack.push(ch); } } } while (!opStack.empty()) { // 处理剩余的运算符 int num2 = numStack.top(); numStack.pop(); int num1 = numStack.top(); numStack.pop(); char op = opStack.top(); opStack.pop(); int result; if (op == '+') { result = num1 + num2; } else if (op == '-') { result = num1 - num2; } else if (op == '*') { result = num1 * num2; } else { result = num1 / num2; } numStack.push(result); } cout << numStack.top() << endl; // 输出最终结果 return 0; } ``` 这个程序可以处理包加减乘除和括号的表达式,但是没有考虑负数的情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值