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

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

 using System;
using System.Collections;
using System.Collections.Generic;
using System.Text; // 解析计算字符串公式
namespace CalcuStrFormula
{
// 处理类
class Handler
{
private Stack _complexNumberStack = new Stack();
private Stack _operatorStack = new Stack();
private Parser _parser = new Parser();
private Operators _operators = new Operators(); private static Handler _instance;
public static Handler instance
{
get
{
if (_instance == null)
{
_instance = new Handler();
}
return _instance;
}
} public ComplexNumber Process(string inputString)
{
_complexNumberStack.Clear();
_operatorStack.Clear(); Queue<object> queue = _parser.Parse(inputString);
ComplexNumber complexNumber = null;
char op, topOp;
int count = queue.Count;
for (int i = ; i < count; i++)
{
object obj = queue.Dequeue();
if (obj is char)
{
op = (char)obj;
if (_operatorStack.Count == )
{
_operatorStack.Push(op);
}
else
{
topOp = (char)_operatorStack.Peek();
if (op == '(')
{
_operatorStack.Push(op); // 左括号直接压入。不判断栈顶
}
else if (op == ')')
{
// 右括号压入前观察栈顶,若栈顶是左括号,则弹出栈顶的左括号
// 否则弹出栈顶运算符,从数栈中弹出操作数进行运算,并将结果重新压入数栈,直到遇到左括号
while ((topOp = (char)_operatorStack.Pop()) != '(')
{
ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
ComplexNumber c2 = null; // 符号左边数
if (_operators.IsTwoNumOperator(topOp))
{
c2 = (ComplexNumber)_complexNumberStack.Pop();
}
ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
_complexNumberStack.Push(c3);
}
}
else if (_operators.ComparePriority(topOp, op) <= )
{
// 若即将压入的运算符不是括号,则比较栈顶运算符和即将压入的运算符的优先级
// 如果栈顶优先级高,则将栈顶运算符取出运算,直到栈顶优先级不大于其。
while (_operatorStack.Count != && _operators.ComparePriority((char)_operatorStack.Peek(), op) <= )
{
topOp = (char)_operatorStack.Pop();
ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
ComplexNumber c2 = null; // 符号左边数
if (_operators.IsTwoNumOperator(topOp))
{
c2 = (ComplexNumber)_complexNumberStack.Pop();
}
ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
_complexNumberStack.Push(c3);
}
_operatorStack.Push(op);
}
else
{
_operatorStack.Push(op);
}
}
}
else if (obj is ComplexNumber)
{
complexNumber = (ComplexNumber)obj;
_complexNumberStack.Push(complexNumber);
} if (queue.Count == )
{
while (_operatorStack.Count != )
{
topOp = (char)_operatorStack.Pop();
ComplexNumber c1 = (ComplexNumber)_complexNumberStack.Pop(); // 符号右边数
ComplexNumber c2 = null; // 符号左边数
if (_operators.IsTwoNumOperator(topOp))
{
c2 = (ComplexNumber)_complexNumberStack.Pop();
}
ComplexNumber c3 = _operators.Compute(topOp, c2, c1);
_complexNumberStack.Push(c3);
}
}
} return (ComplexNumber)_complexNumberStack.Pop();
}
} // 3+4i解析成Queue包含 3, +, 4i
public class Parser
{
private Operators _operators = new Operators(); public Queue<object> Parse(string input)
{
input = input.Replace(" ", "");
if (input.StartsWith("-")) input = '' + input; char[] arr = input.ToCharArray();
Queue<char> queueChar = new Queue<char>();
foreach (char x in arr)
{
queueChar.Enqueue(x);
}
Queue<object> queueResult = ParseStringQueue(queueChar);
return queueResult;
} // 传入字符串队列,返回封装好的队列。
// ComplexNumber对象或char类型运算符各占用一个结点
private Queue<object> ParseStringQueue(Queue<char> queue)
{
Queue<object> secondQ = new Queue<object>();
char c;
StringBuilder sb = null;
string temp;
int count = queue.Count;
bool flag = false; // false表示允许创建新SB对象进行缓存数字字符串
for (int i = ; i < count; i++)
{
c = queue.Dequeue();
if (!_operators.Contains(c))
{
// 如果扫描到的不是运算符,则将其加入到buffer尾部
if (!flag)
{
flag = true;
sb = new StringBuilder();
}
sb.Append(c);
}
if (_operators.Contains(c) || queue.Count == )
{
// 如果扫描到的是运算符,则将缓冲区中的串加入队尾
if (sb != null && flag == true)
{
temp = sb.ToString();
try
{
if (temp.EndsWith("i"))
{
if (temp.Length == )
{
secondQ.Enqueue(new ComplexNumber(, ));
}
else
{
// i前有数字则开出数字部分。
temp = temp.Substring(, temp.Length - );
secondQ.Enqueue(new ComplexNumber(, double.Parse(temp)));
}
}
else
{
secondQ.Enqueue(new ComplexNumber(double.Parse(temp), ));
}
sb = null;
flag = false;
}
catch (Exception e)
{
UnityEngine.Debug.Log("Error " + e.ToString());
}
}
// 如果是运算符,则最后将运算符放入队。
if (_operators.Contains(c))
{
secondQ.Enqueue(c);
}
}
} return secondQ;
}
} // 复数类,提供实数域虚数域,getset方法,加减乘除以及toString()方法
class ComplexNumber
{
private double _realPart; // 实数部分
private double _imaginPart; // 虚数部分 public ComplexNumber()
{
_realPart = 0.0;
_imaginPart = 0.0;
}
public ComplexNumber(double r, double i)
{
_realPart = r;
_imaginPart = i;
}
public ComplexNumber(ComplexNumber c)
{
_realPart = c.GetRealPart();
_imaginPart = c.GetImaginaryPart();
} // get,set方法
public double GetRealPart()
{
return _realPart;
}
public double GetImaginaryPart()
{
return _imaginPart;
}
public void SetRealPart(double d)
{
_realPart = d;
}
public void SetImaginaryPart(double d)
{
_imaginPart = d;
} // 加
public ComplexNumber ComplexAdd(ComplexNumber c)
{
return new ComplexNumber(_realPart + c.GetRealPart(), _imaginPart + c.GetImaginaryPart());
}
public ComplexNumber ComplexAdd(double c)
{
return new ComplexNumber(_realPart + c, _imaginPart);
}
// 减
public ComplexNumber ComplexMinus(ComplexNumber c)
{
return new ComplexNumber(_realPart - c.GetRealPart(), _imaginPart - c.GetImaginaryPart());
}
public ComplexNumber ComplexMinus(double c)
{
return new ComplexNumber(_realPart - c, _imaginPart);
}
// 乘
public ComplexNumber ComplexMulti(ComplexNumber c)
{
return new ComplexNumber(
_realPart * c.GetRealPart()
- _imaginPart * c.GetImaginaryPart(),
_realPart *
c.GetImaginaryPart()
+ _imaginPart *
c.GetRealPart());
}
public ComplexNumber ComplexMulti(double c)
{
return new ComplexNumber(_realPart * c, _imaginPart * c);
}
// 除
public ComplexNumber ComplexDivision(ComplexNumber c)
{
return new ComplexNumber((_realPart * c.GetRealPart() + _imaginPart * c.GetImaginaryPart())
/ (c.GetRealPart() * c.GetRealPart() + c.GetImaginaryPart() * c.GetImaginaryPart())
, (_imaginPart * c.GetRealPart() - _realPart * c.GetImaginaryPart())
/ (c.GetRealPart() * c.GetRealPart() + c.GetImaginaryPart() * c.GetImaginaryPart()));
}
public ComplexNumber ComplexDivision(double c)
{
return new ComplexNumber(_realPart / c, _imaginPart / c);
}
// 幂
public ComplexNumber ComplexPow(ComplexNumber c)
{
int pow;
if (int.TryParse(c.GetRealPart().ToString(), out pow))
{
ComplexNumber origin = new ComplexNumber(this);
ComplexNumber multi = new ComplexNumber(this);
for (int i = ; i < pow - ; i++)
{
origin = origin.ComplexMulti(multi);
}
return origin;
}
else
{
return ComplexPow(c.GetRealPart());
}
}
public ComplexNumber ComplexPow(double c)
{
return new ComplexNumber(Math.Pow(_realPart, c), 0.0);
}
// 最小值
public ComplexNumber ComplexMinimum(ComplexNumber c)
{
if (_realPart <= c.GetRealPart()) return this;
return c;
}
// 最大值
public ComplexNumber ComplexMaximum(ComplexNumber c)
{
if (_realPart >= c.GetRealPart()) return this;
return c;
}
// 转int
public ComplexNumber ToFloorInt()
{
_realPart = Math.Floor(_realPart);
return this;
} public override string ToString()
{
return "(" + _realPart + " + " + _imaginPart + " i" + ")";
}
} // 操作符类
class Operators
{
private char[][] _signOperator; public Operators()
{
// 从上到下,优先级由高到低
_signOperator = new char[][];
_signOperator[] = new char[];
_signOperator[][] = '^';
_signOperator[][] = 's'; // 最小值
_signOperator[][] = 'b'; // 最大值
_signOperator[][] = 'i'; // int值
_signOperator[] = new char[];
_signOperator[][] = '*';
_signOperator[][] = '/';
_signOperator[] = new char[];
_signOperator[][] = '+';
_signOperator[][] = '-';
_signOperator[] = new char[];
_signOperator[][] = '(';
_signOperator[][] = ')';
} // 比较操作符优先级
public int ComparePriority(char firstSign, char secondSign)
{
int priorityF = , priorityS = ;
for (int i = ; i < _signOperator.Length; i++)
{
foreach (char x in _signOperator[i])
{
if (firstSign == x)
{
priorityF = i;
}
if (secondSign == x)
{
priorityS = i;
}
}
} return (priorityF - priorityS);
} // 是否是需要两个参数的操作符
public bool IsTwoNumOperator(char op)
{
if (op == 'i') return false;
return true;
} public bool Contains(char x)
{
if (x == '(' || x == ')')
{
UnityEngine.Debug.LogError(x + "为中文字符,请改为英文字符");
} foreach (char[] arr in _signOperator)
{
foreach (char y in arr)
{
if (x == y)
{
return true;
}
}
}
return false;
} public ComplexNumber Compute(char op, ComplexNumber c1, ComplexNumber c2)
{
ComplexNumber result = null;
switch (op)
{
case '+': result = c1.ComplexAdd(c2); break;
case '-': result = c1.ComplexMinus(c2); break;
case '*': result = c1.ComplexMulti(c2); break;
case '/': result = c1.ComplexDivision(c2); break;
case '^': result = c1.ComplexPow(c2); break;
case 's': result = c1.ComplexMinimum(c2); break;
case 'b': result = c1.ComplexMaximum(c2); break;
case 'i': result = c2.ToFloorInt(); break;
}
return result;
}
}
}

