📄 includes.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 + -