#include "stdafx.h"
#include "string.h"
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#include "math.h"
#include "process.h"
#include "iostream.h"
#define NULL 0 //NULL替代0
#define OK 1 //OK替代1
#define ERROR 0 //ERROR替代0
#define OVERFLOW -2 //内存分配失败后返回的EXIT值
#define STACK_BEGIN_SIZE 10 // 存储空间初始分配量
#define STACK_INCREASE 2 // 存储空间分配增量
typedef struct CsStack
{
double *base; // 栈构造之前和销毁之后,BASE的值均为NULL
double *top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
}CsStack; // 构造顺序栈
void InitStack(CsStack &S) // 构造一个空栈S
{
if(!(S.base=(double *)malloc(STACK_BEGIN_SIZE*sizeof(double))))//S.BASE值为NULL,分配失败
{
exit(OVERFLOW); // 内存分配失败,跳出
}
S.top=S.base;//将栈置为空栈
S.stacksize=STACK_BEGIN_SIZE;//设定栈大小为默认常量STACK_BEGIN_SIZE
}
double ClearStack(CsStack &S) //将栈清空,置为空栈
{
S.top=S.base; //重置栈为空栈
return OK;
}
double GetTop(CsStack S,double &e)
{
if(S.top>S.base) // 若栈不空,则用e返回S的栈顶元素,并返回OK
{
e=*(S.top-1);
return OK;
}
else //否则返回ERROR
{
return ERROR;
}
}
void Push(CsStack &S,double e) // 插入元素e为新的栈顶元素
{
if(S.top-S.base>=S.stacksize) // 实际长度大于目前栈大小,栈满的情况,增加链表长
{
S.base=(double *)realloc(S.base,(S.stacksize+STACK_INCREASE)*sizeof(double));//追加STACK_INCREASE大小的存储空间
if(!S.base) //S.BASE值为NULL,分配失败
{
exit(OVERFLOW); // 内存分配失败,跳出
}
S.top=S.base+S.stacksize;// 栈顶指针指向重定义
S.stacksize=S.stacksize+STACK_INCREASE;// 栈长度重定义
}
*(S.top)++ = e;//先将栈顶元素为e后栈顶指针下移
}
double Pop(CsStack &S,double &e)
{
if(S.top==S.base)// 若栈空,返回ERROR
{
return ERROR;
}
else
{
e=*(--S.top);// 若栈不空,将指针指向栈顶下一位,用e返回其值
return OK;
}
}
char Compare(char t1,char t2)// 判断t1,t2两符号的优先关系
{
char f;
switch(t2)
{
case '+':
case '-':
if(t1=='('||t1=='=')
{
f='<'; // + -的优先级仅比( = 大
}
else
{
f='>'; // 除上述以外条件
}
break;
case '*':
case '/':
if(t1=='*'||t1=='/'||t1==')'||t1=='s'||t1=='l'||t1=='g'||t1=='c'||t1=='t'||t1=='o'||t1=='^')
{
f='>'; // * /的优先级比* / ) s l g c ^低
}
else
{
f='<'; // 除上述以外条件
}
break;
case '(':
if(t1==')') //如)(的表达式是错误的
{
printf("\n\t →出错啦←\n");
printf("| 原 因:表达式输入格式错误。 |\n");
exit(ERROR);
}
else
{
f='<'; // 除上述错误类型外,“(”优先级最大
}
break;
case ')':
switch(t1)
{
case'(':
f='='; // 优先级相同即(),然后脱括号接收下一字符
break;
case'=':// 如=)的表达式是错误的
printf("\n\t →出错啦←\n");
printf("| 原 因:表达式输入格式错误。 |\n");
exit(ERROR);//尚未解决的问题
default :f='>'; // 除上述以外类型“)”优先级最小
}
break;
case'=':
switch(t1)
{
case'=':
f='='; // 优先级相同即==,省去后接受下一字符
break;
case'(' : // 如(=的表达式是错误的
printf("\n\t →出错啦←\n");
printf("| 原 因:表达式输入格式错误。 |\n");
exit(ERROR);//尚未解决的问题
default :f='>';// 除上述以外类型“=”优先级最小
}
break;
case'^':
if(t1=='+'||t1=='-'||t1=='*'||t1=='/'||t1=='('||t1=='^'||t1=='=')
{
f='<';// + - * / ( ^ =优先级比 ^ 低
}
else
{
f='>';// 除上述以外其他条件
}
break;
case's':
case'c':
case'g':
case'l':
case't':
case'o':
switch(t1)
{
case')':
case'l':
case'g':
case'c':
case's':
case't':
case'o':
printf("\n\t →出错啦←\n");
printf("| 原 因:表达式输入格式错误。 |\n");
printf("| 详 细:您出现了多个函数符号连用的情况。 |\n\n");
exit(ERROR);//尚未解决的问题
case'(':
case'=':
case'+':
case'-':
case'*':
case'/':
case'^':f='<';break;
}
break;
}
return f;
}
double Operate1(double a,char JS_ysf,double b)
{//做四则运算和乘方运算
double c;
switch(JS_ysf)
{
case'+':c=a+b;break;
case'-':c=a-b;break;
case'*':c=a*b;break;
case'/':c=a/b;break;
case'^':c=pow(a,b);break;
}
return c;
}
double Operate2(char JS_ysf,double a)
{//做sin、cos、lg、ln的运算
double c;
switch(JS_ysf)
{
case's':c=sin(a);break;
case'c':c=cos(a);break;
case't':c=sin(a)/cos(a);break;
case'o':c=cos(a)/sin(a);break;
case'l':c=log(a);break;
case'g':c=log10(a);break;
}
return c;
}
double In(char c) // 判断c是否为12种运算符之一
{
switch(c)
{
case'+':
case'-':
case'*':
case'/':
case'(':
case')':
case'=':
case'^':
case's':
case'c':
case't':
case'o':
case'l':
case'g':return 1;
default:return 0;
}
}
void main()
{
printf("\t〓〓〓欢迎使用CS堆栈计算器 Ver 2.0 § 程序设计:05141 曹硕〓〓〓\n");
printf("\t| ★目前支持★ 加、减、乘、除、指数、正余弦、正余切、对数及括号|\n");
printf("\t| ★独特功能★ 人性化交互界面、多次进行运算、自动检错报错机制。|\n");
printf("\t| ★输入格式★ “表达式=”回车出结果(结果保留15位有效小数) |\n");
printf("\t| ★三角函数★ 正弦 s(),余弦 c(),正切 t(),余切 o() |\n");
printf("\t| ★对数函数★ 自然对数 l(),以十为底对数 g() |\n");
printf("\t| ★操作说明★ 若您中途想退出,请您输入 Q 回车 |\n");
CsStack StackZF,StackSZ; //结构体变量名表列
double a,b,x,JS_ysf; //存放即时数据
double result; //最终结果变量
double f; //单步结果变量
char c; // 字符串接受变量
char z[60]; // 字符串转数字的中间数组
char js[20]; // 垃圾字符回收数组
int i; // 循环增加量
char dh; // 控制多次运算的变量
int jc=0; // 检查首位是否为“-”的计数器
InitStack(StackZF);// 构造一个空栈来存放运算符
InitStack(StackSZ);// 构造一个空栈来存放数字
start_do: //循环开始标志
do
{
Push(StackZF,'='); // 将“=”压入栈,避免栈为空。
printf("\n请输入算术表达式:");
c=getchar(); //获得首个字符
if((c=='+' || c=='-' || c=='*' || c=='/' || c=='=' || c=='^' || c==10) && jc==0)//判断首位是否运算符
{
if(c==10) goto start_do;
printf("\n\t →出错啦←\n");
printf("| 原因:首位不能是运算符。 |\n");
printf("| 详细:您首位出现了运算符“%c”|\n",c);
if(c==13 ||c==10)
{
jc=0;//重置判断首位变量
goto start_do;
}
else
{
jc=0;//重置判断首位变量
gets(js);//用数组Z接收冗余字符
goto start_do;
}
}
jc++;
GetTop(StackZF,JS_ysf);//用e返回S的栈顶元素“=”
while(c!='='||JS_ysf!='=')//当c或即时栈顶元素不等于'='时执行循环
{
if(In(c)) // 判断c是否为12种运算符之一
{
switch(Compare(JS_ysf,c))//获得优先级高的运算符
{
case '<': //栈顶运算符优先级低的情况
Push(StackZF,c); //c的优先级高于字符栈顶运算符优先级的情况
c=getchar(); //继续获得新的c
GetTop(StackZF,JS_ysf); //获得字符栈顶符号给运算符
break;
case '='://脱括号并接收下一字符
Pop(StackZF,JS_ysf); //将运算符压入堆的下一位
GetTop(StackZF,JS_ysf); //获得目前堆顶运算符
if(JS_ysf=='s'||JS_ysf=='l'||JS_ysf=='c'||JS_ysf=='g'||JS_ysf=='t'||JS_ysf=='o') //对特殊运算符号的处理
{
Pop(StackSZ,f); //将f压入数字堆的下一位
Pop(StackZF,JS_ysf); //将运算符压入字符堆的下一位
Push(StackSZ,Operate2(JS_ysf,f)); //将特殊运算结果压入数字堆顶
GetTop(StackZF,JS_ysf); //获得字符堆顶的运算符
c=getchar();
break;
}
else
{
c=getchar();
break;
}
case '>'://退栈并将运算结果入栈
if(JS_ysf=='+'||JS_ysf=='-'||JS_ysf=='*'||JS_ysf=='/'||JS_ysf=='^')
{
Pop(StackZF,JS_ysf); //将即时运算符压入字符堆的下一位
Pop(StackSZ,b); //将b值压入数字堆的下一位
Pop(StackSZ,a); //将A值压入数字堆的下一位(高于b栈位)
f=Operate1(a,JS_ysf,b); //求解值f
Push(StackSZ,f); //将运算结果f压入栈顶
GetTop(StackZF,JS_ysf); //获得字符堆顶的运算符
break;
}
else break;
}
}
else if((c>='0' && c<='9') || c=='.')//对数字的处理
{
i=0;
do
{
z[i]=c;
i++;//将数字存入数组z[]中
c=getchar();
}while((c<='9' && c>='0') || c=='.');
z[i]=0; //此为\0空字符结束字符串
result=atof(z); //ATOF()函数自动将字符数组转为Double型数
Push(StackSZ,result); //将结果数压入数字堆栈栈顶
}
else if(c=='q' ||c=='Q')//c为q或Q时,退出程序
{
goto end;
}
else//c为非法字符时,做出相应错误提示并返回重输入
{
printf("\n\t →出错啦←\n");
printf("| 原因:表达式输入格式错误。 |\n");
if((c<'0' || c>'9') && c!=10)
{
printf("| 详细:包含非法字符“%c…”。 |\n",c);
}
else
{
printf("| 详细:表达式结束缺少“=”。 |\n");
}
if(c==13 ||c==10)
{
jc=0;//重置判断首位变量
goto start_do;
}
else
{
jc=0;//重置判断首位变量
gets(js);//用数组Z接收冗余字符
goto start_do;
}
}
}
GetTop(StackSZ,x); //栈StackSZ顶即为运算结果
printf("\n计算结果为%10.15f",x); //输出结果
ClearStack(StackZF); //重置栈为空栈
ClearStack(StackSZ); //重置栈为空栈
printf("\n\n继续计算么?(按Y键继续)\n");//用键盘控制是否再次运算
dh=getch();
if(dh==89 || dh==121)
{
dh=1;
jc=0;//重置判断首位变量
}
else
{
dh=0;
}
x=getchar();
}while(dh);//循环使用以上程序达成多次运算
end:
printf("\n\t →成功退出←\n\n CS堆栈科学计算器期待您的再次使用!\n 程序版本:Ver 2.0\n 程序设计:05141班 曹硕.\n\n");
}
|