数据结构我好爱:栈的应用 II--字符串表达式的计算

字符串表达式的计算:栈的使用是其中的基础,其核心是正确分析出程序进行逻辑;

其中需要注意的问题:1.读到右括号需要计算到左括号;

                                    2.优先级问题,先乘除后加减

栈的基本操作:初始化,压栈,弹栈就不赘述了。

对于字符串表达式的计算:有一个注意就是要创建两个栈,一个存放运算符号,一个存储数字。

判定数字:pass

int isNumber(char c) {
	if (c >= '0' && c <= '9') return 1;
	return 0;
}

局部计算:

        1.当进行局部计算时,对于栈顶为左括号,直接弹出再进行计算

        2.取出一个运算符,两个运算数,注意数字顺序

        3.将计算结构压回数字栈

void cal_loc(stackPtr head) {
	if (head->dataC[head->topC] == '(') {
		popC(head);
		return;
	}
	printf("int:");
	PrintI(head);
	putchar('\n');
	printf("char:");
	PrintC(head);
	putchar('\n');
	int a = popI(head);
	int b = popI(head);
	char c = popC(head);
	printf("c==%c ", c);
	int res = 0;
	switch (c) {
	case'*':
		res = a * b;
		break;
	case'/':
		res = (double)b / a;
		break;
	case'+':
		res = a + b;
		break;
	case'-':
		res = b - a;
		break;
	}
	pushI(head, res);
	printf("res = %d a=%d ,b=%d\n", res, a, b);
}

主体计算函数

        1.判断数字,还得注意是非个位数的情况;并且因为优先级的问题以及栈空只剩下一个运算符的情况,我们直接判断,对于优先级:*或/直接进行计算对于加减就交给读到右侧括号的while来进行计算。与凡老师代码不同,优先级的判断交给后边数字。

(举栗子:当出现(1+2*3)的情况,要计算*,但是得先读入后边的3才可以计算,剩下(1+6)就交给后边‘)’的判断while来计算,所以将数字存入之后再判断优先级才是明智之举。

        2.对于符号:‘(、 ‘+、-、*、/’ 直接压栈

                                ‘)’ 标志着进行一轮计算,注意要使用while,否则计算不彻底

                               

int calculate(stackPtr head,char* str) {
	for (int i = 0; i < strlen(str);i++ ) {
		char temp = str[i];
		if (isNumber(temp)) {
			int j = i;
			int sum = 0;
			while (isNumber(str[j]) && j<strlen(str)) {
				sum = sum * 10 + str[j] - '0';
				j++;
			}
			i = j-1;
			pushI(head, sum);
			if (head->dataC[head->topC] == '*' || head->dataC[head->topC] == '/') cal_loc(head);
			else if (head->topC == -1 && head->topI!=0) cal_loc(head);//有可能直接先只压一个数字。
		}
		else {
			switch (temp) {
			case'(':
				pushC(head, temp);
				break;
			case')':
				while(head->dataC[head->topC]!='(' && head->topI!=0) cal_loc(head);
				popC(head);
				break;
			case '*':
				pushC(head, temp);
				break;
			case '/':
				pushC(head, temp);
				break;
			case'+':
				pushC(head, temp);
				break;
			case'-':
				pushC(head, temp);
				break;
			}
		}
	}
	if (head->topC != -1) cal_loc(head);
	return popI(head);
}

运行截图:

 

 完整代码:

#include<stdio.h>
#include<malloc.h>
#include<string.h>

typedef struct {
	char dataC[20];
	int dataI[20];
	int topC,topI;
}*stackPtr, stack;

stackPtr InitStack() {
	stackPtr head = (stackPtr)malloc(sizeof(stack));
	head->topC = -1;
	head->topI = -1;
	return head;
}

void pushC(stackPtr head, char c) {
	if (head->topC >= 18) {
		printf("no space");
		return;
	}
	head->topC++;
	head->dataC[head->topC] = c;
}

char popC(stackPtr head) {
	char tempchar = head->dataC[head->topC];
	head->topC--;
	return tempchar;
}

void pushI(stackPtr head, int c) {
	if (head->topI >= 18) {
		printf("no space");
		return;
	}
	head->topI++;
	head->dataI[head->topI] = c;
}

int popI(stackPtr head) {
	int tempint = head->dataI[head->topI];
	head->topI--;
	return tempint;
}


int isNumber(char c) {
	if (c >= '0' && c <= '9') return 1;
	return 0;
}

void PrintC(stackPtr head) {
	if (head->topC == -1) return;
	for (int i = head->topC; i >= 0; i--) {
		printf("%c ", head->dataC[i]);
	}
}
void PrintI(stackPtr head) {
	if (head->topI == -1) return;
	for (int i = head->topI; i >= 0; i--) {
		printf("%d ", head->dataI[i]);
	}
}

void cal_loc(stackPtr head) {
	if (head->dataC[head->topC] == '(') {
		popC(head);
		return;
	}
	printf("int:");
	PrintI(head);
	putchar('\n');
	printf("char:");
	PrintC(head);
	putchar('\n');
	int a = popI(head);
	int b = popI(head);
	char c = popC(head);
	printf("c==%c ", c);
	int res = 0;
	switch (c) {
	case'*':
		res = a * b;
		break;
	case'/':
		res = (double)b / a;
		break;
	case'+':
		res = a + b;
		break;
	case'-':
		res = b - a;
		break;
	}
	pushI(head, res);
	printf("res = %d a=%d ,b=%d\n", res, a, b);
}

int calculate(stackPtr head,char* str) {
	for (int i = 0; i < strlen(str);i++ ) {
		char temp = str[i];
		if (isNumber(temp)) {
			int j = i;
			int sum = 0;
			while (isNumber(str[j]) && j<strlen(str)) {
				sum = sum * 10 + str[j] - '0';
				j++;
			}
			i = j-1;
			pushI(head, sum);
			if (head->dataC[head->topC] == '*' || head->dataC[head->topC] == '/') cal_loc(head);
			else if (head->topC == -1 && head->topI!=0) cal_loc(head);
		}
		else {
			switch (temp) {
			case'(':
				pushC(head, temp);
				break;
			case')':
				while(head->dataC[head->topC]!='(' && head->topI!=0) cal_loc(head);
				popC(head);
				break;
			case '*':
				pushC(head, temp);
				break;
			case '/':
				pushC(head, temp);
				break;
			case'+':
				pushC(head, temp);
				break;
			case'-':
				pushC(head, temp);
				break;
			}
		}
	}
	if (head->topC != -1) cal_loc(head);
	return popI(head);
}


void Test() {
	stackPtr head = InitStack(head);
	char* tempExpression = "(21+2-1)*6";
	printf("result = %d ", calculate(head, tempExpression));
}
int main() {
	Test();
	return 0;
}


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
因各个项目中需要使用根据字符串计算数值,这里写出一个算法,专门计算字符串。配有大量常用公式。只有一个人方法,直接调用即可。 类名: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)")

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值