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

 

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

 

 

      其中采用了自定义公式来描述参数的变化将导致的图形变化。例如对于厚度的变化,定义的公式为:“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     /// <summary>
 2     /// 操作数类型
 3     /// </summary>
 4     public enum OperandType
 5     {
 6         /// <summary>
 7         /// 函数
 8         /// </summary>
 9         FUNC = 1,
10 
11         /// <summary>
12         /// 日期
13         /// </summary>
14         DATE = 2,
15 
16         /// <summary>
17         /// 数字
18         /// </summary>
19         NUMBER = 3,
20 
21         /// <summary>
22         /// 布尔
23         /// </summary>
24         BOOLEAN = 4,
25 
26         /// <summary>
27         /// 字符串
28         /// </summary>
29         STRING = 5
30 
31     }
 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         /// <summary>
19         /// 操作数类型
20         /// </summary>
21         public OperandType Type { getset; }
22 
23         /// <summary>
24         /// 关键字
25         /// </summary>
26         public string Key { getset; }
27 
28         /// <summary>
29         /// 操作数值
30         /// </summary>
31         public object Value { getset; }
32 
33         #endregion
34 
35         #region Public Method
36         /// <summary>
37         /// 转换操作数到指定的类型
38         /// </summary>
39         /// <param name="opd">操作数</param>
40         /// <returns>返回对应的操作数类型</returns>
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         /// <summary>
62         /// 判断对象是否为数字
63         /// </summary>
64         /// <param name="value">对象值</param>
65         /// <returns>是返回真,否返回假</returns>
66         public static bool IsNumber(object value)
67         {
68             double val;
69             return double.TryParse(value.ToString(), out val);
70         }
71 
72         /// <summary>
73         /// 判断对象是否为日期
74         /// </summary>
75         /// <param name="value">对象值</param>
76         /// <returns>是返回真,否返回假</returns>
77         public static bool IsDate(object value)
78         {
79             DateTime dt;
80             return DateTime.TryParse(value.ToString(), out dt);
81         }
82         #endregion
83     }

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2021-11-15
  • 2022-12-23
  • 2021-05-23
  • 2022-12-23
  • 2022-02-17
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案