VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1368|回复: 1

[转载] 支持含有中文变量名的表达式计算

[复制链接]
16_avatar_middle
在线会员 发表于 2010-10-18 09:09:47 | 显示全部楼层 |阅读模式
源码信息
源代码类型: -
源代码作者: -
编译器版本: -
代码注释: -
数据库种类: -
预览图片: -
源代码简介: -
1、Calc.h

  1. /*
  2. *        calculate expressions, support chinese characters
  3. *        hujinshan extracted and modified it from Roger's Calculator
  4. */
  5. #ifndef _CALC_H
  6. #define _CALC_H

  7. #pragma warning (disable : 4786)
  8. #include <string>
  9. #include <map>
  10. #include <complex>
  11. #include <strstream>
  12. #include <cmath>
  13. #include <ctime>
  14. #include <windows.h>
  15. using namespace std;

  16. #define PI 3.1415926535897932384626433832795

  17. class CCalc
  18. {
  19. public:
  20.         class CCompl : public complex<double>
  21.         {
  22.         public:
  23.                 CCompl(const double &d1 = 0, const double &d2 = 0) : complex<double>(d1,d2) {}
  24.                 CCompl(const complex<double> &in) : complex<double>(in) {}
  25.                 operator double()
  26.                 {
  27.                         if(imag() == 0 ) return real();
  28.                         throw "Error: Complex value";
  29.                 }       
  30.         };

  31. private:
  32.    char errText[2000];

  33.    int Funk(char *p, bool binary, CCompl &x, CCompl &y);
  34.    double Factorial(double x);
  35.    CCompl GetNumber(char *p, int &move);
  36.    bool TestDelimiter(char c)
  37.    {
  38.       return (c=='+' || c=='-' || c=='*' || c=='/' ||
  39.               c=='%' || c==',' || c==')' || c==0 );
  40.    }

  41. public:
  42.    bool gra,newVar,isVar;
  43.    map<string,CCompl> variabler;
  44.    map<string,CCompl>::iterator it;

  45.    CCompl Calc(char *psz);
  46.    CCompl Calc(char *p, int len);
  47. };

  48. #endif
