附上参考文章链接: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. leetcood学习笔记-28-KMP*

    题目: 第一次提交: class Solution: def strStr(self, haystack: str, needle: str) -> int: if not len(needle ...

  2. openFrameworks Download

    { https://openframeworks.cc/zh_cn//download/ } 0.10.1 是最新发布的版本. 这个版本是修改了一些BUG的小版本,与版本 0.10.1100%兼容而且 ...

  3. Android中TextView不获取焦点可以实现跑马灯的效果

    之前在网上找了很多关于TextView的跑马灯效果实现的例子,实现起来都存在一些问题,例如一种是完全重画一个跑马灯,还有就是只设置TextView的相关属性使其具有跑马灯的效果,总的来说这两种方法都是 ...

  4. mysql8.*忘记密码

    1.关闭mysql服务 2.打开cmd窗口,找到安装目录下的bin然后复制命令 mysqld --console --skip-grant-tables --shared-memory 3.再打开一个 ...

  5. delphi与javascript互通

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  6. This inspection warns about local variables referenced before assignment.

    关于 local variable 'has' referenced before assignment 问题 今天在django开发时,访问页面总是出现错误提示“local variable 'ha ...

  7. docker swarm集群挂载宿主机目录

    创建DOCKER集群,挂载宿主机目录src:宿主机目录,dst:容器目录 docker service create --name testrd --detach=false --mount type ...

  8. Valgrind学习

    Valgrind与其他DBI(Pin, DynamoRIO)的区别 我们需要了解DBI的几个 D&R Disassemble-and-Resynthesise 反汇编后重新组装 Valgrin ...

  9. python:Django 简介。

    Django是基Python的重要WEB框架. 1.安装Django Web框架 安装  pip 安装 在命令行模式 执行  [pip install django == 2.0]或者 [pip in ...

  10. 启动多个mysql实例

    如果使用./support-files/mysql.server 文件启动,则默认读取/etc/my.cnf 配置文件,这种方式有时候启动不了 会提示报错 :The server quit witho ...