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 + -
显示快捷键?