我正在设计关系计算器。
如果用户提供了类似-3.33 + 44 * 456 / 2.2-3 + 4 ....
的字符串我想将它存储在字符串数组中
-3.33
44
*
456
/
2.2
-3
4
...... (即*,/,+ ve值,-ve值单独并按顺序排列成字符串数组)
这是我写的代码:
string a = "-3.33+44*456/2.2-3";
string[] ip = new string[25];
int k = 0;
for (int i = 0; i < a.Length; i++)
{
if (a.Substring(i, 1) == "+" || a.Substring(i, 1) == "-" || a.Substring(i, 1) == "*" || a.Substring(i, 1) == "/" || a.Substring(i, 1) == "^")
{
for (int j = i + 1; j < a.Length; j++)
{
if (a.Substring(j, 1) == "+" || a.Substring(j, 1) == "-" || a.Substring(j, 1) == "*" || a.Substring(j, 1) == "/" || a.Substring(j, 1) == "^")
{
if (a.Substring(i, 1) == "+" || a.Substring(i, 1) == "-")
{
ip[k] = a.Substring(i, j-i);
k++;
}
else
{
ip[k] = a.Substring(i, 1);
k++;
ip[k] = a.Substring(i + 1, (j -i)-1);
k++;
}
i = j;
break;
}
}
}
}
但它不能正常工作: 它只在数组中存储一个元素。
从最近两天开始,我正在刹车。 请帮我。 谢谢。
答案 0 :(得分:14)
你从一个完全错误的结局接近问题。你需要的是一个tokenizer和一个解析器。您可以手动编写,也可以使用许多所谓的“编译器编译器”。
您还可以尝试Irony:
namespace Irony.Samples {
// This grammar describes programs that consist of simple expressions and assignments
// for ex:
// x = 3
// y = -x + 5
// the result of calculation is the result of last expression or assignment.
// Irony's default runtime provides expression evaluation.
// supports inc/dec operators (++,--), both prefix and postfix,
// and combined assignment operators like +=, -=, etc.
[Language("ExpressionEvaluator", "1.0", "Multi-line expression evaluator")]
public class ExpressionEvaluatorGrammar : Irony.Parsing.Grammar {
public ExpressionEvaluatorGrammar() {
// 1. Terminals
var number = new NumberLiteral("number");
//Let's allow big integers (with unlimited number of digits):
number.DefaultIntTypes = new TypeCode[] { TypeCode.Int32, TypeCode.Int64, NumberLiteral.TypeCodeBigInt };
var identifier = new IdentifierTerminal("identifier");
var comment = new CommentTerminal("comment", "#", "\n", "\r");
//comment must to be added to NonGrammarTerminals list; it is not used directly in grammar rules,
// so we add it to this list to let Scanner know that it is also a valid terminal.
base.NonGrammarTerminals.Add(comment);
// 2. Non-terminals
var Expr = new NonTerminal("Expr");
var Term = new NonTerminal("Term");
var BinExpr = new NonTerminal("BinExpr", typeof(BinExprNode));
var ParExpr = new NonTerminal("ParExpr");
var UnExpr = new NonTerminal("UnExpr", typeof(UnExprNode));
var UnOp = new NonTerminal("UnOp");
var BinOp = new NonTerminal("BinOp", "operator");
var PostFixExpr = new NonTerminal("PostFixExpr", typeof(UnExprNode));
var PostFixOp = new NonTerminal("PostFixOp");
var AssignmentStmt = new NonTerminal("AssignmentStmt", typeof(AssigmentNode));
var AssignmentOp = new NonTerminal("AssignmentOp", "assignment operator");
var Statement = new NonTerminal("Statement");
var ProgramLine = new NonTerminal("ProgramLine");
var Program = new NonTerminal("Program", typeof(StatementListNode));
// 3. BNF rules
Expr.Rule = Term | UnExpr | BinExpr | PostFixExpr;
Term.Rule = number | ParExpr | identifier;
ParExpr.Rule = "(" + Expr + ")";
UnExpr.Rule = UnOp + Term;
UnOp.Rule = ToTerm("+") | "-" | "++" | "--";
BinExpr.Rule = Expr + BinOp + Expr;
BinOp.Rule = ToTerm("+") | "-" | "*" | "/" | "**";
PostFixExpr.Rule = Term + PostFixOp;
PostFixOp.Rule = ToTerm("++") | "--";
AssignmentStmt.Rule = identifier + AssignmentOp + Expr;
AssignmentOp.Rule = ToTerm("=") | "+=" | "-=" | "*=" | "/=";
Statement.Rule = AssignmentStmt | Expr | Empty;
ProgramLine.Rule = Statement + NewLine;
Program.Rule = MakeStarRule(Program, ProgramLine);
this.Root = Program; // Set grammar root
// 4. Operators precedence
RegisterOperators(1, "+", "-");
RegisterOperators(2, "*", "/");
RegisterOperators(3, Associativity.Right, "**");
// 5. Punctuation and transient terms
RegisterPunctuation("(", ")");
RegisterBracePair("(", ")");
MarkTransient(Term, Expr, Statement, BinOp, UnOp, PostFixOp, AssignmentOp, ProgramLine, ParExpr);
//automatically add NewLine before EOF so that our BNF rules work correctly when there's no final line break in source
this.LanguageFlags = LanguageFlags.CreateAst | LanguageFlags.NewLineBeforeEOF | LanguageFlags.CanRunSample;
}
}
}//namespace
答案 1 :(得分:2)
这是我对这个问题的看法,它适用于测试用例,并且易于扩展/更改:
{
string InputString = "-3.33+44*456/2.2-3+4";
string[] RetArray = InputString.Replace("-", " -").Replace("+", " +").Replace("*", " * ").Replace("/", " / ").Split(new Char[] { ' ' });
}
只有一行。
修改:修正并验证。
答案 2 :(得分:0)
如果您只是尝试执行存储在字符串中的任意数学表达式,那么您一定要查看dotMath - Brief how-to。
希望这有帮助!如果我不明白你的问题而且你正在尝试做一些更复杂的事情,这不会解决,请告诉我!
答案 3 :(得分:0)
不是为你重写代码,我只是指出你有几个错误(见评论):
string a = "-3.33+44*456/2.2-3";
string[] ip = new string[25];
int k = 0;
for (int i = 0; i < a.Length; i++)
{
if (a.Substring(i, 1) == "+" || a.Substring(i, 1) == "-" || a.Substring(i, 1) == "*" || a.Substring(i, 1) == "/" || a.Substring(i, 1) == "^")
{
for (int j = i + 1; j <= a.Length; j++) // a.Length has to be included so the last element gets added
{
// allow the end of the string as an option
if (j == a.Length || a.Substring(j, 1) == "+" || a.Substring(j, 1) == "-" || a.Substring(j, 1) == "*" || a.Substring(j, 1) == "/" || a.Substring(j, 1) == "^")
{
if (a.Substring(i, 1) == "+" || a.Substring(i, 1) == "-")
{
ip[k] = a.Substring(i, j-i);
k++;
}
else
{
ip[k] = a.Substring(i, 1);
k++;
ip[k] = a.Substring(i + 1, (j -i)-1);
k++;
}
i = j - 1; // i gets incremented in the for loop, so subract 1 here
break;
}
}
}
}