2

我目前正在使用反向波兰符号计算器。它功能齐全,但我遇到了文本输入问题,然后将用于计算值。如果引入类似的公式,程序就会中断( 8 5 + ) 6 * =。有没有办法简单地忽略输入值中显示的任何括号?此外,我的程序确实会根据每个数字之间的空格进行拆分,但是如果我要在操作数或括号之间添加空格,它也会中断:(8 5 +)6 * =。如果它是无效的公式12 + =(缺少数字),我想忽略它们并在输出文本框中显示一条错误消息。

旁注:每个公式都由结尾触发=

代码

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);
        }
    }
}

在此处输入图像描述

4

3 回答 3

1

首先,做类似的事情

rpnValue = rpnValue.Replace(" ", "").Replace("(","").Replace(")","");

正如 Sam 对这个问题的回答所建议的那样,需要对整个算法进行重大重写。问题在于消除空格的 Replace(" ", "") 部分。但是,该算法依赖于拆分来标记输入。如果您在拆分之前消除空格,而不是获得一个数字和运算符数组,您将获得一个现有代码无法处理的单个字符串。更糟糕的是 "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");
        }
    }
于 2012-11-30T17:54:16.907 回答
0

如何从字符串中删除不重要的字符:

string str = inStr.Replace(" ", "").Replace("(","").Replace("etc.","");
于 2012-11-30T17:25:54.133 回答
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();
于 2012-11-30T18:50:01.203 回答