calculator.c

来自「redboy for gba 是BPNS为GBA编写的一个小软件。软件的邹形是B」· C语言 代码 · 共 737 行 · 第 1/2 页

C
737
字号
#include <CsAgb.h>
#include <math.h>
#include <rb_math.h>
#include <Qgraph.h>
#include <graph.h>
#include <rb_stdio.h>
#include <rb_string.h>
#define num_sel_xp *(u16 *) 0x06012C00
#define num_sel_yp *(u16 *) 0x06012C04
#define font_color RGB(0,15,5)
#define del_s 0
#define quit_s 1
#define ok_s 2
#define back_s 3
#define pre_s 4
#define exp_max_len 90
extern void n_box(u8 xp,u8 yp,u8 xsp,u8 ysp,u16 co,u16 bg);
extern void win_plate(char *tit,char *mes,u16 bg);
extern void (*sys_deamon)();
extern u8 rb_xp;
extern u8 rb_yp;
extern u8 rb_error;
extern void wait(u32 count);//等待count毫秒
extern void show_text(char *tit,char *txt);
extern void calcu_set(double *M);
extern void calcu_get(double *M);
const char calfun[19][10]={
"SIN","COS","TAN","LOG","LN","POW","EXP","SQR","ABS","DEG",//10
"INT","ASIN","ACOS","ATAN","SINH","COSH","TANH","RAD"};
const char cal_errors[6][40]={
"非法负参数","参数范围溢出","非法函数调用","表达式错误","括号不匹配","结果溢出"};
const char cal_helps[]="科学计算器V1.0使用说明:
=============================
在输入模式下:
R/L     :移动光标
R/L+Down:快速移动光标
B       :删除
Dre     :(方向键)选择项目
A       :选定项目
START   :确定计算
SELECT  :帮助
R+L     :退出计算器
在结果显示(错误报告)模式下:
A       :继续上次输入
B       :清空上次输入
START   :将此次运算结果存入M
=============================
键盘说明:
D    :删除光标后所有字符
R    :上次计算结果
M    :用户保存数据
C+Num:常量调用
Num范围0-9,其意义如下:
C0:R
C1:M
C2:真空光速
C3:圆周率
C4:e
C5:阿伏伽德罗常量
C6:电子电量
C7:万有引力常量
C8:电子质量
C9:质子质量
=============================
运算符说明:
+,-,*,/ :基本运算符
%       :模除
^       :乘幂
()      :括号
E       :科学计数法指数标志
优先级:()>^>%=*=/>+=-
函数说明:
sin,cos,tan   :三角函数
asin,acos,atan:反三角函数
deg,rad       :弧度←→角度转换
sinh,cosh,tanh:双曲函数
pow           :10^x
exp           :e^x
log           :常用对数
ln            :自然对数
=============================
示例:
sin(23)
1+cos(sin(3)+4)
=============================
注意:
本计算器的角度模式为弧度制。
如计算30度角的正弦应为:
sin(rad(30)).
在一般情况下,*不要省写,否则结果可以能出错.";
void cal_say_help()
{
   show_text("科学计算器帮助说明",cal_helps);
}
void cal_deamon()
{
   r_box(11+(rb_xp%31)*7,23+16*(rb_xp/31),18+(rb_xp%31)*7,33+16*(rb_xp/31),0,5);
   rb_yp=!rb_yp;
}
int IsOpt(char ch)//是否为运算符
{
   char opts[]="+-*/%^()M@";
   int i=0;
   while (opts[i]!='\0')
   {
	   if (ch==opts[i]) return 1+i;
	   i++;
   }
   return 0;
}
int IsFun(char *fun)
{
	int i;
	for (i=0;i<18;i++) if (strcmp(fun,calfun[i])==0) return i+1;
	return 0;
}
int IsNum(char ch)
{
	return (ch>='0' && ch<='9');
}
int cal_exp_dns(char *exp,u8 *type,double *val)
{
	int i=0;
	int vp=0;
	int sp=0;
	int first=1;
	int get,get1;
	int isnum=IsNum(exp[0]);
	int start=0;
	char str[exp_max_len];
	while (i<exp_max_len && exp[i]!='\0')
	{
		get1=IsOpt(exp[i]);
		if (get1)//遇到运算符
		{
			if(isnum && exp[i-1]=='E' && (exp[i]=='-' || exp[i]=='+')) isnum=1;
			else if (start)//有数据需处理
			{
				str[sp]='\0';
				sp=0;
				start=0;
				if (isnum)//是数字
				{
					type[vp]=1;//置数字标志
					val[vp]=str_to_num(str);
					vp++;
					isnum=0;
				}
				else
				{
					get=IsFun(str);
					if (!get) return 2;//出错
					type[vp]=2;//置函数标志
					val[vp]=(double)get;
					vp++;
				}
				first=0;

			}
			if(first && exp[i]=='-')//是负号
			{
				str[sp]='-';
				sp++;
				first=0;
				isnum=1;
			}
			else if(isnum && exp[i-1]=='E' && (exp[i]=='-' || exp[i]=='+'))
			{
				if (exp[i]=='-')
				{
					str[sp]=exp[i];
					sp++;
				}
			}
			else if (first && exp[i]=='+') {isnum=1;first=0;}//是正号
			else
			{
				first=0;
				type[vp]=3;//置运算符标志
				val[vp]=(double)get1;
				vp++;
				if (exp[i]=='(') first=1;
				isnum=IsNum(exp[i+1]);
				start=0;
			}

		}
		else
		{
			str[sp]=exp[i];
			sp++;
			start=1;
		}
		i++;
	}
	if (start)
	{
		str[sp]='\0';
		if (isnum)//是数字
		{
			type[vp]=1;//置数字标志
			val[vp]=str_to_num(str);
			vp++;
		}
		else return 4;
	}
	type[vp]=0;//置结束标志
	return 0;
}
int cal_check_exp(u8 *type,double *val)
{
	int i=0;
	int flag=0,flag1=0;
	if (type[0]==3 && val[0]<7.0) return 4;//非法运算符开始
	while (type[i])//扫描表达式
	{
		if (type[i]==3 && val[i]==7.0) flag++;
		else if(type[i]==3 && val[i]==8.0) flag--;
		if (flag<0) return 5;//括符不匹配
		if (type[i]==3 && val[i]==7.0 && type[i+1]==3 && val[i+1]==8.0) return 4;//空的括号
		if (type[i]==flag1 && val[i]!=7.0 && val[i]!=8.0 && val[i]!=9.0) return 4;//运算符非法相连
		flag1=type[i];
		if (flag1==3 && val[i]==8.0) flag1=9;
		if (type[i]==3 && val[i]==8.0 && type[i-1]==3 && val[i-1]!=8.0) return 4;
		if (type[i]==2 && (type[i+1]!=3 || (type[i+1]==3 && val[i+1]!=7))) return 4;//函数检测
		if (type[i]==3 && val[i]==9.0 && type[i+1]!=1) return 4;//变量检测
		i++;
	}
	if (type[i-1]==3 && val[i-1]!=8.0) return 4;//非法的运算符结尾
	if (flag) return 5;//括符不匹配
	return 0;
}
void cal_exp_adj(u8 *type,double *val)//自动补充省略的*号
{
	int i=0;
	int p=0;
	u8 ttp[exp_max_len+1];
	double vll[exp_max_len+1];
	while (type[i])
	{
		if (type[i]==3 && (val[i]==7.0 || val[i]==9.0) && i)//( R
		{
			if (ttp[p-1]==1 || (ttp[p-1]==3 && vll[p-1]==8.0) )
			{
				ttp[p]=3;
				vll[p]=3;
				p++;
			}
		}
		ttp[p]=type[i];
		vll[p]=val[i];
		p++;
		if(type[i]==3 && val[i]==8.0)//)
		{
			if (type[i+1]==1 || type[i+1]==2)
			{
				ttp[p]=3;
				vll[p]=3;
				p++;
			}
		}
		i++;

	}
	for (i=0;i<p;i++)
	{
		type[i]=ttp[i];
		val[i]=vll[i];
	}
	type[i]=0;
}
int OptPre(int opt)
{
	if (opt<3) return 1;
	if (opt<6) return 2;
	if (opt==6) return 3;
	return 0;
}
double FunDo(int id,double val)
{
	switch(id)
	{
	case 1://sin
		return sin(val);
	case 2://cos
		return cos(val);
	case 3://tan
		return tan(val);
	case 4://log
      if (val<=0.0) {rb_error=1;return 0.0;}
		return log10(val);
	case 5://ln
      if (val<=0.0) {rb_error=1;return 0.0;}
		return log(val);
	case 6://pow
		return pow(10.0,val);
	case 7://exp
		return pow(2.718281828,val);
	case 8://sqr
      if (val<=0.0) {rb_error=1;return 0.0;}
		return sqrt(val);
	case 9://abs
		return val<0.0?0.0-val:val;
	case 10://DEG
		return val*57.29577951;
	case 11://int
		return (int)val;
	case 12://arcsin
	   if (val<-1.0 || val>1.0) {rb_error=2;return 0.0;}
		return asin(val);
	case 13://arccos
		if (val<-1.0 || val>1.0) {rb_error=2;return 0.0;}
		return acos(val);
	case 14://arctan
		return atan(val);
	case 15://sinh
		return sinh(val);
	case 16://cosh
		return cosh(val);
	case 17://tanh
		return tanh(val);
	case 18://RAD
		return val/57.29577951;
	default:
		return 0.0;
	}
}

double calcu(u8 *type,double *val,double *R)//计算主程序
{
	int i=0,flag;
	int start;
	int sp=0;
	int nw=6;
	int pre[7]={0,0,0,0,0};
	int opt[7];
	double stack[7];
	while (type[i] && i<exp_max_len)
	{
		if (type[i]==1)//数字入栈
		{
			stack[sp]=val[i];
			sp++;
		}
		else if (type[i]==2)//函数调用
		{
			flag=1;
			i=i+2;
			start=i;
			while (flag)//括符匹配
			{
				if (type[i]==3 && val[i]==8.0) flag--;
				else if (type[i]==3 && val[i]==7.0) flag++;
				i++;
			}
			i--;
			type[i]=0;
			stack[sp]=FunDo((int)val[start-2],calcu(type+start,val+start,R));//结果入栈
			sp++;
		}
		else if (type[i]==3 && val[i]==7)//括号先行运算
		{
			flag=1;
			i++;
			start=i;
			while (flag)//括符匹配
			{
				if (type[i]==3 && val[i]==8.0) flag--;
				else if (type[i]==3 && val[i]==7.0) flag++;

⌨️ 快捷键说明

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