链栈实现简单的计算器功能

输入的格式限定有待完善

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;

const int inf=0x3f3f3f3f;
#define OK 1
#define ERROR 0

typedef int Status;

typedef struct snode{
	int data;
	struct snode* next;
}snode;


typedef struct linkstack{
	snode* top;
	snode* bottom;
	int length;
}linkstack;

Status creat(linkstack* S){//创建一个空栈 
	S->top=S->bottom=(snode*)malloc(sizeof(snode));
	if(!S->top){
		printf("申请空间失败!\n");
		return ERROR;
	}
	S->top->next=NULL;
	S->bottom->next=NULL;
	S->length=0;
	return OK; 
}

bool empty(linkstack S){//判断栈是否为空  
	return !S.length;
}

int size(linkstack S){//返回栈的大小  
	return S.length;
}

Status push(linkstack* S,int e){//元素入栈  
	snode* newx=(snode*)malloc(sizeof(snode));
	if(!newx){
		printf("申请空间失败!\n");
		return ERROR;
	}
	newx->data=e;
	newx->next=S->top->next;
	S->top->next=newx;
	if(!S->length)
		S->bottom=S->bottom->next;
	S->length++;
	return OK;
}

Status pop(linkstack* S){//弹出栈顶元素  
	if(!S->length){
	//	printf("当前栈已经为空!\n");
		return inf;
	}
	snode* del=S->top->next;
	S->top->next=del->next;
	free(del);
	S->length--;
	if(!S->length)
		S->bottom=S->top;
	return OK;
}

int gettop(linkstack S){//获得栈顶元素 存到e中  
	if(!S.length){
	//	printf("当前栈为空!\n");
		return inf;
	}
	return S.top->next->data;
}

