C语言数据结构链栈实现个位数计算式(数据结构第二次实验)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Wofficre/article/details/78483941

代码没有按照老师给定的函数,逻辑比较混乱,变量名不规范;

优点是运用的库较少,内置函数较少,易懂。

题目如下:

课程名称:数据结构

实验目的:

1.掌握栈的定义及实现;

2.掌握利用栈求解算术表达式的方法。

实验要求:

1、    使用链式存储结构完成栈的各种基本操作;

2、    补充完成In(c), Preced(t1,t2),Operate(a,theta,b)三个函数。

实验题目:栈的基本操作及其应用

实验过程:

1、通过修改完善教材中的算法3.4,利用栈来实现算术表达式求值的算法。对算法3.4中调用的几个函数要给出其实现过程:

(1) 函数In(c):判断c是否为运算符;

(2) 函数Precede(t1,t2):判断运算符t1和t2的优先级;

(3) 函数Operate(a,theta,b):对a和b进行二元运算theta。

2、程序运行时,输入合法的算术表达式(中间值及最终结果要在0~9之间,可以包括加减乘除和括号),便可输出相应的计算结果。如下图:

实验提示:(仅供参考,每个函数的具体实现可以有多种方法,希望有创新)

1. 将栈的定义和实现单独保存在头文件“stack.h”中,然后在表达式求值的源程序中包含此头文件(即#include“stack.h”)。

2.表达式求值源程序的具体实现

(1) 主函数如下:

void main()

 {

   Printf(“请输入算术表达式,并以#结束.\n”);

  Printf(“the result of expression is:%d\n”,EvaluateExpression());

 }

(2) 函数EvaluateExpression的实现见算法3.22

(3) 函数In(c)的实现可以采用以下方式:

Status In(SElemType c)// 应在前面有定义typedef char SElemType;

 { // 判断c是否为运算符

   switch(c)

   {

     case'+':return TRUE;

     ……//补充完整

default:return FALSE;

   }

 }

(4) 函数Precede(t1,t2)的实现可以采用以下形式:

SElemType Precede(SElemType t1,SElemType t2)

 { //根据教材表3.1,判断两个运算符的优先关系

   SElemType f;

   switch(t2)

   {

     case '+':

     case '-':if(t1=='('||t1=='#')

                f='<';

              else

                f='>';

              break;

……//补充完整

}

   return f;

}

(5) 函数Operate(a,theta,b)的实现可以采用以下方式:

SElemType Operate(SElemType a,SElemType theta,SElemType b)

 {

   SElemType c;

   a=a-48;

   b=b-48;

   switch(theta)

   {

     case'+':c=a+b+48;

             break;

……//补充完整

   }

   return c;

 }

 

 

选做内容:进一步改进,使表达式的中间值及最终结果不局限于0~9之间的个位数。(如果完成要在实验报告中注明),如下图:

实验结果:

输入:2*(4-1)+8

输出:14

该程序能够完成个位数的四则运算。

实验分析:

1.栈的操作的特点;

2.列举调试运行过程中出现的错误并分析原因。

要求:

(1) 程序要添加适当的注释,程序的书写要采用缩进格式

(2) 程序要具在一定的健壮性,即当输入数据非法时,程序也能适当地做出反应。

(3) 程序要做到界面友好,在程序运行时用户可以根据相应的提示信息进行操作。

(4) 上传源程序到课堂派。顺序表的源程序保存为calculator.cp


代码如下:

#include<stdio.h>
#define OK 1
#define ERROR 0
typedef char ElemType;
typedef int Status;
//定义存放运算符的栈 
typedef struct StackNode1
{
	ElemType data;
	struct StackNode1 *next;	
}StackNode1,*LinkStack1;
//定义存放运算数的栈 
typedef struct StackNode2
{
	ElemType data;
	struct StackNode2 *next;	
}StackNode2,*LinkStack2;
//初始化运算符的栈 
Status InitStack_S1(LinkStack1 &S1)
{
	S1=NULL;
	return OK;
}
//初始化运算数的栈 
Status InitStack_S2(LinkStack2 &S2)
{
	S2=NULL;
	return OK;
}
//运算符进栈操作 
Status Push_S1(LinkStack1 &S1,ElemType e)
{
	LinkStack1 p;
	p=new StackNode1;
	p->data=e;
	p->next=S1;
	S1=p;
	return OK;	
}
//运算数进栈操作 
Status Push_S2(LinkStack2 &S2,ElemType e)
{	
	LinkStack2 p;
	p=new StackNode2;
	p->data=e;
	p->next=S2;
	S2=p;
	return OK;	
}
//运算符出栈操作 
ElemType Get_S1(LinkStack1 &S1)
{
	if(S1==NULL) return ERROR;
	LinkStack1 p; 
	p=S1;
	S1=S1->next;
	return p->data; 
}
//运算数出栈操作 
ElemType Get_S2(LinkStack2 &S2)
{
	if(S2==NULL) return ERROR;
	LinkStack2 p;
	p=S2;
	S2=S2->next;
	return p->data;
}
//删除运算符栈顶元素操作 
Status Pop_S1(LinkStack1 &S1)
{
	LinkStack1 p;
	p=S1;
	S1=S1->next;
	delete p;
	return OK;
}
//判断是否为运算符 
Status If(char a)
{
	if((a=='+')||(a=='-')||(a=='*')||(a=='/')||(a=='(')||(a==')')||(a=='#'))
	{
		return OK;
	}
	else
	{
		return ERROR;
	}
}
//比较运算符优先级 
ElemType Compare(char a,char b)
{
	int a1;
	int b1;
	char m;
	char c[7][7]=
	{
		{'>','>','<','<','<','>','>'},
		{'>','>','<','<','<','>','>'},
		{'>','>','>','>','<','>','>'},
		{'>','>','>','>','<','>','>'},
		{'<','<','<','<','<','=','0'},
		{'>','>','>','>','0','>','>'},
		{'<','<','<','<','<','0','1'}
	};
	switch(a)
	{
		case '+':
			a1=0;
			break;
		case '-':
			a1=1;
			break;
		case '*':
			a1=2;
			break;
		case '/':
			a1=3;
			break;
		case '(':
			a1=4;
			break;
		case ')':
			a1=5;
			break;
		case '#':
			a1=6;
			break;
	}
	switch(b)
	{
		case '+':
			b1=0;
			break;
		case '-':
			b1=1;
			break;
		case '*':
			b1=2;
			break;
		case '/':
			b1=3;
			break;
		case '(':
			b1=4;
			break;
		case ')':
			b1=5;
			break;
		case '#':
			b1=6;
			break;
	}
	m=c[a1][b1];
	return m;
}
//计算函数 
ElemType Cacluate(char c1,char c2,char c3)
{
	int result;
	int a;
	int b;
	a=(int)(c2-'0');
	b=(int)(c3-'0');
//	printf("检验计算函数是否转换成功为int型:%d\n",a);
//	printf("检验计算函数是否转换成功为int型:%d\n",b);
	switch(c1)
	{
		case '+':
			result=a+b;
			break;
		case '-':
			result=a-b;
			break;
		case '*':
			result=a*b;
			break;
		case '/':
			result=a/b;
			break;	
	}
	result=result+'0';
	return result;
}
int main()
{	
	LinkStack1 S1;
	LinkStack2 S2;
	char s[20];                          //储存表达式的字符数组 
	int a;
	int i=0;
	char r1;
	char r2;
	char result;                         //结果 
	char cacluate1,cacluate2,cacluate3;	 //传入计算函数的三个字符变量 
	S1=new StackNode1;
	S2=new StackNode2;
	InitStack_S1(S1);InitStack_S2(S2);
	printf("请输入表达式(以'#'结束):");
	scanf("%s",&s);
	Push_S1(S1,'#');
	Push_S2(S2,'1');
	while(1)
	{
		a=If(s[i]);
		if(a==1)
		{
			//如果是运算符时,进行判断 
			r1=Compare(S1->data,s[i]);
			//若新准备进栈的运算符优先级低时,将栈顶运算符取出并进行计算,
			//栈顶向下移,不进行i++判断下一个字符 
			if(r1=='>')
			{
				cacluate1=Get_S1(S1);
				cacluate2=Get_S2(S2);
				cacluate3=Get_S2(S2);
				r2=Cacluate(cacluate1,cacluate3,cacluate2); 
				Push_S2(S2,r2);			
			}
			//若新准备进栈的运算符优先级高时,进栈,判断下一个字符 
			if(r1=='<')
			{
				Push_S1(S1,s[i]);
				i++;
			}
			//括号相遇时,将左括号弹出栈,并且跳过右括号 
			if(r1=='=')
			{
				Pop_S1(S1);
				i++;
			} 
			if(r1=='0')
			{
				printf("您输入的表达式有错误!");
				break;
			}
			//最后两个#号相遇时,取得栈2的结果 
			if(r1=='1')
			{
				result=S2->data;
				break;
			}
		}
		//运算数时,直接进入栈2 
		else
		{
			Push_S2(S2,s[i]);
			i++;
		}
				
	}
	result=(int)result-'0'; 
	printf("结果是:%d",result);
	return 0;			
}

收获:


1.C语言中如果想把一个整型通过字符型过渡时可进行如下操作:

a=a-'0';                    //将a转换为距离字符'0'a个ascii单位的字符

a=(int)a-'0';             //需要用时再转换为整型


2.C语言中可以把0-9的字符型直接转换为整型,操作参考1

a=(int)(a-'0'); 



猜你喜欢

转载自blog.csdn.net/Wofficre/article/details/78483941