⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cal.c

📁 可以在嵌入式应用中
💻 C
字号:
//数学计算//
#include <CsAgb.h>
#include <variable.h>
#include <rb_stdio.h>
#include <rb_math.h>
#include <tree.h>
#include <math.h>
#include <rbasic.h>
#include <rb_string.h>
#include <strpro.h>
#define mathend 26
#define strpsta 27
const u8 rb_pri[7]={0,1,1,2,2,2,3};//运算优先级
double rb_cal(char *exp);
extern double math_fun(u8 id,char *par);
double strn_fun(u8 id,char *exp);
u8 is_opt(char ch)//是否为运算符
{
   char opts[]="+-*/%^";
   u8 i;
   for (i=0;i<6;i++) if (ch==opts[i]) return i+1;//返回运算符代码
   return 0;
}

u8 is_sbl(char ch)//是否为变量标识符
{
   return (ch=='#' || ch=='$');
}

void exp_adj(char *exp)//表达式调整(去除首尾无用空白)
{
   u8 i=0;
   u8 start=0;
   while (exp[start]==' ') start++;
   if (start)
   {
      while (exp[start]!='\0')
      {
         exp[i]=exp[start];
         i++;
         start++;
      }
      exp[i]='\0';
   }
   i=str_len(exp)-1;
   while (exp[i]==' ') i--;
   exp[i+1]='\0';
}

/*u8 exp_check(char *exp)//表达式词法检测(括号的匹配与字符的检查,有误返回1)
{
   u8 i=0;
   u8 is_error=0;
   int count=0;
   int count1=0;
   while (exp[i]!='\0')
   {
      if (exp[i]=='(') count++;
      else if(exp[i]==')') count--;
      else if(exp[i]=='[') count1++;
      else if(exp[i]==']') count1--;
      else
      {
         is_error=is_letter(exp[i])||is_number(exp[i])||is_opt(exp[i])||
         is_sbl(exp[i])||exp[i]==' '||exp[i]==','||exp[i]=='\"'||exp[i]=='_'
         ||exp[i]=='.';
         is_error=!is_error;
      }
      if (is_error) return 1;
      if (count<0) return 1;//括号不配对
      i++;
   }
   if (count || count1) return 1;
   return 0;
}
*/

u8 get_word_type(char *exp)//获得单词类型(初步分类并不验证)
{
   u8 len;
   u8 type=0;
   exp_adj(exp);
   len=str_len(exp);
   if (len==0) return 0;//错误!
   type=is_opt(exp[0]);
   if (len==1 && type) return type;//是运算符号,返回运算符代号
   if (exp[0]=='(' && exp[len-1]==')') return 10;//是表达式
   if (exp[len-1]==')') return 20;//是函数
   if (is_number(exp[0]) || exp[0]=='-') return 30;//是数字
   if (exp[len-1]==']') return 40;//是数组
   return 50;//是变量名
}

u8 word_is_num(char *exp)//检查数字格式是否正确
{
   u8 i=0;
   u8 dot=0;
   u8 index=0;
   while (exp[i]!='\0')
   {
      if (exp[i]=='-')
      {
         if (!(i==0 || exp[i-1]=='e' || exp[i-1]=='E')) return 0;//非法符号
      }
      else if (exp[i]=='.') dot++;
      else if (exp[i]=='e' || exp[i]=='E') {dot=(dot?dot:1);index++;}
      else if (!is_number(exp[i])) return 0;
      if (dot>1 || index>1) return 0;
      i++;
   }
   if(!is_number(exp[i-1])) return 0;
   return 1;//OK
}

