用栈实现计算器

本文介绍了一种使用栈数据结构实现复杂数学表达式计算的方法。通过将中缀表达式转换为后缀表达式,利用两个栈分别存储操作数和运算符,实现了对包括括号在内的复杂表达式的准确计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我们平时用swith语句写的计算器,只能处理简单的两个操作数和一个运算符,这样其实和日常应用方面差的有点远,所以我们今天学习了一种用栈来实现一条复杂运算式的计算。这个需要用到栈的相关知识,除此之外我们还需要学会如何把中缀转换成后缀表达式,比如:3+(4+5*2)-3这样一个表达式,从左至右遇到操作数压入栈1,遇到操作符压入栈2,当栈2的栈顶元素为空或者栈顶为‘(’ 时无脑压进栈,遇到右括号‘)’时出栈;遇到操作符的优先级大于栈顶元素的优先级时栈顶元素出栈同时去操作数的前两个进行运算,先把上式做一下:

栈1 : 栈底---->栈顶3 4 5 2  ---->   3   4   10  ------>3   14

 栈2:  栈底---->栈顶+ ( + *)此时先取*与2和5相乘得到10压入栈1在去两个元素进行 +即4和10

得到:栈1    3   14     ------->   17 --------->17  3

          栈2:   +    ‘-’的优先级不大于+所以栈顶的元素出栈即进行 3+14 = 17 --------->-

最终得到17 - 3 = 14

重要:当运算符出栈时,拿操作数栈里的次于栈顶元素去加减乘除栈顶元素

 

 

这是在用栈实现计算器时所有需要考虑的因素,代码如下:头文件部分前面也有详细说明重复贴代码了

#include<stdio.h>
#include"linkstack.h"

int perorty(char ch)
{
    switch(ch)
    {
        case '(':
            return 3;
        case '*':
        case '/':
            return 2;
        case '+':
        case '-':
            return 1;
        default:
            return 0;
    }
}
int main()
{
    Stack *s_num, *s_opt;
    char opt[1024] = {0};
    int i = 0, num1 = 0, num2 = 0, tmp = 0;
    if((LinkStackInit(&s_num) != success) || (LinkStackInit(&s_opt) != success))
    {
        printf("Init failure!\n");
    }

    printf("input:\n");
    scanf("%s",opt);
    while(opt[i] !='\0'|| StackEmpty(s_opt) != TRUE)
    {
        if(opt[i] > '0' && opt[i] < '9')
        {
           tmp = tmp * 10 + opt[i] - '0';
           i++;
           if(opt[i] > '9' || opt[i] < '0')
           {
               Push(s_num, tmp) ;
               tmp = 0;
                
           }
        }
        else
        {
            if(opt[i] == ')' && GetTop(s_opt) == '(')
            {
                Pop(s_opt);
                i++;
          //      continue;
            }
            if(StackEmpty(s_opt) == TRUE || (perorty(opt[i]) > perorty(GetTop(s_opt))) 
                    || (GetTop(s_opt) == '(' && opt[i] != ')'))
            {
                Push(s_opt, opt[i]);
                i++;
        //        continue;
            }
            if((opt[i] == '\0' && StackEmpty(s_opt) != TRUE) || 
                    (opt[i] == ')' && GetTop(s_opt) != '(') ||
                    perorty(opt[i] <= perorty(GetTop(s_opt))))
            {
                switch(Pop(s_opt))
                {
                    case '+':
                        num1 = Pop(s_num);
                        num2 = Pop(s_num);
                        Push(s_num, (num1 + num2));
                        break;
                    case '-':
                        num1 = Pop(s_num);
                        num2 = Pop(s_num);
                        Push(s_num, (num2 - num1));
                        break;
                    case '*':
                        num1 = Pop(s_num);
                        num2 = Pop(s_num);
                        Push(s_num, (num2 * num1));
                        break;
                    case '/':
                        num1 = Pop(s_num);
                        num2 = Pop(s_num);
                        Push(s_num, (num2 / num1));
                        break;
                    default :
                        printf("error opt!\n");
                        break;
                }
            }
        }
    }
    printf("%d\n", GetTop(s_num));
    return 0;
}

 

在C语言中,使用(Stack)实现计算器的主要目的是演示递归调用和表达式求值的基本算法,特别是后缀表达式(也称为逆波兰表示法,RPN)。这种方法不需要复杂的符号表或优先级规则,非常适合教学和理解递归。 以下是一个简单的实现后缀表达式计算器的例子: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> // 定义数据结构 typedef struct { double num; } Number; typedef struct { char operator; Number left, right; } Expression; // 函数声明 void push(Number stack[], int &top); double pop(Number stack[], int &top); char pop_operator(Number stack[], int &top); // 后缀表达式处理函数 double evaluate_postfix(char* exp); int main() { char expression[100]; printf("Enter an expression in postfix notation: "); fgets(expression, sizeof(expression), stdin); expression[strcspn(expression, "\n")] = '\0'; // 去除末尾的换行符 double result = evaluate_postfix(expression); printf("Result: %.2lf\n", result); return 0; } // 操作 void push(Number stack[], int &top) { Number n = {atof(stack[top].num)}; top++; stack[top] = n; } double pop(Number stack[], int &top) { top--; return stack[top].num; } char pop_operator(Number stack[], int &top) { top--; return stack[top].operator; } // 表达式求值 double evaluate_postfix(char* exp) { int top = 0; Number stack[100]; // 大小可调整 stack = {'0'}; // 初始化顶为0 for (int i = 0; exp[i] != '\0'; i++) { if (isdigit(exp[i])) { push(stack, top); // 如果是数字,压入 } else { double right = pop(stack, top); double left = pop(stack, top); switch (exp[i]) { case '+': stack[top++] = {left + right}; break; case '- right}; break; case '*': stack[top++] = {left * right}; break; case '/': stack[top++] = {left / right}; break; // 添加其他运算符处理 } } } return pop(stack, top); // 返回结果 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值