【练习】c++用链栈实现计算器

栈有顺序栈和链栈,其中顺序栈相当于用数组表示,而链栈则用链表,在表现方式上用链栈当然更加复杂。
首先对于一个链栈,自己重写类,需要写的基本的函数:构造函数,析构函数,入栈操作,出栈操作,取栈头,判断栈空,(判断栈满的操作对于链栈没有实际意义),其中的数据元素有指向下一个元素的结点指针和当前的元素个数。
上代码:

定义模板类

#include<string>
#include<iomanip>
#define maxlen 1000

template <class T>
struct node
{
    T data;    // 元素字段 
    node* next;           // 指针字段
};

template <class T>
class  stack{
public:
   
    stack();
    ~stack();                           // 初始化
    bool empty()  const {
        if (countt == 0) return true;
        else return false;
    };     // 判断空
    bool full()  const {
        if (countt == maxlen) return true;
        else return false;
    };          // 判断满
    T top()  const;
    // 取栈顶元素
    void push(T x) {
        if (full())return;
     

        countt++;
        node<T>* p = new node<T>;

        p->data = x;
    //    p->next = NULL;
        p->next = first;
       first=p;


    }    //入栈
    void pop();             // 出栈
  //  栈的数据成员;
private:
    int countt;
    node<T>* first = new node<T>;

};

其中要注意node* first,而不是node*< T>
(当模板类的数据成员中有模板结构体时的 处理方式)

成员函数的实现:

template <class T>
stack<T> ::~stack()
{
  //  node<T>*p = first;
    node<T>* u = new node<T>;
    while (!empty()) {
       
        u = first;
        first = first->next;
        delete u;
     //   pop();
        countt--;
    }
  
};

template <class T>
stack<T> ::stack()
{
    countt = 0;
    first = nullptr;
};
template <class T>
T stack<T>::top() const{
   int m = countt - 1;
  // node<T>* p = first->next;

   return first->data;
}
template <class T>
void stack<T>::pop() {
    if (empty())return;
    node<T>* p = first;
    first= first->next;
    delete p;
    countt--;

  //  first = first->next;

}

对于计算器的实现采用中缀转后缀表达式:


class cal {
public:


    double comppost();
    bool trans(string exp);
    void getfromclient(string& m)
    {
        cin >> m;
        int si = m.size();
        exp = new char[si];
        post = new char[si];

    }
private:
    char* post;
    char* exp;
    double result;
};


bool cal::trans(string expp)
{

    stack<char>st;

    int k = 0, i = 0, j = 0;
    while (expp[j] != '\0')
    {
        if (expp[j] == 'C')
        {

            j++;
            i--;

            continue;
        }
        else if (expp[j] == 'A')
        {

            system("cls");
            return false;
        }
        else if (expp[j] == '=')
        {
            exp[i++] = expp[j++];
            break;
        }
        else {
            exp[i++] = expp[j++];


        }

    }
    exp[i] = '\0';
    

    while (exp && (*exp != '='))
    {

        switch (*exp)
        {
        case '(':
            st.push(*exp);
            exp++;
            break;
        case ')':
            while (!st.empty() && st.top() != '(')
            {
                post[k++] = st.top();
                st.pop();
            }
            st.pop();//弹出“(”符号
            exp++;
            break;
        case '+':
        case '-':
            while (!st.empty())
            {
                if (st.top() != ')')
                {
                    post[k++] = st.top();//若栈顶不是(则将栈顶放入post中
                    st.pop();//出栈
                }
                else
                    break;//如果栈顶元素是'('时退出循环
            }
            st.push(*exp);
            exp++;
            break;
        case '*':
        case '/':
            while (!st.empty())
            {
                if (st.top() == '*' || st.top() == '/')
                {
                    post[k++] = *exp;
                    st.pop();
                }
                else
                    break;
            }
            st.push(*exp);

            exp++;
            break;

        default:
            while (*exp >= '0' && *exp <= '9')
            {
                post[k++] = *exp;
                exp++;

            }
            post[k++] = '#';//用#标识一个数字串结束 比如32这样的多位数
        }
    }
    while (!st.empty())//将运算符放入post中
    {
        post[k++] = st.top();
        st.pop();
    }
    post[k] = '\0';//给post表达式添加结束符
    return true;
}
double cal::comppost()//计算后缀表达式的值
{
    double a, b, c;
    stack<double>st;
    while (*post)
    {
        switch (*post)
        {
        case '+':
            a = st.top(); st.pop();
            b = st.top(); st.pop();
            c = a + b;
            st.push(c);
            break;
        case '-':
            a = st.top(); st.pop();
            b = st.top(); st.pop();
            c = b - a;
            st.push(c);
            break;
        case '*':
            a = st.top(); st.pop();
            b = st.top(); st.pop();
            c = a * b;
            st.push(c);
            break;
        case '/':
            a = st.top(); st.pop();
            b = st.top(); st.pop();
            if (a == '0')
            {
                cout << "error!";
                exit(1);
            }
            else
                c = b / a;
            st.push(c);
            break;
        default:
            double d = 0;
            while (*post >= '0' && *post <= '9')
            {
                d = d * 10 + *post - '0';
                post++;
            }
            st.push(d);
            break;
        }
        post++;
    }

    return st.top();
}

int main()
{

    string input;

    cal put;
    double res;
    put.getfromclient(input);//用户接口

    if (put.trans(input))//计算引擎
    {
        res = put.comppost();
        cout << res;
    }
    else

        cout << "已清零\n";

    

   
}

在这里插入图片描述

  • 1
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值