double get_val(char *exp)//取得数值
{
   u8 type=get_word_type(exp);
   u8 len;
   u8 vt=0;
   u8 funid=0;
   char fun[10];
   switch(type)
   {
      case 50://是变量名
      exp_adj(exp);
      len=str_len(exp);
      if (len==0 || exp[len-1]=='$' ||(len==1 && is_sbl(exp[0])))//空的变量名
      {
         rb_error=6;
         return 0.0;
      }
      if (exp[len-1]=='#')//为整形变量
      {
         vt=1;
         exp[len-1]='\0';
      }
      /*if (check_var_name(exp))//非法的变量名
      {
         rb_error=22;
         return 0.0;
      }*/
      if (vt) return rb_get_int(exp);
      return rb_get_float(exp);//取变量值
      break;
      case 30://是数字
      if (word_is_num(exp)) return str_to_num(exp);
      else
      {
         rb_error=6;
         return 0.0;
      }
      break;
      case 10://是表达式
      len=str_len(exp);
      exp[len-1]='\0';
      exp[0]=' ';
      return rb_cal(exp);
      break;
      case 20://函数调用
      len=0;
      while(exp[len]!='(' && exp[len]!='\0')//获得函数名
      {
         fun[len]=exp[len];
         exp[len]=' ';
         len++;
      }
      if (exp[len]!='(')//语法错误
      {
         rb_error=6;
         return 0.0;
      }
      fun[len]='\0';
      exp_adj(fun);
      str_up(fun);
      funid=is_keyword(rb_math_key,fun);
      if (funid==0) {rb_error=6;return;}//找不到对应的数学函数
      exp_adj(exp);
      len=str_len(exp);
      exp[0]=' ';
      exp[len-1]=' ';
      if (funid<=mathend) return math_fun(funid,exp);
      return strn_fun(funid-strpsta+1,exp);
      break;
      case 40://数组的处理
      len=0;
      while(exp[len]!='[' && exp[len]!='\0')
      {
         fun[len]=exp[len];
         exp[len]=' ';
         len++;
      }
      if (exp[len]!='[' || len==0)//不配对
      {
         rb_error=6;
         return 0.0;
      }
      vt=0;
      if(fun[len-1]=='#')
      {
         vt=1;
         fun[len-1]='\0';
      }
      else fun[len]='\0';
      /*if(check_var_name(fun))//非法变量名
      {
         rb_error=22;
         return 0.0;
      }*/
      exp[len]=' ';
      len=str_len(exp);
      exp[len-1]='\0';
      exp_adj(exp);
      len=(u8)rb_cal(exp);
      if (vt) return rb_get_int_dim(fun,len);
      return rb_get_float_dim(fun,len);
      default://其它情况均视为语法错误
      rb_error=6;
      return 0.0;
   }
}
double rb_cal(char *exp)//计算表达式的值
{

   char temp[com_max_len];//单词暂存
   u8 len=0;//单词长度
   double value[12];//数据寄存器
   u8 type[12];//数据类型(0-Num,1-Opt)
   u8 tcp=0;//指针
   u8 i=0;
   u8 opt=0;
   u8 flag;
   u8 istr;
   exp_adj(exp);
   if (exp[0]=='-')
   {
      i++;
      temp[0]='-';
      len++;
   }
   while(exp[i]!='\0')
   {
      opt=is_opt(exp[i]);
      if (exp[i]=='(')//括号配对
      {
         flag=1;
         temp[len]=exp[i];
         len++;
         i++;
         istr=0;
         while(flag && exp[i]!='\0')
         {
            if (exp[i]=='(' && istr==0) flag++;
            else if(exp[i]==')' && istr==0) flag--;
            temp[len]=exp[i];
            if (exp[i]=='\"') istr=!istr;
            len++;
            i++;
         }
         if (flag)//不配对
         {
            rb_error=6;
            return 0.0;
         }
      }
      else if(exp[i]=='[')//[]配对
      {
         flag=1;
         istr=0;
         temp[len]=exp[i];
         len++;
         i++;
         while(flag)
         {
            if (exp[i]=='[' && istr==0) flag++;
            else if(exp[i]==']' && istr==0) flag--;
            temp[len]=exp[i];
            if (exp[i]=='\"') istr=!istr;
            len++;
            i++;
         }
         if (flag)
         {
            rb_error=6;
            return 0.0;
         }
      }
      else if (opt)//是运算符
      {
         if (i==0 || is_opt(exp[i-1]))//语法错误
         {
            rb_error=6;
            rb_say_error("SYNTAX ERROR!");
            return 0;
         }
         temp[len]='\0';
         len=0;
         value[tcp]=get_val(temp);
         type[tcp]=0;
         tcp++;
         if (tcp>2)//检查是否可先行运算
         {
            if (rb_pri[opt]<=rb_pri[type[tcp-2]])//先行运算
            {
               switch(type[tcp-2])//+-*/%^
               {
                  case 1://+
                  value[tcp-3]=value[tcp-3]+value[tcp-1];
                  break;
                  case 2://-
                  value[tcp-3]=value[tcp-3]-value[tcp-1];
                  break;
                  case 3://*
                  value[tcp-3]=value[tcp-3]*value[tcp-1];
                  break;
                  case 4:///
                  if (value[tcp-1]==0.0)//除零
                  {
                     rb_error=23;
                     return 0.0;
                  }
                  value[tcp-3]=value[tcp-3]/value[tcp-1];
                  break;
                  case 5://%
                  value[tcp-3]=(int)value[tcp-3]%(int)value[tcp-1];
                  break;
                  case 6://^
                  value[tcp-3]=pow(value[tcp-3],value[tcp-1]);
                  break;
               }
               tcp=tcp-2;
            }
         }
         type[tcp]=opt;
         tcp++;
         i++;
      }
      else
      {
         temp[len]=exp[i];
         len++;
         i++;
      }
   }
   if (is_opt(exp[i-1]))//非法的运算符结束
   {
      rb_error=6;
      rb_say_error("SYNTAX ERROR.");
      return 0.0;
   }
   temp[len]='\0';
   value[tcp]=get_val(temp);
   if (tcp==0) return value[0];
   tcp--;
   i=1;
   while(i)
   {
      switch(type[tcp])
      {
         case 1://+
         value[tcp-1]=value[tcp-1]+value[tcp+1];
         break;
         case 2://-
         value[tcp-1]=value[tcp-1]-value[tcp+1];
         break;
         case 3://*
         value[tcp-1]=value[tcp-1]*value[tcp+1];
         break;
         case 4:///
         if (value[tcp+1]==0.0)//除零
         {
            rb_error=23;
            return 0.0;
         }
         value[tcp-1]=value[tcp-1]/value[tcp+1];
         break;
         case 5://%
         value[tcp-1]=(int)value[tcp-1]%(int)value[tcp+1];
         break;
         case 6://^
         value[tcp-1]=pow(value[tcp-1],value[tcp+1]);
         break;
      }
      if (tcp==1) i=0;
      else tcp=tcp-2;
   }
   return value[0];//返回运算结果
}

⌨️ 快捷键说明

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