• C#利用栈实现字符串运算解析


    附上参考文章链接:https://blog.csdn.net/qq_34831781/article/details/80104219

    本人整合修复一些bug后的代码

      1 using System;
      2 using System.Collections;
      3 using System.Collections.Generic;
      4 using System.Text;
      5 
      6 // 解析计算字符串公式
      7 namespace CalcuStrFormula
      8 {
      9     // 处理类
     10     class Handler
     11     {
     12         private Stack _complexNumberStack = new Stack();
     13         private Stack _operatorStack = new Stack();
     14         private Parser _parser = new Parser();
     15         private Operators _operators = new Operators();
     16 
     17         private static Handler _instance;
     18         public static Handler instance
     19         {
     20             get
     21             {
     22                 if (_instance == null)
     23                 {
     24                     _instance = new Handler();
     25                 }
     26                 return _instance;
     27             }
     28         }
     29 
     30         public ComplexNumber Process(string inputString)
     31         {
     32             _complexNumberStack.Clear();
     33             _operatorStack.Clear();
     34 
     35             Queue<object> queue = _parser.Parse(inputString);
     36             ComplexNumber complexNumber = null;
     37             char op, topOp;
     38             int count = queue.Count;
     39             for (int i = 0; i < count; i++)
     40             {
     41                 object obj = queue.Dequeue();
     42                 if (obj is char)
     43                 {
     44                     op = (char)obj;
     45                     if (_operatorStack.Count == 0)
     46                     {
     47                         _operatorStack.Push(op);
     48                     }
     49                     else
     50                     {
     51                         topOp = (char)_operatorStack.Peek();
     52                         if (op == '(')
     53                         {
     54                             _operatorStack.Push(op);  // 左括号直接压入。不判断栈顶
     55                         }
     56                         else if (op == ')')
     57                         {
     58                             // 右括号压入前观察栈顶,若栈顶是左括号,则弹出栈顶的左括号
     59                             // 否则弹出栈顶运算符,从数栈中弹出操作数进行运算,并将结果重新压入数栈,直到遇到左括号
     60                             while ((topOp = (char)_operatorStack.Pop()) != '(')
     61                             {
     62                                 ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
     63                                 ComplexNumber c2 = null; // 符号左边数
     64                                 if (_operators.IsTwoNumOperator(topOp))
     65                                 {
     66                                     c2 = (ComplexNumber)_complexNumberStack.Pop();
     67                                 }
     68                                 ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
     69                                 _complexNumberStack.Push(c3);
     70                             }
     71                         }
     72                         else if (_operators.ComparePriority(topOp, op) <= 0)
     73                         {
     74                             // 若即将压入的运算符不是括号,则比较栈顶运算符和即将压入的运算符的优先级
     75                             // 如果栈顶优先级高,则将栈顶运算符取出运算,直到栈顶优先级不大于其。
     76                             while (_operatorStack.Count != 0 && _operators.ComparePriority((char)_operatorStack.Peek(), op) <= 0)
     77                             {
     78                                 topOp = (char)_operatorStack.Pop();
     79                                 ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
     80                                 ComplexNumber c2 = null; // 符号左边数
     81                                 if (_operators.IsTwoNumOperator(topOp))
     82                                 {
     83                                     c2 = (ComplexNumber)_complexNumberStack.Pop();
     84                                 }
     85                                 ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
     86                                 _complexNumberStack.Push(c3);
     87                             }
     88                             _operatorStack.Push(op);
     89                         }
     90                         else
     91                         {
     92                             _operatorStack.Push(op);
     93                         }
     94                     }
     95                 }
     96                 else if (obj is ComplexNumber)
     97                 {
     98                     complexNumber = (ComplexNumber)obj;
     99                     _complexNumberStack.Push(complexNumber);
    100                 }
    101 
    102                 if (queue.Count == 0)
    103                 {
    104                     while (_operatorStack.Count != 0)
    105                     {
    106                         topOp = (char)_operatorStack.Pop();
    107                         ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
    108                         ComplexNumber c2 = null; // 符号左边数
    109                         if (_operators.IsTwoNumOperator(topOp))
    110                         {
    111                             c2 = (ComplexNumber)_complexNumberStack.Pop();
    112                         }
    113                         ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
    114                         _complexNumberStack.Push(c3);
    115                     }
    116                 }
    117             }
    118 
    119             return (ComplexNumber)_complexNumberStack.Pop();
    120         }
    121     }
    122 
    123     // 3+4i解析成Queue包含 3, +, 4i
    124     public class Parser
    125     {
    126         private Operators _operators = new Operators();
    127 
    128         public Queue<object> Parse(string input)
    129         {
    130             input = input.Replace(" ", "");
    131             if (input.StartsWith("-")) input = '0' + input;
    132 
    133             char[] arr = input.ToCharArray();
    134             Queue<char> queueChar = new Queue<char>();
    135             foreach (char x in arr)
    136             {
    137                 queueChar.Enqueue(x);
    138             }
    139             Queue<object> queueResult = ParseStringQueue(queueChar);
    140             return queueResult;
    141         }
    142 
    143         // 传入字符串队列,返回封装好的队列。
    144         // ComplexNumber对象或char类型运算符各占用一个结点
    145         private Queue<object> ParseStringQueue(Queue<char> queue)
    146         {
    147             Queue<object> secondQ = new Queue<object>();
    148             char c;
    149             StringBuilder sb = null;
    150             string temp;
    151             int count = queue.Count;
    152             bool flag = false; // false表示允许创建新SB对象进行缓存数字字符串
    153             for (int i = 0; i < count; i++)
    154             {
    155                 c = queue.Dequeue();
    156                 if (!_operators.Contains(c))
    157                 {
    158                     // 如果扫描到的不是运算符,则将其加入到buffer尾部
    159                     if (!flag)
    160                     {
    161                         flag = true;
    162                         sb = new StringBuilder();
    163                     }
    164                     sb.Append(c);
    165                 }
    166                 if (_operators.Contains(c) || queue.Count == 0)
    167                 {
    168                     // 如果扫描到的是运算符,则将缓冲区中的串加入队尾
    169                     if (sb != null && flag == true)
    170                     {
    171                         temp = sb.ToString();
    172                         try
    173                         {
    174                             if (temp.EndsWith("i"))
    175                             {
    176                                 if (temp.Length == 1)
    177                                 {
    178                                     secondQ.Enqueue(new ComplexNumber(0, 1));
    179                                 }
    180                                 else
    181                                 {
    182                                     // i前有数字则开出数字部分。
    183                                     temp = temp.Substring(0, temp.Length - 1);
    184                                     secondQ.Enqueue(new ComplexNumber(0, double.Parse(temp)));
    185                                 }
    186                             }
    187                             else
    188                             {
    189                                 secondQ.Enqueue(new ComplexNumber(double.Parse(temp), 0));
    190                             }
    191                             sb = null;
    192                             flag = false;
    193                         }
    194                         catch (Exception e)
    195                         {
    196                             UnityEngine.Debug.Log("Error " + e.ToString());
    197                         }
    198                     }
    199                     // 如果是运算符,则最后将运算符放入队。
    200                     if (_operators.Contains(c))
    201                     {
    202                         secondQ.Enqueue(c);
    203                     }
    204                 }
    205             }
    206 
    207             return secondQ;
    208         }
    209     }
    210 
    211     // 复数类,提供实数域虚数域,getset方法,加减乘除以及toString()方法
    212     class ComplexNumber
    213     {
    214         private double _realPart; // 实数部分
    215         private double _imaginPart; // 虚数部分
    216 
    217         public ComplexNumber()
    218         {
    219             _realPart = 0.0;
    220             _imaginPart = 0.0;
    221         }
    222         public ComplexNumber(double r, double i)
    223         {
    224             _realPart = r;
    225             _imaginPart = i;
    226         }
    227         public ComplexNumber(ComplexNumber c)
    228         {
    229             _realPart = c.GetRealPart();
    230             _imaginPart = c.GetImaginaryPart();
    231         }
    232 
    233         // get,set方法
    234         public double GetRealPart()
    235         {
    236             return _realPart;
    237         }
    238         public double GetImaginaryPart()
    239         {
    240             return _imaginPart;
    241         }
    242         public void SetRealPart(double d)
    243         {
    244             _realPart = d;
    245         }
    246         public void SetImaginaryPart(double d)
    247         {
    248             _imaginPart = d;
    249         }
    250 
    251         //
    252         public ComplexNumber ComplexAdd(ComplexNumber c)
    253         {
    254             return new ComplexNumber(_realPart + c.GetRealPart(), _imaginPart + c.GetImaginaryPart());
    255         }
    256         public ComplexNumber ComplexAdd(double c)
    257         {
    258             return new ComplexNumber(_realPart + c, _imaginPart);
    259         }
    260         //
    261         public ComplexNumber ComplexMinus(ComplexNumber c)
    262         {
    263             return new ComplexNumber(_realPart - c.GetRealPart(), _imaginPart - c.GetImaginaryPart());
    264         }
    265         public ComplexNumber ComplexMinus(double c)
    266         {
    267             return new ComplexNumber(_realPart - c, _imaginPart);
    268         }
    269         //
    270         public ComplexNumber ComplexMulti(ComplexNumber c)
    271         {
    272             return new ComplexNumber(
    273             _realPart * c.GetRealPart()
    274             - _imaginPart * c.GetImaginaryPart(),
    275             _realPart *
    276             c.GetImaginaryPart()
    277             + _imaginPart *
    278             c.GetRealPart());
    279         }
    280         public ComplexNumber ComplexMulti(double c)
    281         {
    282             return new ComplexNumber(_realPart * c, _imaginPart * c);
    283         }
    284         //
    285         public ComplexNumber ComplexDivision(ComplexNumber c)
    286         {
    287             return new ComplexNumber((_realPart * c.GetRealPart() + _imaginPart * c.GetImaginaryPart())
    288                 / (c.GetRealPart() * c.GetRealPart() + c.GetImaginaryPart() * c.GetImaginaryPart())
    289                 , (_imaginPart * c.GetRealPart() - _realPart * c.GetImaginaryPart())
    290                 / (c.GetRealPart() * c.GetRealPart() + c.GetImaginaryPart() * c.GetImaginaryPart()));
    291         }
    292         public ComplexNumber ComplexDivision(double c)
    293         {
    294             return new ComplexNumber(_realPart / c, _imaginPart / c);
    295         }
    296         //
    297         public ComplexNumber ComplexPow(ComplexNumber c)
    298         {
    299             int pow;
    300             if (int.TryParse(c.GetRealPart().ToString(), out pow))
    301             {
    302                 ComplexNumber origin = new ComplexNumber(this);
    303                 ComplexNumber multi = new ComplexNumber(this);
    304                 for (int i = 0; i < pow - 1; i++)
    305                 {
    306                     origin = origin.ComplexMulti(multi);
    307                 }
    308                 return origin;
    309             }
    310             else
    311             {
    312                 return ComplexPow(c.GetRealPart());
    313             }
    314         }
    315         public ComplexNumber ComplexPow(double c)
    316         {
    317             return new ComplexNumber(Math.Pow(_realPart, c), 0.0);
    318         }
    319         // 最小值
    320         public ComplexNumber ComplexMinimum(ComplexNumber c)
    321         {
    322             if (_realPart <= c.GetRealPart()) return this;
    323             return c;
    324         }
    325         // 最大值
    326         public ComplexNumber ComplexMaximum(ComplexNumber c)
    327         {
    328             if (_realPart >= c.GetRealPart()) return this;
    329             return c;
    330         }
    331         // 转int
    332         public ComplexNumber ToFloorInt()
    333         {
    334             _realPart = Math.Floor(_realPart);
    335             return this;
    336         }
    337 
    338         public override string ToString()
    339         {
    340             return "(" + _realPart + " + " + _imaginPart + " i" + ")";
    341         }
    342     }
    343 
    344     // 操作符类
    345     class Operators
    346     {
    347         private char[][] _signOperator;
    348 
    349         public Operators()
    350         {
    351             // 从上到下,优先级由高到低
    352             _signOperator = new char[4][];
    353             _signOperator[0] = new char[4];
    354             _signOperator[0][0] = '^';
    355             _signOperator[0][1] = 's'; // 最小值
    356             _signOperator[0][2] = 'b'; // 最大值
    357             _signOperator[0][3] = 'i'; // int值
    358             _signOperator[1] = new char[2];
    359             _signOperator[1][0] = '*';
    360             _signOperator[1][1] = '/';
    361             _signOperator[2] = new char[2];
    362             _signOperator[2][0] = '+';
    363             _signOperator[2][1] = '-';
    364             _signOperator[3] = new char[2];
    365             _signOperator[3][0] = '(';
    366             _signOperator[3][1] = ')';
    367         }
    368 
    369         // 比较操作符优先级
    370         public int ComparePriority(char firstSign, char secondSign)
    371         {
    372             int priorityF = 0, priorityS = 0;
    373             for (int i = 0; i < _signOperator.Length; i++)
    374             {
    375                 foreach (char x in _signOperator[i])
    376                 {
    377                     if (firstSign == x)
    378                     {
    379                         priorityF = i;
    380                     }
    381                     if (secondSign == x)
    382                     {
    383                         priorityS = i;
    384                     }
    385                 }
    386             }
    387 
    388             return (priorityF - priorityS);
    389         }
    390 
    391         // 是否是需要两个参数的操作符
    392         public bool IsTwoNumOperator(char op)
    393         {
    394             if (op == 'i') return false;
    395             return true;
    396         }
    397 
    398         public bool Contains(char x)
    399         {
    400             if (x == '' || x == '')
    401             {
    402                 UnityEngine.Debug.LogError(x + "为中文字符,请改为英文字符");
    403             }
    404 
    405             foreach (char[] arr in _signOperator)
    406             {
    407                 foreach (char y in arr)
    408                 {
    409                     if (x == y)
    410                     {
    411                         return true;
    412                     }
    413                 }
    414             }
    415             return false;
    416         }
    417 
    418         public ComplexNumber Compute(char op, ComplexNumber c1, ComplexNumber c2)
    419         {
    420             ComplexNumber result = null;
    421             switch (op)
    422             {
    423                 case '+': result = c1.ComplexAdd(c2); break;
    424                 case '-': result = c1.ComplexMinus(c2); break;
    425                 case '*': result = c1.ComplexMulti(c2); break;
    426                 case '/': result = c1.ComplexDivision(c2); break;
    427                 case '^': result = c1.ComplexPow(c2); break;
    428                 case 's': result = c1.ComplexMinimum(c2); break;
    429                 case 'b': result = c1.ComplexMaximum(c2); break;
    430                 case 'i': result = c2.ToFloorInt(); break;
    431             }
    432             return result;
    433         }
    434     }
    435 }
    View Code

    仓促上传待整理。。。

  • 相关阅读:
    A1042 Shuffling Machine (20)
    【SSM 4】Mybatis逆向生成工具
    【SSM 4】Mybatis逆向生成工具
    【SSM 3】Mybatis应用,和Hibernate的区别
    【SSM 3】Mybatis应用,和Hibernate的区别
    【SSM 2】spring常用注解
    【SSM 2】spring常用注解
    【SSM 1】SpringMVC、Spring和Struts的区别
    【SSM 1】SpringMVC、Spring和Struts的区别
    【java基础 5】树形结构数据加载的思考
  • 原文地址:https://www.cnblogs.com/DonYao/p/11539980.html
Copyright © 2020-2023  润新知