字符串表达式的计算(c++版)

本文详细介绍了一种利用栈结构解析并计算字符串表达式的方法,包括中缀表达式转后缀表达式及后缀表达式的计算过程。通过具体示例和源代码实现,展示了算法设计的巧妙之处。

一.字符串表达式的解析

      z字符串表达式在栈结构的应用中是一个非常典型的列子,其算法设计思维充分的利用了栈的特性.

     类如: "1+8*9+(4+5)*7" 完成字符串表达式的计算主要分为2个步骤;

    1. 将中缀转化为后缀

              按照(*/+-)的优先级;分别创建2个栈用来贮存数字和符号,从第一个元素遍历,遇到数字进入数字栈,遇到符号进入符号栈,如果入栈符号的优先级小于等于栈顶符号的优先级,则将栈顶元素压入数字栈中,重复上述动作;最后如果符号栈有剩余则全部进入数字栈;

       2.将后缀表达式计算

     遍历全部元素,遇到数字数字压入新栈中,遇到符号将此符号作为前面2个数字的运算符,计算结果压入新栈,直到计算完成

原理图:

                          

二.源代码的实现

        

#include <iostream>
#include <cstdio>
#include <cstring> 
#include <cstdlib>
const int  SIZE = 100; // 栈的初始容量
const int  ADDSIZE = 5; // 栈的单位增加容量
using namespace std;// 命名空间
const int INF = -0xfffffff;// 用于空栈时防止尴尬,返回一个不能读取的地址,让读取的人尴尬;
template <class T>
struct Strack
{
	T *top;// 栈顶的指针
	T *base;// 栈底的指针
	int strackSize;//栈容量
	void init()//栈的初始化
	{
		base = (T *)malloc(SIZE * sizeof(T));//分配内存
		top = base;
		strackSize = SIZE;
	}

	T Top()
	{// 返回栈顶元素
		if (top == base)
			return INF;// 返回尴尬地址
		return *(top - 1);
	}

	bool pop()
	{// 删除栈顶元素
		if (top == base)
			return false;
		top--;
		return true;
	}

	void push(T x)
	{//栈顶插入元素
		if (isPull()) {//如果内存不够重新分配内存
			base = (T *)realloc(base, (strackSize + ADDSIZE)*(sizeof(T)));
			top = base + strackSize;
			strackSize += ADDSIZE;
		}
		*top++ = x;
	}

	bool isEmpty()
	{//判断栈是否为空
		if (top == base)
			return true;
		return false;
	}

	bool isPull()//判满函数
	{
		if (top - base == strackSize)// 一次push一个所以当top - base = strackSize时满
			return true;
		else
			return false;
	}
};

int compareNumber(char x)//用来比较符号的优先级
{
	if (x == '+' || x == '-')
		return 0;
	if (x == '*' || x == '/')
		return 1;
	return -1;
}

void change(char *mid, char *suxfix)//中缀表达式转换为后缀表达式     
{
	int i = 0, len = strlen(mid), mid_index = 0;
	char c;
	Strack<char >intElements;// int数据集
	intElements.init();
	intElements.push('#');// 特殊符号用来区分元素
	while (i < len)
	{
		if (mid[i] == '(')
		{
			intElements.push(mid[i]);
			i++;
		}
		else if (mid[i] == ')')
		{
			while (intElements.Top() != '(')
			{
				suxfix[mid_index++] = intElements.Top();
				suxfix[mid_index++] = ' ';
				intElements.pop();
			}
			intElements.pop();
			i++;
		}
		else if (mid[i] == '+' || mid[i] == '-' || mid[i] == '/' || mid[i] == '*')
		{
			while (compareNumber(intElements.Top()) >= compareNumber(mid[i]))
			{
				suxfix[mid_index++] = intElements.Top();
				suxfix[mid_index++] = ' ';
				intElements.pop();
			}
			intElements.push(mid[i]);
			i++;
		}
		else if (mid[i] >= '0'&&mid[i] <= '9')
		{
			while (mid[i] >= '0'&&mid[i] <= '9')
			{
				suxfix[mid_index++] = mid[i];
				i++;
			}
			suxfix[mid_index++] = ' ';
		}
		else
		{

		}
	}
	while (intElements.Top() != '#') {
		suxfix[mid_index++] = intElements.Top();
		suxfix[mid_index++] = ' ';
		intElements.pop();
	}
	suxfix[mid_index] = 0;
}

