📄 calculate.c
字号:
#include "include.h"
#define MAX_DIGIT 8
#define MAX_VALUE 99999999L
#define ADD_KEY TOTAL
#define DIV_KEY PRICE
#ifdef C6_VER
#define SUB_KEY CHECK
#define MUL_KEY CREDIT
#define DIV_KEY PRICE
#define CAL_KEY00 0xff
#else
#define SUB_KEY DISCOUNT
#define MUL_KEY ADDITION
#define DIV_KEY PRICE
#define CAL_KEY00 KEY00
#endif
/*=======================================================================;
计算器程序函数
主函数:void calculate();
功能:实现四则运算.
说明:按取消键退出,按清除键清除输入操作数,输入操作数和运算结果都不能超
过999999,否则报错。
设计编码:
日期:2003.3.28
========================================================================*/
void calculate() //main for calculate
{
uchar xdata ch=0,status=0,len,op_flag,op_right,clear2line=0;
uchar xdata str1[25],str2[12];
uchar xdata prompt_str[25];
uchar xdata CancelStr[]="按[取消]键返回";
uchar xdata ErrStr0[]="表达式错误",ErrStr1[]="除数为零";
uchar xdata ErrStr2[]="运算结果太大",ErrStr3[]="表达式为空";
uchar* xdata OpErrStr[4]={ErrStr0,ErrStr1,ErrStr2,ErrStr3};
Init_LCD_calculate(); //初始化lcd
str1[0]='\0';
str2[0]='\0';
do
{
if(low_pwr) break;// 如果断电了,则exit;
ch=CalWaitKey();
if(ch==0x1b)ch='+';//合计键
if(ch==VOID) //按取消键立即返回
break;
else if(ch==CLEAR) //清除键清掉输入的字符串str2,且状态转为0
{
if(clear2line)
{
clear_lcd(1,1);
clear2line=0;
lcd_disp_flush_right(1,CancelStr);
}
str2[0]='\0';
lcd_disp_flush_right(3,str2);
status=0;
}
else if(ch==ENTER||ch==SUBTOTAL) //确认键输出结果,状态转为0
{
if(clear2line)
{
clear_lcd(1,1);
clear2line=0;
lcd_disp_flush_right(1,CancelStr);
}
strcat(str1,str2);
len=strlen(str1);
if(str1[len-1]=='+'||str1[len-1]=='-'||str1[len-1]=='*'||str1[len-1]=='/')
str1[len-1]='\0';
op_right=OperateByStr(str1); //入口str1运算表达式,出口str1为运算后的结果.
if(op_right==0&&ch==ENTER)
{
prompt_str[0]='\0';
strcat(prompt_str,"结果:");
strcat(prompt_str,str1);
lcd_disp_flush_right(2,prompt_str);
//ning 03-04-20 len=strlen(prompt_str);
///ning 03-04-20 con_disp(2,24-len,4); //"结果"要反显
}
else if(op_right==0&&ch==SUBTOTAL)
{
prompt_str[0]='\0';
strcat(prompt_str,str1);
lcd_disp_flush_right(2,prompt_str);
}
else
{
clear_lcd(1,1);
lcd_disp(1,0,(uchar*)OpErrStr[op_right-1]);
con_disp(1,0,strlen((uchar*)OpErrStr[op_right-1]),
(uchar*)OpErrStr[op_right-1]);
clear_lcd(2,2);
clear2line=1;
}
if(ch==SUBTOTAL&&op_right==0)
status=5;
else
{
str1[0]='\0'; //使str1,str2为空
status=0;
}
str2[0]='\0';
lcd_disp_flush_right(3,str2);
}
else
{
if(!strlen(str1)&&!strlen(str2)&&ch=='-')
{
str2[0]=ch;
str2[1]='\0';
op_flag=2;
}
else
op_flag=AddCh(&status,str2,ch);
if(op_flag==1) //如op_flag为1,ch为运算符
{
strcat(str1,str2);
op_right=OperateByStr1(str1);
if(op_right)
{
clear_lcd(1,1);
lcd_disp(1,0,(uchar*)OpErrStr[op_right-1]);
con_disp(1,0,strlen((uchar*)OpErrStr[op_right-1]),
(uchar*)OpErrStr[op_right-1]);
clear_lcd(2,2);
str1[0]='\0';
str2[0]='\0';
clear2line=1;
continue;
}
str2[0]='\0';
lcd_disp_flush_right(2,str1);
}
if(op_flag) //表示是可接受了字符,就刷新LCD
{
if(clear2line)
{
clear_lcd(1,1);
clear2line=0;
lcd_disp_flush_right(1,CancelStr);
}
lcd_disp_flush_right(3,str2);
}
}
}while(ch!=VOID);
return;
}
//===========================================================================
void Init_LCD_calculate(void)
{
uchar xdata CalcStr[]="计算器",CancelStr[]="按[取消]键返回";
clear_lcd(0,4);
lcd_disp(0,0,CalcStr);
lcd_disp_flush_right(1,CancelStr);
}
/*===================================
功能:正常显示为向右对齐显示,如str的长度超过24,则不显示,并返回1。
str为要显示的字符串。
====================================*/
uchar lcd_disp_flush_right(uchar line,uchar *str)
{
uchar xdata i,col,ret,dstr[25];
memset(dstr,0,25);
for (i=0;i<25;i++)
if(str[i]=='\0')
break;
if(i>=25)
{
ret=1;
str[24]='\0';
i=24;
}
if((24-i)%2)
dstr[0]=' ';
strcat(dstr,str);
col=(24-i)/2;
clear_lcd(line,1);
lcd_disp(line,col,dstr);
return 0;
}
/*=========================================
功能:实现入口参数str表示的表达式的运算,应保证表达式正确,如表达式有错,
则不运算,出口str为运算后的值。入口出口都是用ASCII码表示。返回值0表示正确,
其它为错误类型:1.表达式错,2.除数为零。3.操作数或中间结果或结果大于
999999.99,4.表达式为空
========================================================*/
uchar OperateByStr(uchar *str)
{
uchar xdata i=0,press_point=0;
uchar xdata ch,len,opp1,opp2;
uchar xdata opd_pos=1,point_flag=0,negative_flag=0,err; //opd_pos表示操作数位置
long xdata result,opd1=0,opd2=0,opd3=0,whole=0,part=0;
len=strlen(str);
if (len==0)
return 4; //表达式为空
for(i=0;i<len;i++)
{
ch=str[i];
if(i==0&&(ch=='+'||ch=='-')) //第一个数前有符号
{
if(ch=='-')
negative_flag=1;
else
negative_flag=0;
}
else if(ch>='0'&&ch<='9')
{
if(!press_point)
whole=whole*10+(ch-'0')*100;
else
{
if(press_point==1)
part=(ch-'0')*10;
else
part=part+(ch-'0');
press_point++;
}
ch=str[i+1];
if((ch<'0'||ch>'9')&&(ch!='.'))
{
if(opd_pos==1)
opd1=whole+part;
else if(opd_pos==2)
opd2=whole+part;
else if(opd_pos==3)
opd3=whole+part;
}
}
else if(ch=='+'||ch=='-'||ch=='*'||ch=='/')
{
press_point=0;
whole=0;
part=0;
if(opd_pos==1)
opp1=ch;
else if(opd_pos==2)
opp2=ch;
ch=str[i+1];
if((ch>='0'&&ch<='9')||(ch=='.'))
opd_pos++; //操作数位置加1
else
return 1; //运算符必跟操作数
}
else if(ch=='.')
press_point=1;
else
return 1; //含有非法字符
} //end for
if(negative_flag)
opd1=-opd1;
if((opp1=='/'&&opd2==0)||(opp2=='/'&&opd3==0)) //检查除数为零
return 3;
if(opd_pos==1)
result=opd1;
else if(opd_pos==2)
{
err=OperateByLong(opp1,opd1,opd2,&result);
if(err)
return err;
}
else if(opd_pos==3)
{
err=OperateByLong(opp2,opd2,opd3,&result);
if(err)
return err;
err=OperateByLong(opp1,opd1,result,&result);
if(err)
return err;
}
LongToString(result,str);
len=strlen(str);
if(result==0)
{
str[0]='0';
str[1]='\0';
}
else if(result>-10&&result<10&&result!=0) //一位数
{
for(i=len+1;i>0;i--)
{
ch=str[i-1];
if(ch=='-')
break;
else
str[i+2]=str[i-1];
}
str[i]='0';
str[i+1]='.';
str[i+2]='0';
}
else if((result>-100&&result<=-10)||(result>=10&&result<100))//两们数
{
for(i=len+1;i>0;i--)
{
ch=str[i-1];
if(ch=='-')
break;
else
str[i+1]=str[i-1];
}
str[i]='0';
str[i+1]='.';
}
else //三位数以上
{
for(i=len;i>len-3;i--)
str[i+1]=str[i];
str[i+1]='.';
if(str[i+2]=='0'&&str[i+3]=='0')
str[i+1]='\0';
}
return 0;
}
/*=================================================================
功能:对长整形数加减乘除,
返回0表示计算正确,
返回2表示除数为0
返回3表示数溢出,即结果大于MAX_VALUE或小于-MAX_VALUE
=================================================================*/
uchar OperateByLong(uchar opp,long opd1,long opd2,long *result) //两个长整形实现四则运算
{
uchar xdata err=0;
// long xdata mod;
switch(opp)
{
case '+': *result=opd1+opd2;
if (*result>MAX_VALUE||*result<-MAX_VALUE)
err=3;
break;
case '-': *result=opd1-opd2;
if (*result>MAX_VALUE||*result<-MAX_VALUE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -