⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 includes.c

📁 即时计算加法
💻 C
字号:
/*
  Name:includes.c
  Copyright:Starting Line
  Author:
  Date: 18-11-08 00:25
  Description:includes.h下两个主要函数的定义
*/

#include "includes.h"

#define REPEAT 1

extern Liner * CalLine_;
extern Lstack * CalStack_;
extern LineHis * LineHisHead;
extern LineHis * HisPoint;
extern FTYPE FUNList [ FUN_NUM ];  //modified by  
int ResFlag = 0;//结果标志,0为正确,1为非正确

/*
  Function Name:LstCal
  Author: 
  Description:用于计算表达式
*/

/*对于省略乘号的情况采用如下算法:在读取非数字时考虑前一个处理的元素是否为数字(即最后一次压栈是不是压数字栈),如果是,按正常规则压入'*' 
对于两个运算符字符连在一块的情况,按错误处理,即在语法中说明必须加括号 如pi(sin1)或者(pi)sin1这样都是允许的
 */

//CalLine放置线性表达式
//CalStack放置后缀表达式
//两个参数均已初始化好,不需要检查
//注意,你还得写一个工程,将所有的运算符号,放进去,做成一个文件,并且写一个读取这个文件的函数
//同样用二维数组读入
void LstCal ( Liner * CalLine , Lstack * CalStack )
{	//计算表达式
	//数字栈栈底为CalStack->Dstack,运算符栈栈底为CalStack->Cstack,两个栈的长度为均为CalStack->StackLen
	//将参数同时用全局变量定位,便于扩展
	CalLine_ = CalLine;
	CalStack_ = CalStack;
	FTYPE *pFT=NULL;   //指向FUNlist中个运算符结构体的指针,表示比较到FUNlist的哪个位置,先初始化为NULL
	char Temp='\0';         //临时存储每一次读到的字符,初始化为'\0'
	char *pL=CalLine -> CLine;     //指向当前处理的表达式中字符
	num Tempnum=0.0;           //临时变量,用于处理数字,每次处理完重置为0
	int Tempxs=1;			//临时存储处理小数时应除的数,初始值为1
	char TempCalChar[FUN_SIZE]={'\0'};  //临时变量,用于存放所读入的运算符,FUN_SIZE为预设运算符的长度
	char *pTC=NULL;         //指向TempCalChar中字符的指针,表示读取到TempCalChar的哪个位置 ,先初始化为NULL     
	num result = 0.0;   //结果
	int TempSize=0;     //当一个栈满的时候由于要进行扩展,扩展后两个栈底同时变化,需先记录栈中当前元素个数
	FUNT TempFuntype=-1;   //临时存储当前运算符的funtype,,每次处理完重置为-1		
	int numflag=0;      //判断刚处理的是否为数字,是为1不是为0(即最后一次压栈是不是压数字栈)
	int leftflag=0;      //标记是否找到了当前右括号对应的左括号,初始化为0 
	LoadFUN();	//读取运算符文件
	while ((Temp=*pL )!= '\0' )
	{
		//当未遇到表达式结束标志时
		//逐步将线性表达式编译成为后缀表达式,同时进行计算
		//
		//的任务
		//
		//
		if(Temp>='0'&&Temp<='9')
		{	
			do{				
				Tempnum=Tempnum*10+(Temp-'0');
				pL++;
				Temp=*pL;
			}while(Temp>='0'&&Temp<='9');				  //此时pL指向非数字
			if(Temp=='.')		//若下一个元素为小数点,则该数为小数,进一步处理
			{
				pL++;
				Temp=*pL;
				if(Temp>='0'&&Temp<='9')
				{
					do{	
						Tempxs=Tempxs*10;			
						Tempnum=Tempnum+(double)(Temp-'0')/Tempxs;  //相当于每一次在将小数点
						pL++;
						Temp=*pL;						
					}while(Temp>='0'&&Temp<='9');				  //此时pL指向非数字
					Tempxs=1;			//处理完小数,重置
				}
				else
				{
					Error( E_GE );          //小数点后没有紧跟数字,为语法错
				/*	free ( CalLine -> CLine );
					free ( CalStack -> Cstack );
					free ( CalStack -> Dstack );
					free ( CalLine );
					free ( CalStack );*/
					return ;
				}
			}
			//原负数处理
			if(CalStack->Dtop-CalStack->Dstack<CalStack->StackLen)  ;//若栈不满,将直接进栈				
			else 
			{
				Error(E_OVERFLOW);						//否则扩展栈后再进栈
			}
			*(CalStack->Dtop++)=Tempnum;           //读到第一个不是数字时将计算好的数字进栈到数字栈
			Tempnum=0.0;                   //重新置为0
			numflag=1;						 //标记刚处理的字符为数字
			
		}//if                      //此时pL指向非数字
		
		if(Temp!= '\0')
		{
			if(numflag==1)				//判断是否需要人为加入一个'*'
				if(Temp!='+'&&Temp!='-'&&Temp!='*'&&Temp!='/'&&Temp!='^'&&Temp!='c'&&Temp!='p'&&Temp!='n'&&Temp!=')')//加了个不等于右括号的情况 /
					Temp='*';                                                                        //此处的n表示nroot首字母,由于接收的运算符以'n'开头的只有nroot故不会出错 
			switch(Temp)                 //判断运算符
			{
				case '(':   //遇到左括号无条件进运算符栈,相当于一个虚拟的栈底.
					{
						if( CalStack -> Ctop - CalStack -> Cstack < CalStack -> StackLen )  ;//若栈不满,将直接进栈
						else 
						{
							Error(E_OVERFLOW);						//否则扩展栈后再进栈				
						}
						*((CalStack->Ctop)++)=left;          //将左括号的内部序号无条件进运算符栈
						numflag=0;						 //标记刚处理的字符为非数字
						pL++;                    //表达式指针指向下一个,准备处理下一个
						break;
					}
				case ')': 
					{   
						while(CalStack->Ctop!=CalStack->Cstack&&leftflag!=1)           //若栈非空,且未找到左括号 
						{
							if(*(CalStack->Ctop-1)!=left)					//若栈顶元素不等于左括号,则计算,退栈
							{
								Tempnum=calproc(*(CalStack->Ctop-1),CalStack);							
								if(CalStack->Dtop-CalStack->Dstack<CalStack->StackLen)  ;//如果栈不满,则无需扩展
								else 
									Error(E_OVERFLOW);                 //为压数字栈准备足够的空间
								*(CalStack->Dtop++)=Tempnum;	
								Tempnum=0.0;                   //重新置为0
								numflag=1;						 //标记刚处理的字符为数字
								CalStack->Ctop--;
							}
							else 
							{
								CalStack->Ctop--;                        //若栈顶元素等于左括号,则直接退栈,此时相当于一个虚拟栈释放
								pL++;
								leftflag=1;						   //找到了与之匹配的左括号,准备处理下一个字符
							}
						}//while						
						if(leftflag!=1)
						{
							Error(E_GE);
						/*	free ( CalLine -> CLine );
							free ( CalStack -> Cstack );
							free ( CalStack -> Dstack );
							free ( CalLine );
							free ( CalStack );*/
							return;
						}                          //说明运算符栈为空仍然找不到左括号,说明有语法错误
                        			else
							leftflag=0;         //否则说明已经找到了左括号,重置为0
							//
							//
							//
							//修改点
							//
							//
							//
							//
                        			break;
					}
				case '+':
					{
						TempFuntype=plus;
						pL++;                    //表达式指针指向下一个,准备处理下一个
						break;
					}
				case '-': 
					{
						if(!numflag)              //如果刚处理的不是数字,说明这里的'-'是一个负号
						{
							TempFuntype=neg__;
						}
						else
							TempFuntype=minus;//	strcpy(TempCalChar,"minus");	
						pL++;                    //表达式指针指向下一个,准备处理下一个 
						break;
					}
				case '*': 
					{	
						if(*pL=='*')					//!!!!!!!判断此次处理的*是否真实存在
						{								//若真实存在,将指针指向表达式中下一个字符,便于进行下一次处理
							pL++;						//这就意味着,若非真实存在,当这次处理完虚拟的'*'后将进行本次实际读到的运算符的处理
						}								//关键是利用了'*'是单字符即可表示运算符的特点,即无需读取表达式下一个,于是处理完pL指针仍然不动
						TempFuntype=multi;	
						break;
					}
				case '/': 
					TempFuntype=divide;
					pL++;                    //表达式指针指向下一个,准备处理下一个
					break;
				case '^': 
					TempFuntype=ntime__;	
					pL++;                    //表达式指针指向下一个,准备处理下一个
					break;
				default  :                //若都不是上述字符,则需开始逐个读取字符
					{
						pTC=TempCalChar;  
						do{						         
							*pTC=Temp;
							pTC++;
							pL++;
							Temp=*pL;
						}while(Temp>='a'&&Temp<='z');							//此时Temp为非字母,pL指向Temp
						*pTC='\0';           //运算符读取结束
						pFT=FUNList;
						while((pFT - FUNList < FUN_NUM ) && strcmp ( TempCalChar,pFT -> Ftype ) != 0 )  //FUN_NUM为FUNList行数,即字符串 数
						{
							pFT++;
						}
						if((pFT - FUNList >= FUN_NUM ))        //未成功匹配
						{
							Error( E_GE );		  //则为语法错误
						/*	free ( CalLine -> CLine );
							free ( CalStack -> Cstack );
							free ( CalStack -> Dstack );
							free ( CalLine );
							free ( CalStack );*/
							return ;
						}
						else TempFuntype = pFT -> Fnum;//否则找出这个运算符的代号

					}//default
			}//switch               //此时pL同一指向下一个待处理的表达式字符
			if(TempFuntype!=-1)        //若刚读取的是常规运算符(不是左右括号),则判断优先级进栈.注:仅在读取表达式的时候考虑表达式是否了省略乘号
			{
				while(CalStack -> Ctop != CalStack -> Cstack && ( * ( CalStack -> Ctop - 1 ) / 100 >= TempFuntype / 100 ))     //若栈非空且栈顶元素的优先级大于等于当前运算符
				{
					Tempnum = calproc ( * ( CalStack -> Ctop - 1 ) , CalStack );					//取当前栈顶运算符进行计算
					if ( CalStack -> Dtop - CalStack -> Dstack < CalStack -> StackLen )  ;//如果栈不满,则无需扩展
					else 
						Error(E_OVERFLOW);                 //为压数字栈准备足够的空间		
					* ( CalStack -> Dtop++ ) = Tempnum;      //将运算结果进数字栈
					Tempnum = 0.0;						  //重新置为0
					numflag = 1;						 //标记刚处理的字符为数字
					CalStack -> Ctop --;				 //完成运算的运算符退栈
				}//while
				* ( CalStack -> Ctop++ ) = TempFuntype;         //进栈
				numflag=0;						 //标记刚处理的字符为非数字
				TempFuntype=-1;					//处理完毕,重置
			}//if
		}//if
	}//while
		//至此,表达式的字符读取完毕
	while(CalStack->Ctop!=CalStack->Cstack)     //若运算符栈非空,则取栈顶元素进行计算
	{
		Tempnum=calproc(*(CalStack->Ctop-1),CalStack);					//取当前栈顶运算符进行计算
		if(CalStack->Dtop-CalStack->Dstack<CalStack->StackLen)  ;//如果栈不满,则无需扩展
		else 
			Error(E_OVERFLOW);                 //为压数字栈准备足够的空间					
		*(CalStack->Dtop++)=Tempnum;      //将运算结果进数字栈
		Tempnum=0.0;                   //重新置为0
		numflag=1;						 //标记刚处理的字符为数字
		CalStack->Ctop--;				 //完成运算的运算符退栈
	}//while	
	if(CalStack->Dtop-CalStack->Dstack!=1)      //此时运算符栈已经为空但数字栈含有不止一个元素,则判断为语法错误
	{
		Error( E_GE );
/*		free ( CalLine -> CLine );
		free ( CalStack -> Cstack );
		free ( CalStack -> Dstack );
		free ( CalLine );
		free ( CalStack );*/
		return ;
	}
	else									//若没有语法错误,则将栈中的唯一元素作为计算结果输出
	{
		result=*(CalStack->Dtop-1);
		
	}

	AddHis ( CalLine );//将以及经计算的表达式(正确的表达式)加入历史记录
	HisPoint = LineHisHead ;
			//完成计算,将传入的用于计算表达式栈指针指向的空间从内存中释放
	if ( ResFlag == 0 )
	{
		printf("\nThe result is: %lf\n",result);	//打印计算结果
	}
}


