字符串公式解析器——使用 逆波兰式算法 及C 实现

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

原文地址:

 http://www.cnblogs.com/lxfqlcz/archive/2011/08/02/2124854.html

 

从5月中旬到7月中旬,我一直在做焊接工程中接头图的参数化和自动化生成软件。主要是将各种标准接头图分解为一个个的图元,并自定义图元参数和图参数,用户在使用时,只需修改相关参数值,即能生成其所需要的接头图,无须再人工用CAD软件手动绘画。如下图所示。

 

 

 

      其中采用了自定义公式来描述参数的变化将导致的图形变化。例如对于厚度的变化,定义的公式为:“dotAll.x=dotAll.x*t1/dot1.y;dotAll.y=dotAll.y*t1/dot1.y;”。这个公式表示对于图形中的所有点,当厚度变化时,点的x坐标变为 原x坐标值乘以新的厚度,再除以原来的序号为1的点的y坐标(即原来的厚度),同理对于y坐标的变化也一样。

      最终公式将解析成 x=2.0 * 3 / 1.5, 最终结果为 4.0。问题的焦点在于如何将“2.0 * 3 / 1.5”这种字符串的表达式,让计算机能理解,并计算出结果。这里我采用了“逆波兰式算法”来解决这个问题。

     关于“逆波兰式算法”的具体内容,请看这里 http://baike.baidu.com/view/2582.htm ,里面解释得很好。

     最终程序里面的算法描述如下 :

 

逆波兰式算法
       1、从左至右扫描一中缀表达式。
                2、若读取的是操作数,则判断该操作数的类型,并将该操作数存入操作数堆栈
                3、若读取的是运算符
                   (1) 该运算符为左括号"(",则直接存入运算符堆栈。
                   (2) 该运算符为右括号")",则输出运算符堆栈中的运算符到操作数堆栈,直到遇到左括号为止,此时抛弃该左括号。
                   (3) 该运算符为非括号运算符:
                       (a) 若运算符堆栈栈顶的运算符为左括号,则直接存入运算符堆栈。
                       (b) 若比运算符堆栈栈顶的运算符优先级高,则直接存入运算符堆栈。
                       (c) 若比运算符堆栈栈顶的运算符优先级低或相等,则输出栈顶运算符到操作数堆栈,直至运算符栈栈顶运算符低于(不包括等于)该运算符优先级,或为左括号,
                           并将当前运算符压入运算符堆栈。
                4、当表达式读取完成后运算符堆栈中尚有运算符时,则依序取出运算符到操作数堆栈,直到运算符堆栈为空。

 

  下面我们来具体实现下这个算法,代码中注释较全,就不详细解说了。

  首先,我们来定义下操作数类。

定义操作数类型枚举
 1       ///  
 2       ///  操作数类型
 3       ///  

 4       public   enum  OperandType
 5      {
 6           ///  
 7           ///  函数
 8           ///  

 9          FUNC  =   1 ,
10 
11           ///  
12           ///  日期
13           ///  

14          DATE  =   2 ,
15 
16           ///  
17           ///  数字
18           ///  

19          NUMBER  =   3 ,
20 
21           ///  
22           ///  布尔
23           ///  

24          BOOLEAN  =   4 ,
25 
26           ///  
27           ///  字符串
28           ///  

29          STRING  =   5
30 
31      }
操作数类 Operand
 1    public   class  Operand
 2      {
 3           #region  Constructed Function
 4           public  Operand(OperandType type,  object  value)
 5          {
 6               this .Type  =  type;
 7               this .Value  =  value;
 8          }
 9 
10           public  Operand( string  opd,  object  value)
11          {
12               this .Type  =  ConvertOperand(opd);
13               this .Value  =  value;
14          }
15           #endregion
16 
17           #region  Variable & Property
18           ///  
19           ///  操作数类型
20           ///  

21           public  OperandType Type {  get set ; }
22 
23           ///  
24           ///  关键字
25           ///  

26           public   string  Key {  get set ; }
27 
28           ///  
29           ///  操作数值
30           ///  

31           public   object  Value {  get set ; }
32 
33           #endregion
34 
35           #region  Public Method
36           ///  
37           ///  转换操作数到指定的类型
38           ///  

39           ///   操作数
40           ///   返回对应的操作数类型
41           public   static  OperandType ConvertOperand( string  opd)
42          {
43               if  (opd.IndexOf( " ( " >   - 1 )
44              {
45                   return  OperandType.FUNC;
46              }
47               else   if  (IsNumber(opd))
48              {
49                   return  OperandType.NUMBER;
50              }
51               else   if  (IsDate(opd))
52              {
53                   return  OperandType.DATE;
54              }
55               else
56              {
57                   return  OperandType.STRING;
58              }
59          }
60 
61           ///  
62           ///  判断对象是否为数字
63           ///  

64           ///   对象值
65           ///   是返回真,否返回假
66           public   static   bool  IsNumber( object  value)
67          {
68               double  val;
69               return   double .TryParse(value.ToString(),  out  val);
70          }
71 
72           ///  
73           ///  判断对象是否为日期
74           ///  

75           ///   对象值
76           ///   是返回真,否返回假
77           public   static   bool  IsDate( object  value)
78          {
79              DateTime dt;
80               return  DateTime.TryParse(value.ToString(),  out  dt);
81          }
82           #endregion
83      }

     然后,我们来定义下运算符类。

运算符类型枚举
  1  ///  
  2       ///  运算符类型(从上到下优先级依次递减),数值越大,优先级越低
  3       ///  

  4       public   enum  OperatorType
  5      {
  6           ///  
  7           ///  左括号:(,left bracket
  8           ///  

  9          LB  =   10 ,
 10 
 11           ///  
 12           ///  右括号),right bracket
 13           ///  

 14          RB  =   11 ,
 15 
 16           ///  
 17           ///  逻辑非,!,NOT
 18           ///  

 19          NOT  =   20 ,
 20 
 21           ///  
 22           ///  正号,+,positive sign
 23           ///  

 24          PS  =   21 ,
 25 
 26           ///  
 27           ///  负号,-,negative sign
 28           ///  

 29          NS  =   22 ,
 30 
 31           ///  
 32           ///  正切,tan
 33           ///  

 34          TAN  =   23 ,
 35           ///  
 36           ///  反正切,atan
 37           ///  

 38          ATAN  =   24 ,
 39 
 40 
 41           ///  
 42           ///  乘,*,multiplication
 43           ///  

 44          MUL  =   30 ,
 45 
 46           ///  
 47           ///  除,/,division
 48           ///  

 49          DIV  =   31 ,
 50 
 51           ///  
 52           ///  余,%,modulus
 53           ///  

 54          MOD  =   32 ,
 55 
 56           ///  
 57           ///  加,+,Addition
 58           ///  

 59          ADD  =   40 ,
 60 
 61           ///  
 62           ///  减,-,subtraction
 63           ///  

 64          SUB  =   41 ,
 65 
 66           ///  
 67           ///  小于,less than
 68           ///  

 69          LT  =   50 ,
 70 
 71           ///  
 72           ///  小于或等于,less than or equal to
 73           ///  

 74          LE  =   51 ,
 75 
 76           ///  
 77           ///  大于,>,greater than
 78           ///  

 79          GT  =   52 ,
 80 
 81           ///  
 82           ///  大于或等于,>=,greater than or equal to
 83           ///  

 84          GE  =   53 ,
 85 
 86           ///  
 87           ///  等于,=,equal to
 88           ///  

 89          ET  =   60 ,
 90 
 91           ///  
 92           ///  不等于,unequal to
 93           ///  

 94          UT  =   61 ,
 95 
 96           ///  
 97           ///  逻辑与,&,AND
 98           ///  

 99          AND  =   70 ,
100 
101           ///  
102           ///  逻辑或,|,OR
103           ///  

104          OR  =   71 ,
105 
106           ///  
107           ///  逗号,comma
108           ///  

109          CA  =   80 ,
110 
111           ///  
112           ///  结束符号 @
113           ///  

114          END  =   255 ,
115 
116           ///  
117           ///  错误符号
118           ///  

119          ERR  =   256
120 
121      }
运算符类
     public   class  Operator
    {
        
public  Operator(OperatorType type,  string  value)
        {
            
this .Type  =  type;
            
this .Value  =  value;
        }

        
///  
        
///  运算符类型
        
///  

         public  OperatorType Type {  get set ; }

        
///  
        
///  运算符值
        
///  

         public   string  Value {  get set ; }


        
///  
        
///  对于>或者<运算符,判断实际是否为>=,<>、<=,并调整当前运算符位置
        
///  

        
///   当前运算符
        
///   当前表达式
        
///   当前运算符位置
        
///   调整后运算符位置
        
///   返回调整后的运算符
         public   static   string  AdjustOperator( string  currentOpt,  string  currentExp,  ref   int  currentOptPos)
        {
            
switch  (currentOpt)
            {
                
case   " < " :
                    
if  (currentExp.Substring(currentOptPos,  2 ==   " <= " )
                    {
                        currentOptPos
++ ;
                        
return   " <= " ;
                    }
                    
if  (currentExp.Substring(currentOptPos,  2 ==   " <> " )
                    {
                        currentOptPos
++ ;
                        
return   " <> " ;
                    }
                    
return   " < " ;

                
case   " > " :
                    
if  (currentExp.Substring(currentOptPos,  2 ==   " >= " )
                    {
                        currentOptPos
++ ;
                        
return   " >= " ;
                    }
                    
return   " > " ;
                
case   " t " :
                    
if  (currentExp.Substring(currentOptPos,  3 ==   " tan " )
                    {
                        currentOptPos 
+=   2 ;
                        
return   " tan " ;
                    }
                    
return   " error " ;
                
case   " a " :
                    
if  (currentExp.Substring(currentOptPos,  4 ==   " atan " )
                    {
                        currentOptPos 
+=   3 ;
                        
return   " atan " ;
                    }
                    
return   " error " ;
                
default :
                    
return  currentOpt;
            }
        }

        
///  
        
///  转换运算符到指定的类型
        
///  

        
///   运算符
        
///   是否为二元运算符
        
///   返回指定的运算符类型
         public   static  OperatorType ConvertOperator( string  opt,  bool  isBinaryOperator)
        {
            
switch  (opt)
            {
                
case   " ! " return  OperatorType.NOT;
                
case   " + " return  isBinaryOperator  ?  OperatorType.ADD : OperatorType.PS;
                
case   " - " return  isBinaryOperator  ?  OperatorType.SUB : OperatorType.NS;
                
case   " * " return  isBinaryOperator  ?  OperatorType.MUL : OperatorType.ERR;
                
case   " / " return  isBinaryOperator  ?  OperatorType.DIV : OperatorType.ERR;
            &nb

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

这里写图片描述

你可能感兴趣的:(字符串公式解析器——使用 逆波兰式算法 及C 实现)