zoukankan      html  css  js  c++  java
  • 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

    仓促上传待整理。。。

  • 相关阅读:
    Azure PowerShell (7) 使用CSV文件批量设置Virtual Machine Endpoint
    Windows Azure Cloud Service (39) 如何将现有Web应用迁移到Azure PaaS平台
    Azure China (7) 使用WebMetrix将Web Site发布至Azure China
    Microsoft Azure News(4) Azure新D系列虚拟机上线
    Windows Azure Cloud Service (38) 微软IaaS与PaaS比较
    Windows Azure Cloud Service (37) 浅谈Cloud Service
    Azure PowerShell (6) 设置单个Virtual Machine Endpoint
    Azure PowerShell (5) 使用Azure PowerShell创建简单的Azure虚拟机和Linux虚拟机
    功能代码(1)---通过Jquery来处理复选框
    案例1.用Ajax实现用户名的校验
  • 原文地址:https://www.cnblogs.com/DonYao/p/11539980.html
Copyright © 2011-2022 走看看