C# 转换或计算包含括号的公式
我需要找到一种方法来转换经过处理的公式(仅使用数字、字母和括号) 例如,对于此输入:“C# 转换或计算包含括号的公式,c#,parentheses,C#,Parentheses,我需要找到一种方法来转换经过处理的公式(仅使用数字、字母和括号) 例如,对于此输入:“5(2(a)sz)”输出应为:“aaszaaszaasz” 我试着这样做: string AddChainDeleteBracks(int open, int close, string input) { string to="",from=""; //get the local chain multipule the number in input[open-1]
5(2(a)sz)
”输出应为:“aaszaaszaasz
”
我试着这样做:
string AddChainDeleteBracks(int open, int close, string input)
{
string to="",from="";
//get the local chain multipule the number in input[open-1]
//the number of the times the chain should be multiplied
for (int i = input[open - 1]; i > 0; i--)
{
//the content
for (int m = open + 1; m < close; m++)
{
to = to + input[m];
}
}
//get the chain i want to replace with "to"
for (int j = open - 1; j <= close; j++)
{
from = from + input[j];
}
String output = input.Replace(from, to);
return output;
}
string AddChainDeleteBracks(int-open、int-close、string-input)
{
字符串to=“”,from=“”;
//获取输入[open-1]中的数字的本地链
//链应该相乘的次数
对于(int i=输入[open-1];i>0;i--)
{
//内容
对于(int m=open+1;m 对于(int j=open-1;j您可以将左括号位置以及与该括号关联的数字存储在堆栈中(例如,后进先出);然后当遇到第一个时(即:下一个)关闭圆括号,弹出堆栈顶部:这将为您提供需要重复的圆括号(目前为止最内部)之间的子字符串的开始和结束位置。然后用重复的字符串替换原始字符串的这部分(包括重复编号)。继续,直到到达字符串的结尾
注意事项:
- 进行替换时,需要更新当前位置,使其现在指向新(修改)字符串中重复字符串的末尾
- 根据是否允许0重复,您可能需要处理一个空的重复——这是一个空字符串
- 当到达字符串末尾时,堆栈应为空(所有左括号都与右括号匹配)
堆栈可能在字符串的中间变空了——如果你遇到一个结束括号,输入字符串是畸形的
- 可能有一种方法可以避开开头/结尾括号,这样它们就不会被视为重复模式的一部分——这取决于您的需求
由于表达式的语法是递归的,我建议使用递归方法
首先将表达式拆分为单个标记。我使用Regex
来执行此操作并删除空条目
示例:“5(2(a)sz)”
分为“5”、“2”、“2”、“a”、“sz”、“sz”、“s”
使用枚举器可以逐个获取令牌。tokens.MoveNext()
获取下一个令牌。tokens.Current
是当前令牌
public string ConvertExpression(string expression)
{
IEnumerator<string> tokens = Regex.Split(expression, @"\b")
.Where(s => s != "")
.GetEnumerator();
if (tokens.MoveNext()) {
return Parse(tokens);
}
return "";
}
公共字符串表达式(字符串表达式)
{
IEnumerator标记=Regex.Split(表达式@“\b”)
。其中(s=>s!=“”)
.GetEnumerator();
if(tokens.MoveNext()){
返回解析(令牌);
}
返回“”;
}
这里的主要工作是以递归的方式完成的
private string Parse(IEnumerator<string> tokens)
{
string s = "";
while (tokens.Current != ")") {
int n;
if (tokens.Current == "(") {
if (tokens.MoveNext()) {
s += Parse(tokens);
if (tokens.Current == ")") {
tokens.MoveNext();
return s;
}
}
} else if (Int32.TryParse(tokens.Current, out n)) {
if (tokens.MoveNext()) {
string subExpr = Parse(tokens);
var sb = new StringBuilder();
for (int i = 0; i < n; i++) {
sb.Append(subExpr);
}
s += sb.ToString();
}
} else {
s += tokens.Current;
if (!tokens.MoveNext())
return s;
}
}
return s;
}
私有字符串解析(IEnumerator令牌)
{
字符串s=“”;
while(tokens.Current!=“”){
int n;
如果(tokens.Current==“(”){
if(tokens.MoveNext()){
s+=解析(令牌);
if(tokens.Current==“”){
tokens.MoveNext();
返回s;
}
}
}else if(Int32.TryParse(tokens.Current,out n)){
if(tokens.MoveNext()){
string subExpr=Parse(令牌);
var sb=新的StringBuilder();
对于(int i=0;i
这是我的第二个答案。我的第一个答案是快速回答。在这里,我尝试通过逐个操作来创建解析器
为了转换表达式,您需要对其进行解析。这意味着您必须分析其语法。在分析其语法的同时,您还可以生成输出
1首先要做的是定义所有有效表达式的语法。
在这里,我使用EBNF来实现它。EBNF很简单
{
和}
包含重复(可能为零)。
[
和]
包含一个可选部分。
|
分离备选方案
有关EBNF的更多详细信息,请参阅WikMedia上的。(此处使用的EBNF变体删除了连接运算符“,”)
EBNF中的语法
Expression = { Term }.
Term = [ Number ] Factor.
Factor = Text | "(" Expression ")" | Term.
以下字段用于保存令牌信息和布尔值\u error
,用于告知解析过程中是否发生错误
private IEnumerator<Match> _matches;
TokenType _tokenType;
string _text;
int _number;
bool _error;
3句法和语义分析
现在,我们已经具备了执行实际解析和表达式转换所需的一切。
EBNF到C#代码的转换是直接的,语法中的重复被转换成C#循环语句。
如果将
语句和备选项转换为开关语句,则选项将转换为
// Expression = { Term }.
private string Expression()
{
string s = "";
do {
s += Term();
} while (_tokenType != TokenType.RPar && _tokenType != TokenType.None);
return s;
}
// Term = [ Number ] Factor.
private string Term()
{
int n;
if (_tokenType == TokenType.Number) {
n = _number;
if (!GetToken()) {
_error = true;
return " Error: Factor expected.";
}
string factor = Factor();
if (_error) {
return factor;
}
var sb = new StringBuilder(n * factor.Length);
for (int i = 0; i < n; i++) {
sb.Append(factor);
}
return sb.ToString();
}
return Factor();
}
// Factor = Text | "(" Expression ")" | Term.
private string Factor()
{
switch (_tokenType) {
case TokenType.None:
_error = true;
return " Error: Unexpected end of Expression.";
case TokenType.LPar:
if (GetToken()) {
string s = Expression();
if (_tokenType == TokenType.RPar) {
GetToken();
return s;
} else {
_error = true;
return s + " Error ')' expected.";
}
} else {
_error = true;
return " Error: Unexpected end of Expression.";
}
case TokenType.RPar:
_error = true;
GetToken();
return " Error: Unexpected ')'.";
case TokenType.Text:
string t = _text;
GetToken();
return t;
default:
return Term();
}
}
//表达式={Term}。
私有字符串表达式()
{
字符串s=“”;
做{
s+=术语();
}而(_-tokenType!=tokenType.RPar&&u-tokenType!=tokenType.None);
返回s;
}
//术语=[Number]因子。
私有字符串项()
{
int n;
if(_tokenType==tokenType.Number){
n=_数;
如果(!GetToken()){
_错误=真;
返回“错误:预期的因素。”;
}
字符串因子=因子();
如果(_错误){
回报系数;
}
var sb=新的StringBuilder(n*系数长度);
对于(int i=0;iprivate IEnumerator<Match> _matches;
TokenType _tokenType;
string _text;
int _number;
bool _error;
public string ConvertExpression(string expression)
{
_matches = Regex.Matches(expression, @"\d+|\(|\)|[a-zA-Z]+")
.Cast<Match>()
.GetEnumerator();
_error = false;
return GetToken() ? Expression() : "";
}
private bool GetToken()
{
_number = 0;
_tokenType = TokenType.None;
_text = null;
if (_error || !_matches.MoveNext())
return false;
_text = _matches.Current.Value;
switch (_text[0]) {
case '(':
_tokenType = TokenType.LPar;
break;
case ')':
_tokenType = TokenType.RPar;
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
_tokenType = TokenType.Number;
_number = Int32.Parse(_text);
break;
default:
_tokenType = TokenType.Text;
break;
}
return true;
}
// Expression = { Term }.
private string Expression()
{
string s = "";
do {
s += Term();
} while (_tokenType != TokenType.RPar && _tokenType != TokenType.None);
return s;
}
// Term = [ Number ] Factor.
private string Term()
{
int n;
if (_tokenType == TokenType.Number) {
n = _number;
if (!GetToken()) {
_error = true;
return " Error: Factor expected.";
}
string factor = Factor();
if (_error) {
return factor;
}
var sb = new StringBuilder(n * factor.Length);
for (int i = 0; i < n; i++) {
sb.Append(factor);
}
return sb.ToString();
}
return Factor();
}
// Factor = Text | "(" Expression ")" | Term.
private string Factor()
{
switch (_tokenType) {
case TokenType.None:
_error = true;
return " Error: Unexpected end of Expression.";
case TokenType.LPar:
if (GetToken()) {
string s = Expression();
if (_tokenType == TokenType.RPar) {
GetToken();
return s;
} else {
_error = true;
return s + " Error ')' expected.";
}
} else {
_error = true;
return " Error: Unexpected end of Expression.";
}
case TokenType.RPar:
_error = true;
GetToken();
return " Error: Unexpected ')'.";
case TokenType.Text:
string t = _text;
GetToken();
return t;
default:
return Term();
}
}