利用链式栈实现的智能计算器(后面会补充小数点运算)

其实要浮点运算的话,将相应的int改为double就可以。要实现expression里面有小数点的话,也就是多判断一个字符的情况而已,然后压入栈的时候多了小数部分的累加而已

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "LinkStack.h" 

/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int isNumber(char c)
{
	return (c >= '0') && (c <= '9');
}

int isOperator(char c)
{
	return (c == '+') || (c == '-') || (c == '*') || (c == '/');
}

int isLeft(char c)
{
	return (c == '(');
}

int isRight(char c)
{
	return (c == ')');
}

int Priority(char c)
{
	int ret = 0;
	if((c == '+') || (c == '-')){
		ret = 1;
	}
	if((c == '*') || (c == '/')){
		ret = 2;
	}
	return ret;
}


void Transfer(char* str1,char* str2)
{
	LinkStack* stack = LinkStack_Create();
	int i = 0;
	int j = 0;
	while(str1[i] != '\0'){
		if(isNumber(str1[i])){
			while(isNumber(str1[i])){
				str2[j] = str1[i];
				j++;//在循环里注意使用continue,如果在改变下标之前用continue会造成内存泄漏 
				i++;//有循环的地方,在进入下一循环之前一般都要改变循环变量 
			}
			str2[j] = 'A';
			j++;
			i--;//由于存储数字完毕的时候,原字符串str1的下标已经指向下一个元素,所以要--使其指向当前元素,不然最后的i++会使得有一个字符会被跳过不予处理 
			
		}else if(isOperator(str1[i])){
			if(LinkStack_Size(stack) > 0){//判断栈是否为空,为空直接进栈,否则才去取出栈顶元素进行优先级比较 
		
				while(Priority(str1[i]) <= Priority(*((char*)LinkStack_Top(stack)))){//在进行取出栈顶元素操作的时候,要避免操作的是一个空栈,
																					//所以事先要判断栈的大小,只有栈不为空的时候才去取栈顶元素,否则直接进栈 
					str2[j] = *((char*)LinkStack_Pop(stack));
					j++;
					if(LinkStack_Size(stack) == 0){//还要注意如果之前栈里面如果只有一个元素,则弹出以后栈又变为空,
													//此时就不要在循环判断优先级了,而应该直接跳出来将符号进栈 
						break;
					}
				}
			}
			LinkStack_Push(stack,(void*)(str1 + i));//进栈的时候可以存入的是实际数据在内存中的地址,
														//也可以将实际数据直接转换成int型的数据当作地址存入结构体的item成员 
		}else if(isLeft(str1[i])){
			LinkStack_Push(stack,(void*)(str1 + i));
		}else if(isRight(str1[i])){
			while(!(isLeft(*((char*)LinkStack_Top(stack))))){
				str2[j] = *((char*)LinkStack_Pop(stack));//相应的取出元素的时候,根据存入的方式不同用不同的取出方式,
														//如果存入的是实际数据在内存中的地址,那么top或者pop返回的是这个地址,所以要将地址值先转换成char指针类型,
														//再用取内容操作符取出该地址处存放的实际数据,
														//如果是把实际数据转换成int数据当地址存入,则取出的时候先将返回值转换成int再转成char类型的数据,
														//因为返回值是一个void*类型的值,这个值的长度和int类型的数据一样长,
														//但是我们要的是字符,所以最终要将int转成char,实际上char是一种特殊的int嘛 
				j++;
			}
			LinkStack_Pop(stack);
		}else{
			printf("Invalid expression!!\n");
			break;
		}
		/*printf("%d\n",LinkStack_Push(stack,(void*)(str1 + i)));
		printf("%c\n",*((char*)LinkStack_Pop(stack)));*/
	
		i++;
	}
	while((LinkStack_Size(stack) > 0) && (str1[i] == '\0')){
		str2[j] = *((char*)LinkStack_Pop(stack));
		j++;
	}	
	str2[j] = '\0';
	LinkStack_Destroy(stack);
}
int Value(char c)
{
	return (c - '0');
}

int Express(int left,int right,char op)
{
	int ret = 0;
	switch(op){
		case '+':
			ret = left + right;
			break;
		case '-':
			ret = left - right;
			break;
		case '*':
			ret = left * right;
			break;
		case '/':
			ret = left / right;
			break;
		default:
			break;
	}
	return ret;
}

int Result(char* str)
{
	LinkStack* stack = LinkStack_Create();
	int i = 0;
	int j = 0,k = 0;
	int ret = 0;
	int val = 0;
	while(str[i] != '\0'){
		if(isNumber(str[i])){
			int index = i;//标记数字的最高位在str中的下标 
			while(str[i] != 'A'){//将A之前的数字统计成为实际的数字大小,再把得到的结果当作地址直接存入栈 
				i++;	//得到数字的位数	
			}
			i--;//将str的下标回退一个,指向数字的个位。否则他指向的是字符A 
			for(j = i; j >= index;j--){
				val += (Value(str[j])*((int)pow(10,k)));//进行数字字符到真实数据的转换 
				k++;//用到的pow函数的参数要更新 
			}
			k = 0;//每次转换数据完成以后要将10的多少次方的参数清零 
		
			//printf("%d\n",val);
			LinkStack_Push(stack,(void*)val);//将得到的实际的数据作为临时数据压入栈 
			val = 0; //每次转换数据完成以后要将临时结果清零 
			i++;
		}else if(isOperator(str[i])){
			int right = (int)LinkStack_Pop(stack);//遇到操作符号就依次从栈里面取出右左操作数 
			int left = (int)LinkStack_Pop(stack);
			int result = Express(left,right,str[i]);
			
			LinkStack_Push(stack,(void*)result);//将优先级较高操作符对应的计算结果压入栈作为下一次的右操作数或者最终结果 
		}else{
			printf("Invalid expression!!!\n");
			break;
		}
		i++;
	}
	
	if((LinkStack_Size(stack) == 1) && (str[i] == '\0')){
		ret = (int)LinkStack_Pop(stack);//弹出最终结果 
	}else{
		printf("Invalid expression!\n");
	}
	LinkStack_Destroy(stack);//建立了任何数据结构最后都应该销毁 
	return ret;
}

int main(int argc, char *argv[]) {
	char str2[100],str1[100];
	int i = 0;
	printf("Please input The expression:\n");
	gets(str1);
	Transfer(str1,str2);
	printf("后缀表达式:\n");
	while(str2[i] != '\0'){
		if(str2[i] != 'A')
			printf("%c",str2[i]);
		i++;
	} 
	printf("\n");
	printf("the result is :%d\n",Result(str2));
	
	return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值