反向波兰表示法:忽略输入公式中的括号和空格

时间:2012-11-30 17:22:44

标签: c#

我目前正在使用反向抛光记谱计算器。它功能齐全,但我遇到了文本输入问题,然后将用于计算值。如果引入类似( 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);
        }
    }
}

enter image description here

3 个答案:

答案 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();