复制代码
2、Calc.cpp


  1. /*
  2. *        calculate expressions, support chinese characters
  3. *        hujinshan extracted and modified it from Roger's Calculator
  4. */

  5. #include "Calc.h"

  6. CCalc::CCompl CCalc::Calc(char *p, int len)
  7. {
  8.    int pos=0, move;
  9.    bool neg = false;
  10.    while(p[pos] == '+' || p[pos] == '-')
  11.    {
  12.       if(p[pos] == '-') neg =!neg;
  13.       if(IsDBCSLeadByte(p[pos]))
  14.                   pos+=2;
  15.           else
  16.                   pos++;
  17.    }
  18.    CCompl d1 = GetNumber(p + pos, move);
  19.    if(neg) d1 = -d1;
  20.    pos += move;

  21.    while(pos < len)
  22.    {
  23.       char c = p[pos];
  24.       if(c == '+' || c == '-') return d1 + Calc( p + pos, len - pos );
  25.       if(c == '*' || c == '/' || c == '%')
  26.       {
  27.          pos++;
  28.          neg = false;
  29.          while(p[pos] == '+' || p[pos] == '-')
  30.          {
  31.             if(p[pos] == '-')
  32.                                 neg =!neg;
  33.                         if(IsDBCSLeadByte(p[pos]))
  34.                                 pos+=2;
  35.                         else
  36.                                 pos++;
  37.          }
  38.          CCompl d2 = GetNumber(p + pos, move);
  39.          if(neg) d2 = -d2;
  40.          pos += move;
  41.          if(c == '*') d1 *= d2;
  42.          else if(d2 == CCompl(0,0)) throw "Division by Zero";
  43.          else if(c == '/') d1 /= d2;
  44.          else d1 = fmod(d1,d2);
  45.       }
  46.       else
  47.       {
  48.          //sprintf(errText,"Expected operator before %s",p + pos);
  49.          sprintf(errText,"What ??? '%c'",p[pos]);
  50.          throw errText;
  51.       }
  52.    }
  53.    return d1;
  54. }

  55. int CCalc::Funk(char *p, bool binary, CCompl &x, CCompl &y)
  56. {
  57.    int size = 0, nr=1;
  58.    while( nr )
  59.    {
  60.       if(!p[size] ) throw "Error: Missing ')'";
  61.       if( p[size] == '(') nr++;
  62.       if( p[size] == ')') nr--;
  63.                   size++;
  64.    }
  65.    size--;

  66.    if(binary)
  67.    {
  68.       for(int i=0; i<size; i++)
  69.       {
  70.          if(p[i] == '(')
  71.          {
  72.             int nr = 1;
  73.             while(nr && i < size)
  74.             {
  75.                i++;
  76.                if(p[i] == '(') nr++;
  77.                if(p[i] == ')') nr--;
  78.             }
  79.          }
  80.          if(p[i] == ',') break;
  81.       }
  82.       if(i == size) throw "Error: Missing ','";
  83.       x = Calc(p, i);
  84.       y = Calc(p + i + 1, size - i - 1);
  85.    }
  86.    else x = Calc(p, size);

  87.    if(IsDBCSLeadByte(p[size]))
  88.            return size+2;
  89.    else
  90.            return size+1;

  91. }

  92. double CCalc::Factorial(double x)
  93. {
  94.    if(x < 0) throw "Factorial do not handle negative values";
  95.    double d = 1;
  96.    for(int i=1; i<=(int)x; i++) d *= i;
  97.    return d;
  98. }

  99. #define FX(FUNK,LEN,BIN,DO) if(!_memicmp(p,FUNK,LEN)) { move = LEN + Funk(p+LEN,BIN,x,y); { DO; } }

  100. CCalc::CCompl CCalc::GetNumber(char *p, int &move)
  101. {
  102.    CCompl x,y;
  103.    switch (tolower(*p))
  104.    {
  105.    case 'a':
  106.       FX("abs("  ,4,0, return abs(x););
  107.       FX("asin(" ,5,0, if(gra) return asin(x)*360/(2*PI); return asin(x););
  108.       FX("acos(" ,5,0, if(gra) return acos(x)*360/(2*PI); return acos(x););
  109.       FX("atan(" ,5,0, if(gra) return atan(x)*360/(2*PI); return atan(x););
  110.       break;
  111.    case 'c':
  112.       FX("cos("  ,4,0, if(gra) x = 2*PI/360*x; return cos(x););
  113.       FX("cosh(" ,5,0, if(gra) x = 2*PI/360*x; return cosh(x););
  114.       FX("cpx("  ,4,1, double t=variabler["x"]; if(t>=x && t<y) return 1; return 0; );
  115.       break;
  116.    case 'e':
  117.       FX("exp("  ,4,0, return exp(x););
  118.       break;
  119.    case 'i':
  120.       FX("im("   ,3,0, return x.imag(););
  121.       FX("int("  ,4,0, if(x<0) return ceil(x); return floor(x););
  122.       break;
  123.    case 'l':
  124.       FX("ln("   ,3,0, return log(x););
  125.       FX("log("  ,4,0, return log10(x););
  126.       break;
  127.    case 'm':
  128.       FX("max("  ,4,1, if(x<y) return x; return y;);
  129.       FX("min("  ,4,1, if(x>y) return x; return y;);
  130.       break;
  131.    case 'n':
  132.       FX("norm(" ,5,0, return norm(x););
  133.       break;
  134.    case 'p':
  135.       FX("pow("  ,4,1, return pow(x,y););
  136.       FX("pol("  ,4,1, if(gra) y = 2*PI/360*y; return polar((double)x,(double)y););
  137.       break;
  138.    case 'r':
  139.       FX("re("   ,3,0, return x.real(););
  140.       break;
  141.    case 's':
  142.       FX("sqr("  ,4,0, return sqrt(x););
  143.       FX("sin("  ,4,0, if(gra) x = 2*PI/360*x; return sin(x););
  144.       FX("sqrn(" ,5,1, return std::pow(x,1/y);); // Bug p?negativa x v鋜den.
  145.       FX("sinh(" ,5,0, if(gra) x = 2*PI/360*x; return sinh(x););
  146.       break;
  147.    case 't':
  148.       FX("tan("  ,4,0, if(gra) x = 2*PI/360*x; return tan(x););
  149.       FX("tanh(" ,5,0, if(gra) x = 2*PI/360*x; return tanh(x););
  150.       break;
  151.    case '!':
  152.       FX("!("    ,2,0, return Factorial(x););
  153.       break;
  154.    case '(':
  155.       FX("("     ,1,0, return x;)
  156.       break;
  157.    }

  158.    if(p[0] == '0' && (p[1] == 'x' || p[1] == 'X') )
  159.    {
  160.       int i=0; char c; move = 1;
  161.       sscanf(p,"%x",&i);
  162.       do
  163.           {
  164.                   move++; c = tolower(p[move]);
  165.           }while( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'));
  166.       return (double)i;
  167.    }

  168.    if(p[0] == '0' && (p[1] == 'b' || p[1] == 'B') )
  169.    {
  170.       int i=0; move = 2;
  171.       while(p[move] == '0' || p[move] == '1')
  172.           {
  173.                   i *= 2;
  174.                   if(p[move] == '1')
  175.                           i++; move++;
  176.           }
  177.       return (double)i;
  178.    }

  179.    if( (*p>='0' && *p<='9') || *p=='.' )
  180.    {
  181.       move=0;
  182.       double d = atof(p);
  183.       if   (p[move] == '+' || p[move] == '-') move++;
  184.       while(p[move] >= '0' && p[move] <= '9') move++;
  185.       if   (p[move] == '.') move++;
  186.       while(p[move] >= '0' && p[move] <= '9') move++;
  187.       if   (p[move] == 'e' || p[move] == 'E')
  188.       {
  189.          move++;
  190.          if   (p[move] == '+' || p[move] == '-') move++;
  191.          while(p[move] >= '0' && p[move] <= '9') move++;
  192.       }
  193.       if(p[move] == 'i')
  194.           {
  195.                   move++;
  196.                   return CCompl(0,d);
  197.           }
  198.       return d;
  199.    }
  200.    
  201.    bool found = false; move = 0;
  202.    for(it=variabler.begin(); it!=variabler.end(); it++)
  203.    {
  204.       if(memcmp( p, it->first.c_str(), it->first.size()) == 0)
  205.       {
  206.          found = true;
  207.          if(it->first.size() > (unsigned int)move) { move = it->first.size(); x = it->second; }
  208.       }
  209.    }
  210.    if(found) return x;
  211.    
  212.    if(_memicmp( p, "pi", 2) == 0 && TestDelimiter(p[2]) )
  213.    {
  214.            move = 2;
  215.            return PI;
  216.    }

  217.    if(p[0] == 'e' && TestDelimiter(p[1]) )
  218.    {
  219.            move = 1;
  220.            return 2.71828182845904523536;
  221.    }   

  222.    int i=0;
  223.    char tmp[100];
  224.    while( !TestDelimiter(p[i]) )
  225.    {
  226.            tmp[i] = p[i];
  227.            i++;
  228.    }

  229.    tmp[i]=0;
  230.    if(i) { sprintf(errText,"Syntax Error: '%s'",tmp); throw errText; }
  231.    throw "Syntax Error";
  232. }

  233. CCalc::CCompl CCalc::Calc(char *psz)
  234. {
  235.    int i=0,k=0;
  236.    char p[5000];
  237.    while(psz[k])
  238.    {
  239.            if(!isspace(psz[k]))
  240.            {
  241.                    p[i] = psz[k]; i++;
  242.            }
  243.            k++;
  244.    }

  245.    if(!i) return 0;
  246.    p[i] = 0;
  247.    for(k=0; k<i; k++)
  248.    {
  249.            if(p[k] == '=')
  250.                    break;
  251.    }

  252.    if(k>=i) k=-1;
  253.    
  254.    newVar = false; isVar = false;
  255.    
  256.    CCompl d;
  257.    if (IsDBCSLeadByte(p[k]))
  258.            d = Calc(p+k+2,i-k-2);
  259.    else
  260.            d = Calc(p+k+1,i-k-1);
  261.    
  262.    
  263.    if(k >= 0)
  264.    {
  265.       if( (!isalpha(p[0]) ) && (!IsDBCSLeadByte(p[0])) )
  266.                   throw "Variable must begin with alpha";
  267.           if(IsDBCSLeadByte(p[0]))
  268.                   i=2;
  269.           else
  270.                   i=1;

  271.       for(; i<k; i++)
  272.                   if( !isalnum(p[i]) && (!IsDBCSLeadByte(p[0])) )
  273.                           throw "A non alphanumeric value in variable";
  274.       string s;
  275.       s.append(p,k);
  276.       if(s=="e" || s=="PI" || s=="pi" )
  277.                   throw "Error: Reserved name";
  278.       CCompl &d2 = variabler[s];
  279.       if(d2 != d)
  280.           {
  281.                   d2 = d;
  282.                   newVar = true;
  283.           }
  284.       isVar = true;
  285.    }
  286.    return d;
  287. }
复制代码
3、使用方法
  1.   

  2. #include "calc.h"
  3. #include <iostream>
  4. #include <string>
  5. #include <Windows.h>

  6. void main()
  7. {
  8.         using namespace std;
  9.         try{
  10.        
  11.         CCalc calc;
  12.         calc.Calc("var=100");
  13.         cout<<"令: var=100"
  14.                 <<endl;
  15.         double x=calc.Calc("(var*2.0+10*(5+5)/5 )");
  16.         cout<<"(var*2.0+10*(5+5)/5 )="
  17.                 <<x<<endl;
  18.        
  19.         calc.Calc("甲值=210");
  20.         calc.Calc("乙值=10");
  21.         cout<<"令: 甲值=210, 乙值=10"
  22.                 <<endl;

  23.         cout<< "甲值*乙值/300="
  24.                 <<calc.Calc("甲值*乙值/300").real()
  25.                 <<endl;

  26.         cout<< "乙值+甲值*乙值/乙值-甲值="
  27.                 <<calc.Calc("乙值+甲值*乙值/乙值-甲值").real()
  28.                 <<endl;


  29.         cout<< "sin(var)*甲值/300="
  30.                 <<calc.Calc("sin(var)*甲值/300").real()
  31.                 <<endl<<endl;

  32.         //cout<< calc.Calc("i")<<endl;
  33.         }

  34.         catch (char* s) {
  35.                 cout<<"\n**  Error: ****"<<s<<endl;
  36.         }

  37. }
复制代码
支持含有中文变量名的表达式计算 支持含有中文变量名的表达式计算.rar (121.57 KB, 下载次数: 32)
支持含有中文变量名的表达式计算




上一篇:一个很完善的函数式计算器
下一篇:顺序表的基本操作
92_avatar_middle
在线会员 发表于 2010-12-3 19:51:58 | 显示全部楼层
  呵呵   不错咯   顶
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-9-21 07:52

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表