在一个XML文件中给定计算的表达式,如何在ASP.Net中自动执行之?
比如:
param.xml
<?xml version="1.0" encoding="gb2312" ?>
<产品成本>
  <管理总费用>30000.00</管理总费用>
  <本月产品数量 单位="个">20000</本月产品数量>
  <工人工资总费用>100000</工人工资总费用>
  <固定资产折旧费用>20000</固定资产折旧费用>
  <其他费用>10000</其他费用>
  <产品单位成本>(管理总费用 + 工人工资总费用 + 固定资产折旧费用 + 其他费用) / 本月产品数量
  </产品单位成本>
</产品成本>在asp.net中,可以采用:
....
public double 管理总费用 = xmlDoc.SelectSingleNode("/产品成本/管理总费用");
....
public double 其他费用 =  xmlDoc.SelectSingleNode("/产品成本/其他费用");
public string 单位成本计算表达式= xmlDoc.SelectSingleNode("/产品成本/产品单位成本");问题是:如何让"单位成本计算表达式"执行出结果呢?谢谢.

解决方案 »

  1.   

    楼上:就是可以把各个节点的值取出来,但是由于计算所用表达式也是从XML中取出的,我的问题是如何让“表达式”转为自动执行。
      

  2.   

    要结合算术符号优先级来做首先读取所有“单位成本”以前的所有数据
    记录下它的名称,和值string[] names,double[] values;然后扫描单位成功计算公式,以算术符号为分割副获取公式字段,然后扫描names并找到相应的值。
    将值和取出的算术符号压入一个栈中,比较算术符号优先级,进行算术运算和栈,重复这个过程一直扫描到</单位成本>
    当然你要进行算术符号分类才能进行运算最后栈中的数据就是你要的,
      

  3.   

    可以重温一下<<编译原理>>,实现技术上说没有问题,主要是太繁了
    慢慢辛苦咯
      

  4.   

    C#中就没有一个类似JavaScript中的Eval()执行语句吗?
      

  5.   

    参考    怎样将字符串的公式转换成程序表达的公式在vc下的。要先改为c#的语法String 改为string 等等;
    用的时候用loadexp(string)读入你的表达式;
    然后用string getresult()返回的到结果;mfc下通过编译可以运行,有表达式纠错功能。
    运算符号有+ - * / ^ sin() cos() tan() ln() () 任意的组合或嵌套class supermath{
    public:
        int deadline;
        CString errormsg;
    CString expstr;
        CString thesign;
        float runstr(CString,int);
        int isdigits(CString);
        void xtrim(CString*);
        void prerun(CString*);
    CString getresult();
    void loadexp(CString);
    };void supermath::loadexp(CString str){
        expstr=str;
    }int supermath::isdigits(CString str)
    {
        int i,is=1;
    char *t=str.GetBuffer(str.GetLength());
    for (i=0;i<(int)strlen(t);i++)
        if (!((*(t+i)>='0' && *(t+i)<='9') || *(t+i)=='.' || (*(t+i)=='-' && i==0))) is=0;
    return is;
    }void supermath::xtrim(CString *str)
    {
        char *t=str->GetBuffer(str->GetLength());
    int level=0,isdotrim=1;
    for(int i=0;i<(int)strlen(t)-1;i++)
    {
        if (*(t+i)=='(') level++;
            if (*(t+i)==')') level--;
    if (level==0) isdotrim=0;
    }
        if ((isdotrim)&&strlen(t)>1) 
    {
    *str=str->Mid(1,str->GetLength()-2); 
        xtrim(str);    
    }
    }void supermath::prerun(CString *str){
        int level=0,i;
    for(i=0;i<str->GetLength();i++){
        if (str->Mid(i,1)=='(') level++;
            if (str->Mid(i,1)==')') level--;
    }
    if (level!=0) errormsg="括号请成对!";
    str->Replace("tg","tan");
    }float supermath::runstr(CString str,int maxtime)
    {
    float midvar;
    int i,j,level;
    if (errormsg!="") return 2;
    if (maxtime>deadline) {
    errormsg="expression fleat!!";
        return 2;
    }
    xtrim(&str);
    if (isdigits(str)) return (float)atof(str.GetBuffer(str.GetLength()));
        else {
    char *exp=str.GetBuffer(str.GetLength());
    char *sign=thesign.GetBuffer(str.GetLength());
            for(i=0;i<10;i++){
    level=0;
        for(j=0;j<str.GetLength()-1;j++)
    {
    if (*(exp+j)=='(') level++;
    if (*(exp+j)==')') level--;
    if (str.Mid(j,1)==thesign.Mid(i,1) && level==0) {
    CString str1=str.Mid(0,j);
                        CString str2=str.Mid(j+1);
    switch (*(sign+i))
    {
    case '+':
                            return runstr(str1,maxtime+1)+runstr(str2,maxtime+1);break;
    case '-':
    if (str1=="") midvar=0; else midvar=runstr(str1,maxtime+1);
                            return midvar-runstr(str2,maxtime+1);break;
    case '*':
                            return runstr(str1,maxtime+1)*runstr(str2,maxtime+1);break;
    case '/':
    midvar=runstr(str2,maxtime+1);
    if (midvar==0)  {errormsg+=" '/0'形错误 位置:‘"+str+"’<-err..  "; return 2;}
    return runstr(str1,maxtime+1)/midvar; break;
    case '^':
    midvar=(float)pow(runstr(str1,maxtime+1),runstr(str2,maxtime+1));
    if ((midvar+1)==midvar) { errormsg+=" '-x^0.5'形错误 位置:‘"; errormsg+=str; errormsg+="’<-err..  "; return 2; }
    return midvar; break;
    case 'i': 
    return (float)sin(runstr(str2.Mid(1),maxtime+1));break;
    case 'c':
    return (float)cos(runstr(str2.Mid(2),maxtime+1));break;
    case 't':
    midvar=(float)tan(runstr(str2.Mid(2),maxtime+1));
    if ((midvar+1)==midvar) {errormsg+=" 'tan(pi/2)'形错误 位置:‘"+str+"’<-err..  "; return 2;} 
        return midvar; break;
    case 'b':
    return (float)fabs(runstr(str2.Mid(1),maxtime+1));break;
    case 'l':
    midvar=runstr(str2.Mid(1),maxtime+1);
    if (midvar<=0)  {errormsg+=" 'ln-'形错误 位置:‘"+str+"’<-err..  "; return 2;} 
    return (float)log(midvar); break;
    default:
    errormsg+=" 内部未知错误!";
    }
    }
    }
    }
    }
    errormsg+="含有未知运算符 位置:‘"+str+"’<-err.. ";
    return 2;
    }
    CString supermath::getresult()
    {   
    deadline=10;
        errormsg="";
    thesign="+-/*^ictbl";
    errormsg="";
    CString str; prerun(&expstr);
    str.Format("%f",runstr(expstr,1));
    if (errormsg=="") return str; else return errormsg;
    }
      

  6.   

    不要失望,下面的可以。
    http://www.yestar2000.com/TechCenter/1410/TC_16048.htm
    //===========================================================
    //四种Eval测试结果:不要用CodeDom做大批量的表达式四则运算
    //===========================================================--------------------------------------------------------------------------------
    作者:qiushuiwuhen 来源:未知 加入时间:2004-6-29 浏览次数: 
    -------------------------------------------------------------------------------- 
    有时候需要表达式运算,如
    String strExpression="-12 * ( - 2.2 + 7.7 ) - 44 * 2";网上找的,一般是利用CodeDom,见
    http://www.codeproject.com/csharp/runtime_eval.asp简化为:
     System.CodeDom.Compiler.ICodeCompiler comp = (new Microsoft.CSharp.CSharpCodeProvider().CreateCompiler());
     System.CodeDom.Compiler.CompilerParameters cp = new System.CodeDom.Compiler.CompilerParameters();object qswhEval2(string Expression){
     StringBuilder code = new StringBuilder();
     code.Append("using System; \n");
     code.Append("namespace ADOGuy { \n");
     code.Append("  public class _Evaluator { \n");
     code.Append("    public object __foo() ");
     code.Append("{ ");
     code.AppendFormat("      return ({0}); ", Expression);
     code.Append("}\n");
     code.Append("} }");
     System.CodeDom.Compiler.CompilerResults cr = comp.CompileAssemblyFromSource(cp, code.ToString());
     System.Reflection.Assembly a = cr.CompiledAssembly;
     object _Compiled = a.CreateInstance("ADOGuy._Evaluator");
     System.Reflection.MethodInfo mi = _Compiled.GetType().GetMethod("__foo");
     return mi.Invoke(_Compiled, null);

    但用起来感觉很慢,毕竟需要实时编译。于是,就自己照数据结构书上写了一种算法:
    string Precede(string p, string q){
     switch(p){
      case "+":
      case "-":return ("*/(".IndexOf(q)!=-1)?"<":">";
      case "*":
      case "/":return (q=="(")?"<":">";
      case "(":return (q==")")?"=":"<";
      case ")":return (q=="(")?"?":">";
      case "#":return (q=="#")?"=":"<";
     }
     return "?";
    }
    Double Operate(Double a,char o,Double b)
    {
       switch(o)
        {
          case '+':return a+b;
          case '-':return a-b;
          case '*':return a*b;
          case '/':return a/b;
        }
        return 0;
    }Object qswhEval1(string Expression){
     /*************(qiushuiwuhen 2002-12-14)****************/
     Stack nArr=new Stack(),oArr=new Stack();
     int j=0;
     Double a=0,b=0;
     string w="";
     char o;
     MatchCollection arr=Regex.Matches(Expression.Replace(" ","")+"#",@"(((?<=(^|\())-)?\d+(\.\d+)?|\D)");
     
     oArr.Push('#');
     w=Convert.ToString(arr[j++]);
     while(!(w=="#"&&Convert.ToString(oArr.Peek())=="#")){
      if("+-*/()#".IndexOf(w)!=-1){
       switch(Precede(oArr.Peek().ToString(),w)){
        case "<":
          oArr.Push(w);
          w=Convert.ToString(arr[j++]);
          break;
        case "=":
          oArr.Pop();
          w=Convert.ToString(arr[j++]);
          break;
        case ">":
          o=Convert.ToChar(oArr.Pop());
          b=Convert.ToDouble(nArr.Pop());
          a=Convert.ToDouble(nArr.Pop());
          nArr.Push(Operate(a,o,b));
          break;
        default:
          return "Error";
          break;
         
       }
      }else{
       nArr.Push(w);
       w=Convert.ToString(arr[j++]);
      }
     }
     return nArr.Pop();
    }还有利用JScript的Eval的两种算法
    Microsoft.JScript.Vsa.VsaEngine ve=Microsoft.JScript.Vsa.VsaEngine.CreateEngine();
    object qswhEval3(string Expression){
     return Microsoft.JScript.Eval.JScriptEvaluate(Expression,ve);
    }object qswhEval4(string Expression){
     return qswhJs.qswhEval.Eval(Expression);
    }第四种需先建立一js编译为dll,如下代码
    import System;package qswhJs {
      class qswhEval {
        static function Eval(Expression):Object { return eval(Expression); }
      }
    }测试代码如下:
    void Page_Load(Object o,EventArgs ea){
     String strExpression="-12 * ( - 2.2 + 7.7 ) - 44 * 2";
     int i=0,c=100;
     DateTime d1,d2;
    cp.GenerateExecutable = false;
    cp.GenerateInMemory = true;
     
     d1=DateTime.Now;
     for(i=0;i<c;i++)qswhEval1(strExpression);
     d2=DateTime.Now;
     Response.Write("方法一:对表达式分析 "+d2.Subtract(d1)+"<br>");
     
     d1=DateTime.Now;
     for(i=0;i<c;i++)qswhEval2(strExpression);
     d2=DateTime.Now;
     Response.Write("方法二:利用CodeCom  "+d2.Subtract(d1)+"<br>");
     
     d1=DateTime.Now;
     for(i=0;i<c;i++)qswhEval3(strExpression);
     d2=DateTime.Now;
     Response.Write("方法三:利用Jscript+Vsa  "+d2.Subtract(d1)+"<br>");
     
     d1=DateTime.Now;
     for(i=0;i<c;i++)qswhEval4(strExpression);
     d2=DateTime.Now;
     Response.Write("方法四:利用Jsc+Dll  "+d2.Subtract(d1)+"<br>");
    }测试结果:方法一:对表达式分析 00:00:00.1702448
    方法二:利用CodeCom 00:00:23.7942144
    方法三:利用Jscript+Vsa 00:00:00.1902736
    方法四:利用Jsc+Dll 00:00:00.2403456在此推荐第一种(如果要纯CSharp的话)
    和第三种(代码简单,功能更多)
      

  7.   

    happyjun2000(蓝色游侠∮学习@交流) :
    感谢你的热心帮助,我比较菜,调试过程中还是有点问题。有没有你调试过的源代码,发给我行吗?
    Email(MSN):a3news(AT)hotmail.com另外,到这里回复一下,我好将分(另加50分)给你。http://community.csdn.net/Expert/topic/3529/3529655.xml?temp=.107052