我目前正在使用反向抛光记谱计算器。它功能齐全,但我遇到了文本输入问题,然后将用于计算值。如果引入类似( 8 5 + ) 6 * =
的公式,程序会中断。有没有办法简单地忽略输入值中出现的任何括号?此外,我的程序会根据每个数字之间的空格进行拆分,但如果我要在操作数或括号之间添加空格,它也会断开:(8 5 +)6 * =
。如果它是一个无效的公式12 + =
(缺少一个数字),我想忽略它们,只在输出textBox中显示一条错误信息。
旁注:每个公式都由结尾=
触发。
代码
namespace rpncalc
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string inputValue = "";
private void RPNCalc(string rpnValue)
{
Stack<int> stackCreated = new Stack<int>();
stackCreated.Clear();
string[] inputArray = rpnValue.Split();
int end = inputArray.Length - 1;
int numInput;
int i = 0;
do
{
if ("=+-*/%^".IndexOf(inputArray[i]) == -1)
{
try
{
numInput = Convert.ToInt32(inputArray[i]);
stackCreated.Push(numInput);
}
catch
{
MessageBox.Show("Please check the input");
}
}
else if (inputArray[i]== "+")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 + store1);
}
catch
{
}
}
else if (inputArray[i]== "-")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 - store1);
}
catch
{
}
}
else if (inputArray[i]== "%")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 % store1);
}
catch
{
}
}
else if (inputArray[i]== "*")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 * store1);
}
catch
{
}
}
else if (inputArray[i]== "/")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push(store2 / store1);
}
catch
{
}
}
else if (inputArray[i] == "^")
{
try
{
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
stackCreated.Push((int)Math.Pow(store1, store2));
}
catch
{
}
}
}
while(i++ < end && inputArray[i]!= "=" && stackCreated.Count != 0);
string result = inputValue + " " + stackCreated.Pop().ToString() + Environment.NewLine;
TxtOutputBox.AppendText(result);
TxtInputBox.Clear();
}
private void TxtOutputBox_TextChanged(object sender, EventArgs e)
{
}
private void Btn_Calc_Click(object sender, EventArgs e)
{
inputValue = TxtInputBox.Text + " ";
RPNCalc(inputValue);
}
}
}
答案 0 :(得分:1)
首先,做一些像
这样的事情rpnValue = rpnValue.Replace(" ", "").Replace("(","").Replace(")","");
正如Sam对这个问题的回答所建议的那样,需要对整个算法进行重大改写。问题在于替换(“”,“”)部分,它消除了空格。但是,该算法依赖于Split来标记输入。如果在拆分之前消除空格,而不是获取数字和运算符数组,则将获得现有代码无法处理的单个字符串。更糟糕的是,“12 3 * =”和“1 23 * =”将被转换为“123 * =”!!!
为避免进行大的更改,请按如下方式更改代码:
在分割前插入以下代码:
rpnValue = rpnValue.Replace("("," ").Replace(")"," ");
这可确保根据要求忽略括号,但使(8 5 +)6 * =工作。
然后再添加以下内容:
if (" \t\n\r".IndexOf(inputArray[i]) != -1) {
continue;
} else if ("=+-*/%^".IndexOf(inputArray[i]) == -1)
...
循环结束时的代码也需要更改:
while (i++ < end && inputArray[i] != "=");
if(stackCreated.Count != 1)
MessageBox.Show("Please check the input");
希望有所帮助: - )
---------------------------答案正确到此结束--------------- -------------------
其他建议: 这个问题没有涵盖错误报告的问题,但我还注意到了其他一些问题:堆栈上的操作被try catch语句包围,catch部分没有任何反应。这样,格式错误的输入没有被适当地标记。我建议删除那些try catch语句并在函数体内放置一个。
一些有趣的事情:我的目的是回答所提出的非常具体的问题,但是由于看到LB的漂亮代码已经发布在这里,我更新了答案,包括RPNCalc的另一种定义,这种定义尽可能简洁但更接近你的原始方法不依赖于正则表达式(除了要计算的表达式不以=
结尾)。
private void RPNCalc(string rpnValue)
{
Stack<int> stackCreated = new Stack<int>();
try {
var tokens = rpnValue.Replace("(", " ").Replace(")", " ")
.Split().Where(s => !String.IsNullOrWhiteSpace(s));
foreach (var t in tokens) {
try {
stackCreated.Push(Convert.ToInt32(t));
} catch {
int store1 = stackCreated.Pop();
int store2 = stackCreated.Pop();
switch(t) {
case "+": store2 += store1; break;
case "-": store2 -= store1; break;
case "*": store2 *= store1; break;
case "/": store2 /= store1; break;
case "%": store2 %= store1; break;
case "^": store2 = (int) Math.Pow(store2, store1); break; /* was (int) Math.Pow(store1, store2); in the original code*/
default: throw new Exception();
}
stackCreated.Push(store2);
}
}
if(stackCreated.Count != 1)
MessageBox.Show("Please check the input");
else
textBox1.Text = stackCreated.Pop().ToString();
} catch {
MessageBox.Show("Please check the input");
}
}
答案 1 :(得分:0)
如何从字符串中删除不重要的字符:
string str = inStr.Replace(" ", "").Replace("(","").Replace("etc.","");
答案 2 :(得分:0)
只是一个想法;
string input = @"( 8 5 + ) 6 *";
var tokens = Regex.Matches(input, @"(?<num>[0-9]+)|(?<op>[\+\-\*\/\^\%])").Cast<Match>()
.Select(m=> String.IsNullOrEmpty(m.Groups["num"].Value)
? new Tuple<string,string>("op",m.Groups["op"].Value)
: new Tuple<string,string>("num",m.Groups["num"].Value))
.ToList();
var fxns = new Dictionary<string, Func<int, int, int>>()
{
{"+",(i,j)=>j+i },
{"-",(i,j)=>j-i },
{"*",(i,j)=>j*i },
{"/",(i,j)=>j/i },
{"%",(i,j)=>j&i },
{"^",(i,j)=>(int)Math.Pow(j,i) },
};
Stack<int> stack = new Stack<int>();
foreach (var token in tokens)
{
if (token.Item1 == "num")
stack.Push(int.Parse(token.Item2));
else
stack.Push(fxns[token.Item2](stack.Pop(), stack.Pop()));
}
int finalResult = stack.Pop();