C++利用栈求解中缀表达式的值

利用两个栈求解中缀表达式

基础没有小括号的版本

首先是最基础的只有 +、-、*、/ 功能的版本(实际再加 % ^ 运算都是一样的),并没有添加 (、) 进行运算限制

计算思路就是当前运算符与栈顶运算符进行比较,如果小于栈顶运算符的优先级,则说明应该先算栈顶的优先符;在只有 +、-、*、/ 运算,这个运算规则是很容易理解的

#include <iostream>
#include <stack>
#include <map>
using namespace std;

int getNum(string A, int length, int& startIndex);

// 运算符优先级 # < () < +- < */

void getRes(stack<int>& num, stack<char>& myOperator);

void printStack(stack<char> myOperator, stack<int> num);

int main()
{
	stack<char> myOperator;
	stack<int> num;

	string A;
	cin >> A;

	int length = A.length();
	int startIndex = 0;

	map<char, int> mp;
	mp.insert(map < char, int>::value_type('#', 0));
	mp.insert(map < char, int>::value_type('(', 1));
	mp.insert(map < char, int>::value_type(')', 1));
	mp.insert(map < char, int>::value_type('+', 2));
	mp.insert(map < char, int>::value_type('-', 2));
	mp.insert(map < char, int>::value_type('*', 3));
	mp.insert(map < char, int>::value_type('/', 3));

	for (int i = 0; i < length; i++)
	{
		if (A[i] >= '0' && A[i] <= '9')
		{
			startIndex = i;
			num.push(getNum(A, length, startIndex));
			i = startIndex - 1;
		}
		else if (myOperator.empty() || mp[myOperator.top()] < mp[A[i]])
		{
			myOperator.push(A[i]);
		}
		else
		{
			getRes(num, myOperator);
			myOperator.push(A[i]);

		}
		printStack(myOperator, num);
	}

	while (!myOperator.empty())
	{
		getRes(num, myOperator);
	}

	cout << num.top();
}

int getNum(string A, int length, int& startIndex)
{
	int i;
	for (i = startIndex; i < length; i++)
	{
		if (A[i] < '0' || A[1] > '9')
		{
			break;
		}
	}
	string temp = A.substr(startIndex, i);
	startIndex = i;
	return atoi(temp.c_str());
}

void getRes(stack<int>& num, stack<char>& myOperator)
{
	int num2 = num.top();
	num.pop();
	int num1 = num.top();
	num.pop();
	char ch = myOperator.top();
	myOperator.pop();

	switch (ch)
	{
	case '+':
		num.push(num1 + num2);
		break;
	case '-':
		num.push(num1 - num2);
		break;
	case '*':
		num.push(num1 * num2);
		break;
	case '/':
		num.push(num1 / num2);
		break;
	}
}

void printStack(stack<char> myOperator, stack<int> num)
{
	stack<char> tempOperator = myOperator;
	stack<int> tempNum = num;

	int operatorSize = tempOperator.size();
	int numSize = tempNum.size();

	for (int i = 0; i < max(operatorSize, numSize); i++)
	{
		if (!tempOperator.empty())
		{
			cout << tempOperator.top() << "\t";
			tempOperator.pop();
		}
		else
		{
			cout << " \t";
		}

		if (!tempNum.empty())
		{
			cout << tempNum.top();
			tempNum.pop();
		}
		cout << endl;
	}

	cout << "------------------------------" << endl;
}

/*
测试数据一:
1+3*5*6/2

预期结果:
46

测试数据二:
1*4/2/2*5

预期结果:
5

测试数据三:
123+234

预期结果:
357

测试数据四:
5+3*12+4/4-8

预期结果:
34
*/

有小括号的版本

由于小括号的限制,导致需要先算小括号里面的,写法有了一些变化

这次会在遇到左括号时进行入栈,然后在遇到右括号时进行左括号的出栈,达到先算括号里面的功能

#include <iostream>
#include <stack>
#include <map>
using namespace std;

int getNum(string A, int length, int& startIndex);

// 运算符优先级 # < () < +- < */

void getRes(stack<int>& num, stack<char>& myOperator);

void printStack(stack<char> myOperator, stack<int> num);

int main()
{
	stack<char> myOperator;
	stack<int> num;

	string A;
	cin >> A;

	int length = A.length();
	int startIndex = 0;

	map<char, int> mp;
	mp.insert(map < char, int>::value_type('#', 0));
	mp.insert(map < char, int>::value_type('(', 1));
	mp.insert(map < char, int>::value_type(')', 1));
	mp.insert(map < char, int>::value_type('+', 2));
	mp.insert(map < char, int>::value_type('-', 2));
	mp.insert(map < char, int>::value_type('*', 3));
	mp.insert(map < char, int>::value_type('/', 3));

	for (int i = 0; i < length; i++)
	{
		if (A[i] >= '0' && A[i] <= '9')
		{
			startIndex = i;
			num.push(getNum(A, length, startIndex));
			i = startIndex - 1;
		}
		else if (myOperator.empty() || mp[myOperator.top()] < mp[A[i]])
		{
			myOperator.push(A[i]);
		}
		else
		{
			if (A[i] == '(')
			{
				myOperator.push(A[i]);
			}
			else if (A[i] == ')')
			{
				while (myOperator.top() != '(')
				{
					getRes(num, myOperator);
				}
				myOperator.pop();
			}
			else
			{
				getRes(num, myOperator);
				myOperator.push(A[i]);
			}
		}
		printStack(myOperator, num);
	}

	while (!myOperator.empty())
	{
		getRes(num, myOperator);
		printStack(myOperator, num);
	}

	cout << num.top();
}

int getNum(string A, int length, int& startIndex)
{
	int i;
	for (i = startIndex; i < length; i++)
	{
		if (A[i] < '0' || A[1] > '9')
		{
			break;
		}
	}
	string temp = A.substr(startIndex, i);
	startIndex = i;
	return atoi(temp.c_str());
}

void getRes(stack<int>& num, stack<char>& myOperator)
{
	int num2 = num.top();
	num.pop();
	int num1 = num.top();
	num.pop();
	char ch = myOperator.top();
	myOperator.pop();

	switch (ch)
	{
	case '+':
		num.push(num1 + num2);
		break;
	case '-':
		num.push(num1 - num2);
		break;
	case '*':
		num.push(num1 * num2);
		break;
	case '/':
		num.push(num1 / num2);
		break;
	}
}

void printStack(stack<char> myOperator, stack<int> num)
{
	stack<char> tempOperator = myOperator;
	stack<int> tempNum = num;

	int operatorSize = tempOperator.size();
	int numSize = tempNum.size();

	for (int i = 0; i < max(operatorSize, numSize); i++)
	{
		if (!tempOperator.empty())
		{
			cout << tempOperator.top() << "\t";
			tempOperator.pop();
		}
		else
		{
			cout << " \t";
		}

		if (!tempNum.empty())
		{
			cout << tempNum.top();
			tempNum.pop();
		}
		cout << endl;
	}

	cout << "------------------------------" << endl;
}

/*
测试数据一:
5+3*(12+4)/4-8

预期结果:
9
*/

支持负数、%、^、和小数的版本

相较于小括号的版本遇到的主要的问题是负号的判断,其余的都只是简单的添加一些语句与修改数据类型和调用函数而已(实际有点难考虑,我设计为负号需要在小括号内使用,且紧靠左边,例如(-3*5) => -15 )

#include <iostream>
#include <stdio.h>
#include <stack>
#include <map>
#include <cmath>
using namespace std;

float getNum(string A, int length, int& startIndex);

// 运算符优先级 () < +- < */% < ^

void getRes(stack<float>& num, stack<char>& myOperator);

void printStack(stack<char> myOperator, stack<float> num);

