慕容紫小英 发表于 2020-7-26 22:30:10

C语言实现整数的逆波兰计算器,包括后缀转换和结果计算

本帖最后由 慕容紫小英 于 2020-7-26 23:09 编辑

这几天在学习数据结构,网上的代码有大多对基础差的人不太友好,写的比较难懂,我自己也是基础较差,但是我要求自己用自己的方式实现这些经典的程序设计,同时也希望给和我一样跨考计算机的朋友提供一些可供参考的源代码。

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

#define maxsize 100

/*本人也是跨考党,已经将代码尽我所能的解释清楚明白,方便于像我一样的初学者观看学习*/

typedef struct SqStack//定义栈
{
        char data;
        int top;
}SqStack;

int push(SqStack *st,char x)//入栈
{
        if((*st).top == maxsize-1)
                return 0;
        ++((*st).top);
        (*st).data[(*st).top] = x;
        return 1;
}

int pop(SqStack *st,char *x)//出栈
{
        if((*st).top == -1)
                return 0;
        *x = (*st).data[(*st).top];
        --((*st).top);
        return 1;
}
//中缀表达式转换为逆波兰式
//思路:1.定义两个栈,一个存放数字,称为num栈,一个存放运算符( + - * / ),称为opera栈
//      2.从左至右逐个遍历字符数组,分为以下两种情况
//         如果是数字直接入栈num
//         如果是运算符:
//         (1)opera为空,直接压入
//         (2)运算符为左括号'(',直接压入opera
//         (3) 运算符为'+' '-' '*' '/' ,则判断当前opera的栈顶元素,并比较优先级
//               一般来说,乘法 = 除法 > 加法 = 减法
//               如果栈顶元素优先级高,则将栈顶元素移出并压入栈num中 ,再将当前运算符压入栈opera中
//               需要注意的是,平级的运算符也是要出栈的
//          (4)运算符为右括号')',连续将opera的栈顶元素压入num中直至碰见左括号'(' ,并将左括号'('移出栈
//      3.读到'\0'之后,将栈opera剩余元素全部压入栈num
void RPN_switch(SqStack *A,SqStack *B,char ss[])
{
        int i;
        char temp;//记录出栈元素
       
        for(i = 0;i < maxsize;i++)
        {
                if(ss == '\0')
                        break;
                else
                if(isdigit(ss))//数字直接入栈num
                {
                        push(A,ss);
                }
                else
                {
                        if(isdigit(ss))
                        {
                                push(A,' ');//此处的操作是为了分割多位数和个位数,碰见运算符之前如果是数字则将一个' '(空格)压入栈num中
                        }       
                        switch(ss)//碰见运算符,进行上述判断再压入栈opera
                        {
                                case '(':{
                                                push(B,ss);
                                                break;
                                             }
                                case '+':{
                                               if((*B).top == -1)
                                               {
                                                       push(B,ss);
                                                       break;
                                               }
                                               else
                                               {
                                                       switch((*B).data[(*B).top])
                                                       {
                                                               case '+':{
                                                                                        pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                               
                                                               case '-':{
                                                                                          pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                               case '*':{
                                                                                          pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                               case '/':{
                                                                                          pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                               case '(':{
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                       }
                                                       break;
                                               }
                                       }       
                                case '-':{
                                               if((*B).top == -1)
                                               {
                                                       push(B,ss);
                                                       break;
                                               }
                                               else
                                               {
                                                       switch((*B).data[(*B).top])
                                                       {
                                                               case '+':{
                                                                                          pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                                    }
                                                               
                                                               case '-':{
                                                                                          pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                                    }
                                                               case '*':{
                                                                                          pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                               case '/':{
                                                                                          pop(B,&temp);
                                                                                          push(A,temp);
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                               case '(':{
                                                                                          push(B,ss);
                                                                                          break;
                                                                              }
                                                       }
                                                       break;
                                               }
                                       }
                                case '*':{
                                               if((*B).data[(*B).top]=='/')
                                               {
                                                        pop(B,&temp);
                                                        push(A,temp);
                                                        push(B,ss);
                                                        break;
                                               }
                                               else
                                               {       
                                                       push(B,ss);
                                                       break;
                                               }
                                       }
                                case '/':{
                                               if((*B).data[(*B).top]=='*')
                                               {
                                                        pop(B,&temp);
                                                        push(A,temp);
                                                        push(B,ss);
                                                        break;
                                               }
                                               else
                                               {       
                                                       push(B,ss);
                                                       break;
                                               }
                                       }
                                case ')':{
                                               do
                                               {
                                                       pop(B,&temp);
                                                       push(A,temp);
                                               }while((*B).data[(*B).top]!='(');
                                               pop(B,&temp);
                                               break;
                                       }       
                        }
                }

        }

        do
        {
                pop(B,&temp);
                push(A,temp);
        }while((*B).top > -1);
        push(A,'\0');//栈opera元素全部压入栈num之后,栈num最后别忘了补'\0'
        strcpy(ss,(*A).data);//用栈num替换原来的字符数组
        printf("%s",ss);
}

double Operation(double a,char op,double b)//计算器中的两元操作,由于除法的存在,数据类型选择double
{
        if(op == '+')
                return a+b;
        if(op == '-')
                return a-b;
        if(op == '*')
                return a*b;
        if(op == '/')
        {
                if(b == 0)
                {
                        printf("分母不能为0!\n");
                        return 0;
                }
                else
                {
                        return a/b;
                }
        }
}

void Calculator(char ss[])//计算器的代码部分
{
        int i;
        double a,b,c;//a,b取出字符数组中的数字,c是两数进行计算之后的结果
        double result;//定义一个double类型的栈
        int top = -1;
        char op;//记录运算符

        for(i = 0;i < maxsize;i++)
        {
                if(ss == '\0')
                        break;
                else
                if(isdigit(ss))//此处是将char类型的数字转化为int类型
                {
                        if(isdigit(ss))//碰到数字,判断前一个是否为数字,如果是那么就是多位数
                        {
                                result = result*10+(ss-'0');//直接将栈中的数字乘以10加上新读到的数字
                        }
                        else//如果前面不是数字就压入新的数字
                        {
                                result[++top] = ss-'0';
                        }
                }
                else
                if(ss=='+'||ss=='-'||ss=='*'||ss=='/')//碰见运算符则应该处理栈顶的两数字了
                {
                        op = ss;
                        b = result;
                        a = result;
                        c = Operation(a,op,b);
                        result[++top] = c;
                }
        }

        printf(" = %f\n",result);
}

int main(void)
{
        printf("欢迎使用逆波兰计算器!\n");
        printf("请输入您希望计算的表达式!\n");
       
        char ss;
        int i = 0;
        fgets(ss,maxsize,stdin);

        SqStack num;
        SqStack opera;
        num.top = -1,opera.top = -1;

        RPN_switch(&num,&opera,ss);
        Calculator(ss);

        return 0;
}
页: [1]
查看完整版本: C语言实现整数的逆波兰计算器,包括后缀转换和结果计算