Status show(linkstack S){//输出当前栈的内容  
	if(!S.length){
		printf("空!\n");
		return ERROR;
	}
	snode* p=S.top->next;
	while(p){
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
	return OK;
}

Status clear(linkstack *S){//清空栈  
	while(S->top->next)
		pop(S);
	return OK; 
}

Status destroy(linkstack* S){//销毁当前栈  
	snode* del;
	while(S->top){
		del=S->top;
		S->top=S->top->next;
		free(del);
	}
	S->top=S->bottom=NULL;
	return OK;
}

int type(int c){
	if(c>='0'&&c<='9')
		return 1;//数字
	return 0;//字符 
} 

/*  运算符优先级表 
		0	1	2	3	4	5	6
		+	-	*	/	(	)	#
	0+	>	>	<	<	<	>	>
	1-	>	>	<	<	<	>	>
	2*	>	>	>	>	<	>	>
	3/	>	>	>	>	<	>	>
	4(	<	<	<	<	<	=	。 
	5)	>	>	>	>	。	>	> 
	6# 	<	<	<	<	<	。	=
		
*/ 

int precede(char a,char b){//判断两个符号的优先级  表示第一个 ? 第二个 
	int rule[7][7]={//运算符优先级表 1表示> ,2表示< ,0表示= ,-1表示。 
		1, 1, 2, 2, 2, 1, 1,
		1, 1, 2, 2, 2, 1, 1,
		1, 1, 1, 1, 2, 1, 1,
		1, 1, 1, 1, 2, 1, 1,
		2, 2, 2, 2, 2, 0, -1,
		1, 1, 1, 1, -1, 1, 1,
		2, 2, 2, 2, 2, -1, 0 
	};
	
	char pp[7]={'+','-','*','/','(',')','#'};//用于查找运算符的序号  
	int hang=0,lie=0;
	while(a!=pp[hang])
		hang++;
	while(b!=pp[lie])
		lie++;
	return rule[hang][lie];
} 

int operate(int a,char theta,int b){ // a theta b 
	switch(theta){
		case '+':
			return a+b;
		case '-':
			return a-b;
		case '*':
			return a*b;
		case '/':
			return a/b;
	}
}

Status solve(){
	linkstack num,sign;
	creat(&num);
	creat(&sign);
	push(&sign,'#');
	char ch  ;
	char theta;
	int a,b;
	
	ch=getchar();
	while(ch!='#'||gettop(sign)!='#'){
 		if(!(ch=='#'||ch=='('||ch==')'||ch=='+'||ch=='-'||ch=='*'||ch=='/'||ch>='0'&&ch<='9')){
			printf("你的输入不符合计算器规则!");
			return 0;
		} 
		if(type(ch)){
			push(&num,ch-'0');
			ch=getchar();
		}
		else
			switch(precede(gettop(sign),ch)){
				case 0://括号已经匹配 
					pop(&sign);
					ch=getchar();
					break;
				case 1://碰到优先级低的运算符 先计算初结果并入栈  
					theta=gettop(sign);
					pop(&sign) ;
					a=gettop(num);
					pop(&num);
					b=gettop(num);
					pop(&num);
					if(a==inf||b==inf){
						printf("你的输入不符合计算器规则!");
						getchar(); 
						return 0;	
					}
					
					push(&num,operate(b,theta,a));
					break;
				case 2://碰到优先级高的运算符 高级运算符入栈 
					push(&sign,ch);
					ch=getchar();
					break; 		
			}
	}
	int res=gettop(num);
	pop(&num);
	pop(&sign);
	if(!empty(num)||!empty(sign)){
		printf("你的输入不符合计算器规则!");
		getchar();
		return 0;
	}
	cout<<res<<endl;
	getchar();
	return OK;
} 

int main()
{
	while(1){
		printf("\t----------这是一个计算器,请输入你想要的计算的表达式(以#结尾):----------\n");
		printf("\t\t  ------------只能输入一位数的计算和小括号------------\n"); 
		solve();
		printf("\n\n点击任意键清空计算记录~");
		getchar();
		system("cls"); 
	}
	return 0;
}

 

这里还有一个可以实现多位数字的运算的加强版

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<iostream>
using namespace std;
 
const int inf=0x3f3f3f3f;
#define OK 1
#define ERROR 0
 
typedef int Status;
 
typedef struct snode{
	int data;
	struct snode* next;
}snode;
 
 
typedef struct linkstack{
	snode* top;
	snode* bottom;
	int length;
}linkstack;
 
Status creat(linkstack* S){//创建一个空栈 
	S->top=S->bottom=(snode*)malloc(sizeof(snode));
	if(!S->top){
		printf("申请空间失败!\n");
		return ERROR;
	}
	S->top->next=NULL;
	S->bottom->next=NULL;
	S->length=0;
	return OK; 
}
 
bool empty(linkstack S){//判断栈是否为空  
	return !S.length;
}
 
int size(linkstack S){//返回栈的大小  
	return S.length;
}
 
Status push(linkstack* S,int e){//元素入栈  
	snode* newx=(snode*)malloc(sizeof(snode));
	if(!newx){
		printf("申请空间失败!\n");
		return ERROR;
	}
	newx->data=e;
	newx->next=S->top->next;
	S->top->next=newx;
	if(!S->length)
		S->bottom=S->bottom->next;
	S->length++;
	return OK;
}
 
Status pop(linkstack* S){//弹出栈顶元素  
	if(!S->length){
	//	printf("当前栈已经为空!\n");
		return inf;
	}
	snode* del=S->top->next;
	S->top->next=del->next;
	free(del);
	S->length--;
	if(!S->length)
		S->bottom=S->top;
	return OK;
}
 
int gettop(linkstack S){//获得栈顶元素 存到e中  
	if(!S.length){
	//	printf("当前栈为空!\n");
		return inf;
	}
	return S.top->next->data;
}
 
Status show(linkstack S){//输出当前栈的内容  
	if(!S.length){
		printf("空!\n");
		return ERROR;
	}
	snode* p=S.top->next;
	while(p){
		printf("%d ",p->data);
		p=p->next;
	}
	printf("\n");
	return OK;
}
 
Status clear(linkstack *S){//清空栈  
	while(S->top->next)
		pop(S);
	return OK; 
}
 
Status destroy(linkstack* S){//销毁当前栈  
	snode* del;
	while(S->top){
		del=S->top;
		S->top=S->top->next;
		free(del);
	}
	S->top=S->bottom=NULL;
	return OK;
}
 
int type(int c){
	if(c>='0'&&c<='9')
		return 1;//数字
	return 0;//字符 
} 
 
/*  运算符优先级表 
		0	1	2	3	4	5	6
		+	-	*	/	(	)	#
	0+	>	>	<	<	<	>	>
	1-	>	>	<	<	<	>	>
	2*	>	>	>	>	<	>	>
	3/	>	>	>	>	<	>	>
	4(	<	<	<	<	<	=	。 
	5)	>	>	>	>	。	>	> 
	6# 	<	<	<	<	<	。	=
		
*/ 
 
int precede(char a,char b){//判断两个符号的优先级  表示第一个 ? 第二个 
	int rule[7][7]={//运算符优先级表 1表示> ,2表示< ,0表示= ,-1表示。 
		1, 1, 2, 2, 2, 1, 1,
		1, 1, 2, 2, 2, 1, 1,
		1, 1, 1, 1, 2, 1, 1,
		1, 1, 1, 1, 2, 1, 1,
		2, 2, 2, 2, 2, 0, -1,
		1, 1, 1, 1, -1, 1, 1,
		2, 2, 2, 2, 2, -1, 0 
	};
	
	char pp[7]={'+','-','*','/','(',')','#'};//用于查找运算符的序号  
	int hang=0,lie=0;
	while(a!=pp[hang])
		hang++;
	while(b!=pp[lie])
		lie++;
	return rule[hang][lie];
} 
 
int operate(int a,char theta,int b){ // a theta b 
	switch(theta){
		case '+':
			return a+b;
		case '-':
			return a-b;
		case '*':
			return a*b;
		case '/':
			return a/b;
	}
}
 
Status solve(){
	linkstack num,sign;
	creat(&num);
	creat(&sign);
	push(&sign,'#'); 
	int a,b;
	char theta;
	char str[999];
	gets(str);
	
	for(int i=0;i<strlen(str);i++)
	if(!(str[i]=='#'||str[i]=='('||str[i]==')'||str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'||str[i]>='0'&&str[i]<='9')){
		printf("你的输入不符合计算器规则!");
		return ERROR;
	} 
	
	if(str[strlen(str)-1]!='#'||str[0]=='#'){
		printf("你的输入不符合计算器规则!\n");
		return ERROR;
	}
	
	for(int i=0;i<strlen(str);i++){
		int sum=0;
		if(type(str[i])){
			while(type(str[i])){
				int temp=str[i]-'0';
				sum=sum*10+temp;
				i++;
			}
			push(&num,sum);
		}
		
		switch(precede(gettop(sign),str[i])){
			case 0://括号已经匹配 
				pop(&sign);
				break;
			case 1://碰到优先级低的运算符 先计算出结果并入栈  
				theta=gettop(sign);
				pop(&sign) ;
				a=gettop(num);
				pop(&num);
				b=gettop(num);
				pop(&num);
				if(a==inf||b==inf){//数字栈空了,还有运算符  
					printf("你的输入不符合计算器规则!");
					return ERROR;	
				}
				push(&num,operate(b,theta,a));
				i--;
				break;
			case 2://碰到优先级高的运算符 高级运算符入栈 
				push(&sign,str[i]);
				break; 		
		}
	}
	int res=gettop(num);	
	pop(&num);
	pop(&sign);
	
//	if(!empty(num)||!empty(sign)){
//		printf("你的输入不符合计算器规则!");
//		return ERROR;
//	}
	
	cout<<"运算的结果为:"<<res<<endl;
	return OK;
} 
 
int main()
{
	while(1){
		printf("\t----------这是一个计算器,请输入你想要的计算的表达式(以#结尾):----------\n");
		printf("\t\t  ------------只能输入整数的计算和小括号------------\n"); 
		solve();
		printf("\n\n点击任意键清空计算记录~");
		getchar();
		system("cls"); 
	}
	return 0;
}

 

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来为您介绍一下如何使用链实现简易计算器。 首先,我们需要定义一个链的结构体,包括数据域和指针域: ``` struct Node { double data; Node* next; }; ``` 然后,我们需要定义一些基本的操作,如入、出、获取顶元素等: ``` void push(Node*& top, double data) { Node* newNode = new Node; newNode->data = data; newNode->next = top; top = newNode; } double pop(Node*& top) { if (top == nullptr) { throw "Stack is empty!"; } double data = top->data; Node* temp = top; top = top->next; delete temp; return data; } double peek(Node* top) { if (top == nullptr) { throw "Stack is empty!"; } return top->data; } ``` 接下来,我们可以利用这些基本操作来实现一个简易计算器。具体实现方法如下: 1. 读入一个表达式,将其中的数字和运算符分别入。 2. 当遇到一个运算符时,弹出顶的两个数字进行计算,并将结果入。 3. 重复步骤2,直到表达式中的所有运算符都被处理完毕。 4. 最终中剩下的数字就是表达式的计算结果。 下面是一个示例代码: ``` double calculate(string expression) { Node* stack = nullptr; for (int i = 0; i < expression.length(); i++) { if (isdigit(expression[i])) { double num = 0; while (i < expression.length() && isdigit(expression[i])) { num = num * 10 + (expression[i] - '0'); i++; } push(stack, num); i--; } else if (expression[i] == '+' || expression[i] == '-' || expression[i] == '*' || expression[i] == '/') { double num1 = pop(stack); double num2 = pop(stack); switch (expression[i]) { case '+': push(stack, num2 + num1); break; case '-': push(stack, num2 - num1); break; case '*': push(stack, num2 * num1); break; case '/': push(stack, num2 / num1); break; } } } double result = pop(stack); if (stack != nullptr) { throw "Invalid expression!"; } return result; } ``` 这样,我们就实现了一个简易的计算器

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值