/*
  Function Name:Shell
  Author: 
  Description:Shell函数
*/

void Shell ( void )
{
        Liner * CalLine = NULL;//声明一个线性域
	Lstack * CalStack = NULL;//声明一个栈
	while ( REPEAT )//提供消息循环
	{
		CalLine = NULL;
		CalStack = NULL;
		CalLine = ( Liner * ) malloc ( sizeof ( Liner ));
		CalStack = ( Lstack * ) malloc ( sizeof ( Lstack ));
		if ( CalLine == NULL || CalStack ==NULL )
		{
			Error ( E_OVER_MEM );
		}
		LinerCreater ( CalLine );//分配空间;
		LstCreater ( CalStack );
		CalLine_ = CalLine;//将他们在全局变量中做映像便于传递参数
		CalStack_ = CalStack;
		GetLine ( CalLine );
		switch ( * ( CalLine -> CLine + 0 ))
		{
			case ':' :
			{
				//Init ( CLS );
				command ( CalLine -> CLine );
				free ( CalLine -> CLine );
				free ( CalLine );
				break;
			}
			default :
			{
				LstCal ( CalLine , CalStack );
				ResFlag = 0;
				free ( CalLine_ -> CLine );
				free ( CalStack_ -> Cstack );
				free ( CalStack_ -> Dstack );
				free ( CalLine_ );
				free ( CalStack_ );
				//puts ( CalLine_ -> CLine );
				break;
			}
		}
	}
}

/*
  Function Name:_24Point
  Author: 
  Description:二十四点游戏
*/

void _24Point ( void )
{
	//24点
	//暂缺
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -