四则计算机实现(C++)(堆栈的应用)

简介: 四则计算机实现(C++)(堆栈的应用)

算法要求:

  1. 输入一个数学表达式(假定表达式输入格式合法),计算表达式结果并输出。
  2. 数学表达式由单个数字和运算符“+”、“-”、“*”、“/”、“(、) ”构成,例如 2 + 3 * ( 4 + 5 ) - 6 / 4。
  3. 变量、输出采用整数,只舍不入。

图解算法思想:

1、图中1、2、3、4~~表示操作的前后顺序

2、图中橙色栈用来处理数字,黄色用来处理运算符。

3、本图实际上将中缀转后缀、后缀求值两步整合在一起  

最后一步执行:取出‘-’,然后43-6=37,作为最后结果。

 

程序思想流程图:

 

代码如下:

【实验全部代码】
#include <iostream>
#include <string>
using namespace std;
// 写一个栈的模板函数,因为下面需要用到 int 和 char 两种 stack 类型,且方法一样
template <class T>
class Stack {
private:
    T data[1001];
    int size; // 同时承担 top 的作用
public:
    Stack() {
        size = 0;
    }
    ~Stack() {
        size = 0;
    }
    T pop() {//出栈
        size--;
        return data[size];
    }
    void push(T a) {//入栈
        data[size++] = a;
    }
    T front() {//返回栈顶元素
        return data[size - 1];
    }
    void clear() {//清除栈中元素,非物理清除,仅逻辑清除
        size = 0;
    }
    bool empty() {//判空
        return (size == 0);
    }
};
// 中序转后序函数
string inToSuffix(string s) {
    string result = "";
    int size = s.size();
    Stack<char> a;
    for (int i = 0; i < size; i++) {
//对括号的处理
        if (s[i] == '(') {
            a.push(s[i]);
        } else if (s[i] == ')') {
            if (!a.empty()) {
                char t = a.pop();
                while (t != '(' && !a.empty()) {
                    result.push_back(t);
                    t = a.pop();
                }
            }
//加减乘除的处理
        } else if (s[i] == '+' || s[i] == '-') { // 加减的等级是最低的
            while (!a.empty()) {
                if (a.front() == '(') {
                    break;
                } else { // 加减和乘除的处理方式一样,都是弹出
                    result.push_back(a.pop());
                }
            }
            a.push(s[i]);
        } else if (s[i] == '*' || s[i] == '/') {
            while (!a.empty()) {
                if (a.front() == '(') {
                    break;
                } else if (a.front() == '*' || a.front() == '/') { // 仅仅乘除被弹出,加减留在里面
                    result.push_back(a.pop());
                } else
                    break; // 如果遇到加减,则要直接 break,否则死循环
            }
            a.push(s[i]);
//数字的处理
        } else if (s[i] >= '0' && s[i] <= '9') {
            result.push_back(s[i]);
        } else {
            cout << "存在非法输入" << endl;
            break;
        }
    }
    while (!a.empty()) { // 最后要把栈中所有东西一一输出
        result.push_back(a.pop());
    }
    return result;
}
int suffix_print(string s) { // 后缀表达式核心就在于运算顺序,所以中缀中的括号在后缀中已经转化为数字和运算的前后顺序
    Stack<int> a;
    int size = s.size();
    for (int i = 0; i < size; i++) {
        if (s[i] >= '0' && s[i] <= '9')
            a.push(s[i] - '0');
        else {
            int s2 = a.pop();
            int s1 = a.pop();
            if (s[i] == '*') {
                a.push(s1 * s2);
            } else if (s[i] == '+') {
                a.push(s1 + s2);
            } else if (s[i] == '/') {
                a.push(s1 / s2);
            } else {
                a.push(s1 - s2);
            }
        }
    }
    return a.front();
}
int main() {
    cout << "Input" << endl;
    string input;
    cin >> input;
    cout << "Output" << endl;
    string inpute1 = inToSuffix(input);
    cout << "=" << suffix_print(inpute1) << endl;
    cout << "End";
    return 0;
}

感悟与算法分析:

本题是实现计算器的制作。可以分为三个子问题:括号作用在数据结构中的实现、如何将中缀表达式化为后缀表达式、如何将后缀表达式的值计算出来

针对