int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);

	stack<char> myOperator;
	stack<float> num;

	string A;
	cin >> A;

	int length = A.length();
	int startIndex = 0;

	map<char, int> mp;
	mp.insert(map < char, int>::value_type('(', 1));
	mp.insert(map < char, int>::value_type(')', 1));
	mp.insert(map < char, int>::value_type('+', 2));
	mp.insert(map < char, int>::value_type('-', 2));
	mp.insert(map < char, int>::value_type('*', 3));
	mp.insert(map < char, int>::value_type('/', 3));
	mp.insert(map < char, int>::value_type('%', 3));
	mp.insert(map < char, int>::value_type('^', 4));

	for (int i = 0; i < length; i++)
	{
		bool flag = (A[i] >= '0' && A[i] <= '9') || (A[i] == '-' && A[i - 1] == '(' && (A[i + 1] >= '0' && A[i + 1] <= '9'));
		if (flag)
		{
			startIndex = i;
			num.push(getNum(A, length, startIndex));
			i = startIndex - 1;
		}
		else if (myOperator.empty() || mp[myOperator.top()] < mp[A[i]])
		{
			myOperator.push(A[i]);
		}
		else
		{
			if (A[i] == '(')
			{
				myOperator.push(A[i]);
			}
			else if (A[i] == ')')
			{
				while (myOperator.top() != '(')
				{
					getRes(num, myOperator);
				}
				myOperator.pop();
			}
			else
			{
				getRes(num, myOperator);
				myOperator.push(A[i]);
			}
		}
		printStack(myOperator, num);
	}

	while (!myOperator.empty())
	{
		getRes(num, myOperator);
		printStack(myOperator, num);
	}

	cout << num.top();
}

float getNum(string A, int length, int& startIndex)
{
	bool isNegative = false;
	if (A[startIndex] == '-')
	{
		isNegative = true;
	}

	bool isFirsAppear = true;
	int i = isNegative ? startIndex + 1 : startIndex;
	for (; i < length; i++)
	{
		if ((A[i] >= '0' && A[i] <= '9'))
		{
			continue;
		}
		else if (A[i] == '.' && isFirsAppear)
		{
			isFirsAppear = false;
			continue;
		}
		break;
	}
	string temp = A.substr(startIndex, i);
	startIndex = i;
	return atof(temp.c_str());
}

void getRes(stack<float>& num, stack<char>& myOperator)
{
	float num2 = num.top();
	num.pop();
	float num1 = num.top();
	num.pop();
	char ch = myOperator.top();
	myOperator.pop();

	switch (ch)
	{
	case '+':
		num.push(num1 + num2);
		break;
	case '-':
		num.push(num1 - num2);
		break;
	case '*':
		num.push(num1 * num2);
		break;
	case '/':
		num.push(num1 / num2);
		break;
	case '%':
		num.push((int)num1 % (int)num2);
		break;
	case '^':
		num.push(pow(num1, num2));
		break;
	}
}

void printStack(stack<char> myOperator, stack<float> num)
{
	stack<char> tempOperator = myOperator;
	stack<float> tempNum = num;

	int operatorSize = tempOperator.size();
	int numSize = tempNum.size();

	for (int i = 0; i < max(operatorSize, numSize); i++)
	{
		if (!tempOperator.empty())
		{
			cout << tempOperator.top() << "\t";
			tempOperator.pop();
		}
		else
		{
			cout << " \t";
		}

		if (!tempNum.empty())
		{
			cout << tempNum.top();
			tempNum.pop();
		}
		cout << endl;
	}

	cout << "------------------------------" << endl;
}

/*
测试数据一:
5%2+3*(-12+4.3)/4-8^2

预期结果:
-68.775

测试数据二:
5%2+3*(-12+(-4.3*5))/4-8^2

预期结果:
-88.125
*/

结合Winform制作带界面的计算器(只写了支持小括号的版本)

主要是对C++程序的输入输出重定向与C#调用exe程序

#include <iostream>
#include <stdio.h>
#include <stack>
#include <map>
using namespace std;

int getNum(string A, int length, int& startIndex);

// 运算符优先级 # < () < +- < */

void getRes(stack<int>& num, stack<char>& myOperator);

void printStack(stack<char> myOperator, stack<int> num);

int main()
{
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);

	stack<char> myOperator;
	stack<int> num;

	string A;
	cin >> A;

	int length = A.length();
	int startIndex = 0;

	map<char, int> mp;
	mp.insert(map < char, int>::value_type('#', 0));
	mp.insert(map < char, int>::value_type('(', 1));
	mp.insert(map < char, int>::value_type(')', 1));
	mp.insert(map < char, int>::value_type('+', 2));
	mp.insert(map < char, int>::value_type('-', 2));
	mp.insert(map < char, int>::value_type('*', 3));
	mp.insert(map < char, int>::value_type('/', 3));

	for (int i = 0; i < length; i++)
	{
		if (A[i] >= '0' && A[i] <= '9')
		{
			startIndex = i;
			num.push(getNum(A, length, startIndex));
			i = startIndex - 1;
		}
		else if (myOperator.empty() || mp[myOperator.top()] < mp[A[i]])
		{
			myOperator.push(A[i]);
		}
		else
		{
			if (A[i] == '(')
			{
				myOperator.push(A[i]);
			}
			else if (A[i] == ')')
			{
				while (myOperator.top() != '(')
				{
					getRes(num, myOperator);
				}
				myOperator.pop();
			}
			else
			{
				getRes(num, myOperator);
				myOperator.push(A[i]);
			}
		}
		printStack(myOperator, num);
	}

	while (!myOperator.empty())
	{
		getRes(num, myOperator);
		printStack(myOperator, num);
	}

	cout << num.top();
}