仓促上传待整理。。。

C#利用栈实现字符串运算解析的更多相关文章

  1. 利用栈实现字符串中三种括号的匹配问题c++语言实现

    编写一个算法,检查一个程序中的花括号,方括号和圆括号是否配对,若能够全部配对则返回1,否则返回0. Head.h: #ifndef HEAD_H_INCLUDED #define HEAD_H_INC ...

  2. C++ 利用栈解决运算问题

    2017-06-27 19:19:18 第一步需要将中缀表达式转为后缀表达式.这步的转化可以说是本题的核心. 主要的转化手段是利用栈,有如下几个规则: 数字直接输出 "("直接进栈 ...

  3. buuoj [RoarCTF 2019]Easy Calc(利用PHP的字符串解析特性)

    web [RoarCTF 2019]Easy Calc(利用PHP的字符串解析特性) 先上源码 <?phperror_reporting(0);if(!isset($_GET['num'])){ ...

  4. python 利用栈实现复杂计算器

    #第五周的作业--多功能计算器#1.实现加减乘除及括号的优先级的解析,不能使用eval功能,print(eval(equation))#2.解析复杂的计算,与真实的计算器结果一致#用户输入 1 - 2 ...

  5. 三道题(关于虚表指针位置/合成64位ID/利用栈实现四则运算)

    第一题 C++标准中,虚表指针在类的内存结构位置没有规定,不同编译器的实现可能是不一样的.请实现一段代码,判断当前编译器把虚表指针放在类的内存结构的最前面还是最后面.  第二题 在游戏中所有物品的实例 ...

  6. 利用栈实现算术表达式求值(Java语言描述)

    利用栈实现算术表达式求值(Java语言描述) 算术表达式求值是栈的典型应用,自己写栈,实现Java栈算术表达式求值,涉及栈,编译原理方面的知识.声明:部分代码参考自茫茫大海的专栏. 链栈的实现: pa ...

  7. [Java]利用栈判断括号是否完整配对

    利用栈实现判断字符串中的括号是否都是配对的. 主要算法是依次读取字符串中的每一个字符,如果是左括号则将左括号压入栈中,如果是右括号则从栈中弹出最上面的字符,若两者不是同种括号或栈内已经没有字符就返回f ...

  8. Java开发笔记(三十八)利用正则表达式校验字符串

    前面多次提到了正则串.正则表达式,那么正则表达式究竟是符合什么定义的字符串呢?正则表达式是编程语言处理字符串格式的一种逻辑式子,它利用若干保留字符定义了形形色色的匹配规则,从而通过一个式子来覆盖满足了 ...

  9. Kotlin入门(31)JSON字符串的解析

    json是App进行网络通信最常见的数据交互格式,Android也自带了json格式的处理工具包org.json,该工具包主要提供了JSONObject(json对象)与JSONArray(json数 ...

随机推荐

  1. 【leetcode】328. Odd Even Linked List

    题目如下: Given a singly linked list, group all odd nodes together followed by the even nodes. Please no ...

  2. C/C++ clock()

    { clock_t start = clock(); for(int i = 0; i < 1000000; i++) { static int var = 0; var++; } clock_ ...

  3. java中设置http响应头控制浏览器禁止缓存当前文档内容

    response.setDateHeader("expries", -1); response.setHeader("Cache-Control", " ...

  4. CSS格式化---属性排序

    一.背景 与同事合作开发一个项目,后面修改 CSS 时,发现属性顺序跟我写的不一样 我从事开发前端时,导师是有给我大概指定了一定的书写规范 现在开发时,看到的 CSS 属性排序不一样,看起来有点难受( ...

  5. GitHub 万星推荐:黑客成长技术清单

    GitHub 万星推荐:黑客成长技术清单 导语:如果你需要一些安全入门引导,“Awesome Hacking”无疑是最佳选择之一. 最近两天,在reddit安全板块和Twitter上有个GitHub项 ...

  6. ebay上传图片的要求

    eBay's Picture Requirements Introduction to Pictures in Listings Pictures make an item more appealin ...

  7. TLS/SSL 协议 - ServerHello

    ServerHello ServerHello消息的意义是将服务器选择的连接参数传送回客户端.这个消息的结构与ClientHello类似,只是每个字段只包含一个选项. 服务器无需支持客户端支持的最佳版 ...

  8. Day 19:面向对象【类方法】静态属性/静态属性/类方法

    静态属性  @property  class Mom: gender = "woman" def __init__(self,name,weight): self.name = n ...

  9. 高效IO之Dex加密(三)

    更多Android高级架构进阶视频学习请点击:https://space.bilibili.com/474380680 apk加固原理之dex加密 原理其实不复杂,加固其实就是加密dex文件,防止de ...

  10. maven管理工具配置

    1.登录maven.apache.org,下载maven.,选择apache-maven-3.6.2-bin.zip,并解压到所需目录. 2.进行环境配置,计算机右击--属性---高级系统配置---环 ...