问题一:对于一个表达式,我们采用栈的方式去存储。那么如何用栈来处理括号问题呢?

  1. 遇到括号则判断是否是哪一类型括号
  2. 如果是左括号则直接压入栈,后续将括号内的符号一一压入,期间这些符号也可以弹出,但是左括号一直不弹出。直到遇到右括号,则左括号上面以及左括号本身都要一并弹出。但是左括号并不输出、同时右括号并不压入栈。
  3. 如果右括号遇到但是栈中所有元素都弹出也没有左括号则报错误。若是左括号到程序最后也没有弹出则报错误

问题二:如何将中缀表达式转化为后缀表达式只要遵循下面这几个要求即可。

  1. 利用栈结构来处理
  2. 遇到1~9的数字直接printf打印输出,栈仅仅记录运算符号。
  3. 遇到括号则分为左右两种括号按照问题一的要求来处理
  4. 遇到+-*/运算符则要先把栈中优先级等于或小于该运算符的一一弹出,然后把该运算符本身压入栈中。

所以本问题可以利用多次的if判断语句,将问题分为这几种情况分别按照要求去处理

问题三:后缀表达式的求值也同样分为以下几个步骤来处理即可。

  1. 同样需要栈,但是栈此时存放的是数字
  2. 遇到数字则直接压入栈
  3. 遇到一个运算符则取出栈顶的两个元素,按照先输出的在左边、后输出的在右边与该运算符进行计算,并将运算结果重新压回栈中
  4. 在后缀表达式结束后,将栈中的元素取出来即为最后的答案

综上来说本题考察的主要是波兰表达式和逆波兰表达式的转化,以及逆波兰表达式的计算。而这些计算借助的数据结构就是栈。程序在书写的过程中最需要注意的就是if、elseif的分类处理。有一些类处理中需要用break来退出,否则会让程序进入死循环。其他一些注意点都在程序注释中标明。

仅供参考,一定不要直接复制!!!查重很严的!!!

相关文章
|
2月前
|
存储 并行计算 安全
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
|
6月前
|
存储 安全 C++
C++中的引用和指针:区别与应用
引用和指针在C++中都有其独特的优势和应用场景。引用更适合简洁、安全的代码,而指针提供了更大的灵活性和动态内存管理的能力。在实际编程中,根据需求选择适当的类型,能够编写出高效、可维护的代码。理解并正确使用这两种类型,是掌握C++编程的关键一步。
78 1
|
6月前
|
存储 程序员 编译器
C/C++堆栈详细分析,新老程序员必会
C/C++堆栈详细分析,新老程序员必会
189 1
|
7月前
|
C++
C++中的封装、继承与多态:深入理解与应用
C++中的封装、继承与多态:深入理解与应用
163 1
|
2月前
|
存储 编译器 C++
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
【C++篇】揭开 C++ STL list 容器的神秘面纱:从底层设计到高效应用的全景解析(附源码)
59 2
|
3月前
|
编译器 C++
【C++核心】函数的应用和提高详解
这篇文章详细讲解了C++函数的定义、调用、值传递、常见样式、声明、分文件编写以及函数提高的内容,包括函数默认参数、占位参数、重载等高级用法。
26 3
|
2月前
|
存储 编译器 C语言
深入计算机语言之C++:类与对象(上)
深入计算机语言之C++:类与对象(上)
|
2月前
|
存储 分布式计算 编译器
深入计算机语言之C++:C到C++的过度-2
深入计算机语言之C++:C到C++的过度-2
|
2月前
|
编译器 Linux C语言
深入计算机语言之C++:C到C++的过度-1
深入计算机语言之C++:C到C++的过度-1
|
4月前
|
存储 算法 C++
C++ STL应用宝典:高效处理数据的艺术与实战技巧大揭秘!
【8月更文挑战第22天】C++ STL(标准模板库)是一组高效的数据结构与算法集合,极大提升编程效率与代码可读性。它包括容器、迭代器、算法等组件。例如,统计文本中单词频率可用`std::map`和`std::ifstream`实现;对数据排序及找极值则可通过`std::vector`结合`std::sort`、`std::min/max_element`完成;而快速查找字符串则适合使用`std::set`配合其内置的`find`方法。这些示例展示了STL的强大功能,有助于编写简洁高效的代码。
52 2