int getNum(string A, int length, int& startIndex)
{
	int i;
	for (i = startIndex; i < length; i++)
	{
		if (A[i] < '0' || A[1] > '9')
		{
			break;
		}
	}
	string temp = A.substr(startIndex, i);
	startIndex = i;
	return atoi(temp.c_str());
}

void getRes(stack<int>& num, stack<char>& myOperator)
{
	int num2 = num.top();
	num.pop();
	int num1 = num.top();
	num.pop();
	char ch = myOperator.top();
	myOperator.pop();

	switch (ch)
	{
	case '+':
		num.push(num1 + num2);
		break;
	case '-':
		num.push(num1 - num2);
		break;
	case '*':
		num.push(num1 * num2);
		break;
	case '/':
		num.push(num1 / num2);
		break;
	}
}

void printStack(stack<char> myOperator, stack<int> num)
{
	stack<char> tempOperator = myOperator;
	stack<int> tempNum = num;

	int operatorSize = tempOperator.size();
	int numSize = tempNum.size();

	for (int i = 0; i < max(operatorSize, numSize); i++)
	{
		if (!tempOperator.empty())
		{
			cout << tempOperator.top() << "\t";
			tempOperator.pop();
		}
		else
		{
			cout << " \t";
		}

		if (!tempNum.empty())
		{
			cout << tempNum.top();
			tempNum.pop();
		}
		cout << endl;
	}

	cout << "------------------------------" << endl;
}

/*
测试数据一:
5+3*(12+4)/4-8

预期结果:
9
*/
using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows.Forms;

namespace Calculator_C__
{
    public partial class 计算器 : Form
    {
        public 计算器()
        {
            InitializeComponent();
        }

        private void Calculate_Click(object sender, EventArgs e)
        {
            string input = Input.Text;
            StreamWriter writer = new StreamWriter("input.txt");
            writer.Write(input);
            writer.Close();

            Process process = new Process();
            ProcessStartInfo startInfo = new ProcessStartInfo("4.exe");
            process.StartInfo = startInfo;
            process.Start();

            Thread.Sleep(1000);

            StreamReader reader = new StreamReader("output.txt");
            string line;
            while ((line = reader.ReadLine()) != null)
            {
                Result.Text += line + "\n";
            }
            reader.Close();
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个经典的算法问题。首先,我们需要将中缀表达式转换为后缀表达式,然后再利用结构求解后缀表达式的。具体的实现方法可以参考以下步骤: 1. 创建一个,用于存储操作符和操作数。 2. 从左到右遍历中缀表达式的每个字符。 3. 如果当前字符是数字,则将其压入中。 4. 如果当前字符是操作符,则将其与顶的操作符进行比较,如果当前操作符的优先级小于等于顶操作符的优先级,则将顶操作符弹出并计算,直到当前操作符的优先级大于顶操作符的优先级,然后将当前操作符压入中。 5. 如果当前字符是左括号,则将其压入中。 6. 如果当前字符是右括号,则弹出顶操作符并计算,直到遇到左括号为止。 7. 遍历完整个中缀表达式后,将中剩余的操作符依次弹出并计算,直到为空。 这样就可以得到后缀表达式了,然后再利用结构求解后缀表达式的。具体的实现方法可以参考以下步骤: 1. 创建一个,用于存储操作数。 2. 从左到右遍历后缀表达式的每个字符。 3. 如果当前字符是数字,则将其压入中。 4. 如果当前字符是操作符,则从中弹出两个操作数,进行计算,并将计算结果压入中。 5. 遍历完整个后缀表达式后,中剩余的操作数就是表达式的。 以上就是利用结构求解中缀表达式的具体实现方法。希望能对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值