📄 calc.c
字号:
/**************************************************************************/
/*==========================================================================
*
* 版权所有 (C) 2000-2001 吴柏建. All Rights Reserved.
*
* 文件: Calc.c
* 内容: PSDE_DEMO_PDA之计算操作函数源文件。
* 作者: 吴柏建
* 制作日期: 2001.10.9
* 修改日期: 2001..
*
***************************************************************************/
/*CALC_IN_STRING_WAY宏有定义时表示使用字符串方式进行数值计算。*/
//#define CALC_IN_STRING_WAY
#ifndef CALC_IN_STRING_WAY
#include "stdio.h"
#include "math.h"
#endif
#include "pda.h"
#define UNDO 2
#define CE 3
#define CC 4
#define MC 5
#define MR 6
#define MS 7
#define MA 8
#define DIV 9 /*/*/
#define MUT 10/***/
#define SUB 11/*-*/
#define ADD 12/*+*/
#define ROOT 13
#define PERCENT 14
#define RECIPROCAL 15/*倒数*/
#define P_N 16/*+/-*/
#define MAXNUM 12/*计算器能接受的数字位数*/
typedef struct _CALCDATA
{
unsigned char InOne[32];/*第一个操作数*/
unsigned char Opt;/*操作符*/
unsigned char InTwo[32];/*第二个操作数*/
unsigned char OldIn[32];/*对操作符连操作的原始操作数*/
unsigned char OldOpt;/*连操作的原始操作符*/
unsigned char M[32];/*保存的数字字符串*/
/*status:
0:第一操作数插入改写,此时无操作符和第二个操作数。
1:有第一个操作数和操作符但无第二个操作数。(此时'='表示对操作符连操作)
2:第二个操作数插入改写,此时有第一个操作数、操作符。
3:第二个操作数将被清零重输,由1,2状态通过单目操作符进入,重输后进入2,4,5状态。
4:有第一个操作数表示结果将被清零重输,此时无操作符和第二个操作数。
5:状态同4,但是由等于操作进入,显示函数中按显示精度舍入结果进入状态4。
8:ERROR。
*/
unsigned char status;
}CALCDATA;
CALCDATA calc;
#ifdef CALC_IN_STRING_WAY
/*以下是不支持double型数据计算的代码*/
/*
不使用double型数据计算实现以下函数。内容:略。
void StrDIV(unsigned char *d,unsigned char *a,unsigned char *b);
void StrMUT(unsigned char *d,unsigned char *a,unsigned char *b);
void StrSUB(unsigned char *d,unsigned char *a,unsigned char *b);
void StrADD(unsigned char *d,unsigned char *a,unsigned char *b);
void StrROOT(unsigned char *d,unsigned char *a);
*/
/*不支持double型数据计算的代码结束*/
#else
/*以下是支持double型数据计算的代码*/
short StrCopy(unsigned char *d,unsigned char *s)
{
short i=0;
while(*s){i++;*d++=*s++;}
*d=*s;
return i;
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---数字转换为字符串-------------------------------------------------□
□ □
□---2001.3.1---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
void DoubleToStr(unsigned char *d,double i)
{
unsigned char buf[32],*s,*e;
sprintf(buf,"%12.13f",i);
s=buf;
while(*s==' ')s++;
e=s;
while(*e)e++;
while(*--e=='0')*e=0;
if(*s=='-')StrCopy(d,s);
else
{
*d++='+';
StrCopy(d,s);
}
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---字符串转换为数字-------------------------------------------------□
□ □
□---2001.3.1---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
double StrToDouble(unsigned char *s)
{
unsigned char c;
unsigned char sign = 0;
double value = 0.0;
double fract = 0.1;
c=*s++;
if( c=='-'||c=='+')
{
if(c=='-')sign=1;
c = *s++;
}
while((c>='0')&&(c<='9'))
{
value = value * 10.0 + (c - '0');
c = *s++;
}
if(c=='.')
{
c=*s++;
while((c>='0')&&(c<='9'))
{
value = fract * (c - '0') + value;
fract /= 10.0;
c=*s++;
}
}
if( sign )value = -value;
return value;
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---计算器除法计算---------------------------------------------------□
□ □
□---2001.3.2---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
void StrDIV(unsigned char *d,unsigned char *a,unsigned char *b)
{
double dd,aa,bb;
aa=StrToDouble(a);
bb=StrToDouble(b);
if(bb==0.0)d[1]='e';
else
{
dd=aa/bb;
DoubleToStr(d,dd);
}
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---计算器乘法计算---------------------------------------------------□
□ □
□---2001.3.2---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
void StrMUT(unsigned char *d,unsigned char *a,unsigned char *b)
{
double dd,aa,bb;
aa=StrToDouble(a);
bb=StrToDouble(b);
dd=aa*bb;
DoubleToStr(d,dd);
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---计算器减法计算---------------------------------------------------□
□ □
□---2001.3.2---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
void StrSUB(unsigned char *d,unsigned char *a,unsigned char *b)
{
double dd,aa,bb;
aa=StrToDouble(a);
bb=StrToDouble(b);
dd=aa-bb;
DoubleToStr(d,dd);
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---计算器加法计算---------------------------------------------------□
□ □
□---2001.3.2---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
void StrADD(unsigned char *d,unsigned char *a,unsigned char *b)
{
double dd,aa,bb;
aa=StrToDouble(a);
bb=StrToDouble(b);
dd=aa+bb;
DoubleToStr(d,dd);
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---计算器根号计算---------------------------------------------------□
□ □
□---2001.3.2---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
void StrROOT(unsigned char *d,unsigned char *a)
{
double dd,aa;
aa=StrToDouble(a);
dd=sqrt(aa);/*平方根*/
DoubleToStr(d,dd);
}
#endif/*支持double型数据计算的代码结束*/
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---计算器数据结构初始化---------------------------------------------□
□ □
□---2001.3.1---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
void InitCalc(void)
{
calc.status=0;
*calc.InOne='+';
calc.InOne[1]=0;
calc.Opt=0;
*calc.InTwo='+';
calc.InTwo[1]=0;
calc.OldOpt=0;
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---字符串处理进位---------------------------------------------------□
□ s指向字符串需要进位的地方。 □
□ 返回TRUE表示进位导致字符串起点向前进一位,FALSE起点不变。 □
□---2001.3.3---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
char EnterNum(unsigned char *s)
{
unsigned char *d=s;
*d--=0;
while(1)
{
if(*d=='.'){d--;continue;}
if(*d=='+'||*d=='-')
{
d--;*d=d[1];d[1]='1';*--s=0;return 1;
}
if(*d>='0'&&*d<='9')
{
*d+=1;
if(*d<='9')return 0;
else *d-=10;
d--;
}
else return 0;
}
}
/*≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡
□---计算器输出显示---------------------------------------------------□
□ □
□---2001.3.3---------------------------------------------------------□
≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡≡*/
const unsigned char CalcStrError[]="error";
void CalcShow(void)
{
short i,max;
unsigned char *s,*ss,*d,buf[34];
/*获取要显示的字符串指针*/
s = (calc.Opt) ? calc.InTwo : calc.InOne;
if(calc.status==4||calc.status==5||calc.status==1) s = calc.InOne;
ss=s;
/*检查整数部分是否超过MAXNUM并记录整数位数到i中*/
for(d=s+1,i=0; *d; d++)
{
if(*d == '.')break;
i++;
}
if(i>MAXNUM) calc.status = 8;
max=i;
/*检查字符串中是否有非法字符,通常由运算溢出或出错引入非法字符*/
for(d=s+1; *d; d++)
{
if(*d!='.' && (*d<'0'||*d>'9') )
{
calc.status = 8;
break;
}
}
AAA:
/*处理好用来显示的字符串,放入指针d所指向的字符串中*/
if(calc.status==8)d = (unsigned char *)CalcStrError;
else
{
d=&buf[2];
/*如字符串s为"-0"使之变为"+0"*/
if(!s[1]||(s[1]=='0'&&s[2]==0))*s='+';
/*Copy字符串s到字符串d,并消除d中的字符'+'*/
if(*s=='+')StrCopy(&buf[1],s);
else StrCopy(d,s);
/*使s指针指向小数点,没有小数点时指向结束符*/
for(s=d; *s&&*s!='.'; s++);
if(*s)/*有小数点时*/
{
/*如显示数字超出长度,切断小数点后的多出部分*/
while(*++s)
{
if(++i>=MAXNUM)
{
if(i>MAXNUM)s--;
/*4舍5入*/
if(*++s>='5')
{
if(EnterNum(s))
{
d--;
s--;
if(max+1>MAXNUM){ calc.status = 8;goto AAA;}
}
}
else *s=0;
break;
}
}
/*显示的为计算结果时消除小数的尾'0'*/
if(calc.status>=3||calc.status==1)
{
while(*--s=='0')*s=0;
}
}
else/*无小数点时补上小数点*/
{
*s++='.';
*s=0;
}
/*仅有小数点时小数点前加字符'0'*/
if(*d=='.')
{
d[0]='0';
d[1]='.';
d[2]=0;
}
}
/*计算结果舍入后重新作为操作数*/
if(calc.status==5)
{
calc.status=4;
if(*d=='-')StrCopy(calc.InOne,d);
else StrCopy(calc.InOne,&buf[1]);
}
else if(calc.status!=0&&calc.status!=2)
{
if(*d=='0'&&d[1]=='.'&&d[2]==0)
{
*ss++='+';*ss=0;
}
}
if(*d=='-'&&d[1]=='0'&&d[2]=='.'&&d[3]==0)d++;
/*在适当的位置显示字符串*/
i=GetStrLength(d)*8;
DispBar(9,10,143,19,COLOR_WHITE);
i=148-i;
DispStr(i,13,d,COLOR15,COLOR0);
/*显示或清除M*/
i=(StrToDouble(calc.M)==0.0)?' ':'M';
DispChar(13,10,i,COLOR15,COLOR0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -