• 支持函数,变量的算术表达式计算(三、加入函数)


    工作好忙。。。所以现在才来更新。。。

    有了前面的铺垫,要加入功能就很简单了,下面我们加入对函数的支持

    一、函数的要点有3个
    1. 名称: 没有名字可程序就不能识别了,呵呵
        例: Sin, Cos, Abs 等
    2. 参数:一个函数至少要有一个参数,参数必须放到括号里, 多个参数用逗号(,)分隔
    3. 计算:函数必须有一个输出值

    二、了解了这几点,加入函数的功能还是比较容易的
    1.根据函数的要点定义基类 FunctionBase, 加入一些属性
    a.名称
            protected string name;
            
    /// <summary>
            
    /// 函数名称
            
    /// </summary>

            public string Name
            
    {
                
    get return name; }
                
    set { name = value; }
            }
     b.参数
            protected decimal?[] data;
            
    /// <summary>
            
    /// 参数数组(储存传入的参数)
            
    /// </summary>

            public decimal?[] Data
            
    {
                
    get return data; }
                
    set { data = value; }
            }

            
    protected int paramCount;
            
    /// <summary>
            
    /// 指明参数的个数
            
    /// </summary>

            public int ParamCount
            
    {
                
    get return paramCount; }
            }
    c. 计算
            /// <summary>
            
    /// 计算(定义为虚函数)
            
    /// </summary>
            
    /// <returns></returns>

            public abstract object Calc();
    2. 解析表达式的时候, 加入对函数的支持
    再第二章的ConvertExpression结尾,已经有对函数的支持了,贴一小段看看
    default:
                                
    //数字
                                if (char.IsDigit(c))
                                
    {
                                    ProcDigit(
    ref i, ref strExpression);
                                }

                                
    else //其它的字符全当成函数
                                {
                                    ProcFunc(
    ref i, ref strExpression);
                                }

                                
    break;


    ProcFunc 函数和其它的 ProcXXXX 函数差不多, 无非就是对字符的解析
            private void ProcFunc(ref int index, ref string expression)
            
    {
                
    if (needOp)
                    
    throw new ExpressionException("缺少操作符"1001);

                StringBuilder str 
    = new StringBuilder();
                
    for (int i = index; i < expression.Length; i++)
                
    {
                    
    char c = expression[i];
                    
    if (char.IsWhiteSpace(c) || c == '(')
                    
    {
                        
    this.needParentheses = true;
                        
    break;
                    }

                    
    else
                    
    {
                        str.Append(c);
                    }

                    index 
    = i;
                }

                
    string strFunc = str.ToString();
                
    //函数是否正确
                if (!FuncFactory.IsValidFunc(strFunc))
                    
    throw new ExpressionException("函数名无效:" + strFunc, 2001);
                
    else
                    stackOp.Push((OperatorType)FuncFactory.GetFuncIndex(strFunc));
            }

    3. 修改 CalcOperator 函数, 加入对函数的计算
                if (IsBaseOperator(op))
                
    {
                    //第二章中的基本四则运算, 代码可参见第二章

                }

                
    else if (IsFunc(op))
                
    {
                    FunctionBase func 
    = FuncFactory.GetFunc((int)op);
                    
    if (func == null)
                        
    throw new ExpressionException("不可识别的函数名.");
                    
    else
                    
    {
                        func.Data 
    = data;
                        
    try
                        
    {
                            
    return func.Calc();
                        }

                        
    catch (Exception ex)
                        
    {
                            
    throw new ExpressionException("函数计算出错:" + ex.Message, 9000);
                        }

                    }

                }
    三、编写具体的函数
    a . 函数工厂类 FuncFactory , 根据函数名称返回具体的函数类, 略。。。
    b. 编写一个 sqrt 函数,作为实例,可自行添加任意函数
        /// <summary>
        
    /// 开平方
        
    /// </summary>

        public class FuncSQRT : FunctionBase
        
    {
            
    public FuncSQRT()
            
    {
                
    //参数名称和参数个数一定要设置正确
                
    //否则在解析的时候会出错
                paramCount = 1;
                name 
    = "SQRT";
            }

            
    /// <summary>
            
    /// 计算
            
    /// 函数类实现这一步就行了, 简单吧
            
    /// </summary>
            
    /// <returns></returns>

            public override object Calc()
            
    {
                
    if (data[0== null)
                    
    return DBNull.Value;
                
    return Math.Sqrt((double)data[0]);
            }

        }

    PS:前面有个朋友说缺少幂运算, 呵呵, 加上这个很简单
    看看加入了函数和幂运算的效果 :)

    下载程序
  • 相关阅读:
    nginx转发域名小记
    简化kubernetes应用部署工具之Helm应用部署
    docker-compose的使用
    使用二进制包安装k8s
    搭建k8s(一)
    linux环境下安装使用selenium Chrome
    常用User-Agent大全
    缓存之Memcache
    git-commit Angular规范
    Kubernetes介绍及基本概念
  • 原文地址:https://www.cnblogs.com/michaelhuwei/p/1123401.html
Copyright © 2020-2023  润新知