double countSuxfix(char *suxfix)//计算后缀表达式   suxfix后缀表达式
{
	int len = strlen(suxfix);
	double x;
	Strack <int >intElements;
	intElements.init();
	int i = 0;
	while (i<len) {
		if (suxfix[i] == ' ')// 用于表达式有效字符集用完跳出循环
		{
			i++;
			continue;
		}
		switch (suxfix[i])
		{
		case '+':
			x = intElements.Top();//根据原理图看
			intElements.pop();
			x = intElements.Top() + x;
			intElements.pop(); i++;
			break;
		case '-':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top() - x;
			intElements.pop();
			i++;
			break;
		case '*':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top()*x;
			intElements.pop();
			i++;
			break;
		case '/':
			x = intElements.Top();
			intElements.pop();
			x = intElements.Top() / x;
			intElements.pop();
			i++;
			break;
		default:
		{
			x = 0;
			while (suxfix[i] >= '0'&&suxfix[i] <= '9') {
				x = x * 10 + suxfix[i] - '0';// 连续2个数,第一个*10,以此类推
				i++;
			}
		}
		}

		intElements.push(x);
	}
	return intElements.Top();
}
int main()
{
	char str[1000];
	char newStr[1000];
	scanf("%s", str);
	change(str, newStr);
	cout << newStr << endl;
	cout << countSuxfix(newStr) << endl;
	return 0;
}

--------------------------------------------------------------------------over-----------------------------------------------------------------------------------------

因各个项目中需要使用根据字符串计算数值,这里写出一个算法,专门计算字符串。配有大量常用公式。只有一个人方法,直接调用即可。 类名:CustomMath 函数名:Calculations(string value) 说明:求解算式表达式字符串的值 表达式中包含的符号或函数: truncate, ceiling,floor,round,log10, sign,sinh,sqrt, asin,atan,cosh, tanh, sin,cos,tan ,abs,acos, exp,log,max,min,pow,mod,+,-,*,/,',',(,) 函数说明:(不区分大小写) truncate(num) 计算指定数的整数部分 truncate(1.23)=1 ceiling (num) 返回大于或等于指定的双精度浮点数的最小整数值 ceiling(1.23)=2 floor(num) 返回小于或等于指定双精度浮点数的最大整数 floor(1.23)=1 round(num) 将双精度浮点值舍入为最接近的整数值 round(1.23)=1 round(num,num1) 将小数值按指定的小数位数舍入 round(1.23,1)=1.2 log10(num) 返回指定数字以 10 为底的对数 log10(10)=1 sign(num) 返回表示数字符号的值 sign(1.23)=1 sinh(num) 返回指定角度的双曲正弦值 sinh(1.23)=1.5644 sqrt(num) 返回指定数字的平方根 sqrt(9)=3 sqrt(num,num1) 返回指定数字的num1根 sqrt(27,3)=3 asin(num) 返回正弦值为指定数字的角度 asin(0.5)=PI/6 atan(num) 返回正切值为指定数字的角度 atan(1)=45 cosh(num) 返回指定角度的双曲余弦值 cosh(1.23)=1.8567 tanh(num) 返回指定角度的双曲正切值 tanh(1.23)=0.8425 sin(num) 返回指定角度的正弦值 sin(PI/6)=0.5 cos(num) 返回指定角度的余弦值 sin(PI/3)=0.5 tan(num) 返回指定角度的余切值 sin(PI/4)=1 abs(num) 返回数字的绝对值 abs(-12)=12 acos(num) 返回余弦值为指定数字的角度 acos(0.5)=PI/3 exp(num) 返回 e 的指定次幂 exp(1)=2.718 log(num) 返回指定数字的自然对数(底为 e) log(e)=1 log(num,num1) 返回指定数字在使用指定底时的对数 log(e,e)=1 max(num,um1) 返回最大值 max(1,2)=2 min(num,num1) 返回最小值 min(1,2)=1 pow(num,num1) 返回指定数字的指定次幂 pow(2,2)=4 mod(num,num1) 返回余数 mod(3,2)=1 常量: PI 值:3.14159265358979323846 E 值:2.7182818284590452354 YEAR 值:当前年份 MONTH 值:当前月份 DAY 值: 当前日 HOUR 值:当前时 MINUTE 值:当前分 SECOND 值:当前秒 RANDOM 值:一个随机数(0-1 之间) 实例 系统计算:1+2*3/4-0.5=2 函数计算:1+2*3/4-0.5=2 调用方式:CustomMath.Calculations("1+2*3/4-0.5") 系统计算(1+2)*3/4-0.5=1.75 函数计算(1+2)*3/4-0.5=1.75 调用方式:CustomMath.Calculations("(1+2)*3/4-0.5") 系统计算(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 公式计算(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6=1.20185042515466 调用方式:CustomMath.Calculations("(sin(pi)+sqrt(3+5*7+(2+8/4*5+2)))/6") 系统计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 函数计算:sin(pow(3,2)/4)+3.5-9*sqrt(81)=-76.7219268031121 调用方式:CustomMath.Calculations("sin(pow(3,2)/4)+3.5-9*sqrt(81)")
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值