弄了很久中缀表达式转前缀和后缀表达式的概念,后缀表达式也称为逆波兰式表达式,前缀表达式称为波兰式表达式。用C#仿照简单实现了他们之间的转换以及求值。不要喷我,因为概念都是一样的,不要以为是抄袭,哈哈。
程序中有很多不足的地方(比如不支持大于10的整数,因为我直接使用String.ToCharArray()肯定不妥),希望大家一起改进,谢谢。以下贴出全部代码:using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;namespace ReversePolishNotation
{
    class Program
    {
        static void Main(string[] args)
        {
            //中缀表达式转化为后缀表达式
            Trans trans = new Trans();
            Eval eval = new Eval();
            string s = Console.ReadLine().Replace(" ",string.Empty);
            Console.WriteLine("Input string: "+s);
            string translated = trans.TranslateRPN(s);
            Console.WriteLine("RPN string: "+translated);
            double res = eval.EvaluateRPN(translated);
            Console.WriteLine("Valud: "+res.ToString("f2"));            //中缀表达式转化为前缀表达式
            translated = trans.TranslatePN(s);
            Console.WriteLine("PN string: " + translated);
            res = eval.EvaluatePN(translated);
            Console.WriteLine("Valud: " + res.ToString("f2"));
        }
    }    //Eval: Evaluate RPN string
    //single digits, treated as doubles, and operators
    class Eval
    {
        Stack<double> stack = null;        public Eval()
        {
            stack = new Stack<double>();
        }        public double EvaluateRPN(String s)
        {
            double op1 = 0.0, op2 = 0.0, res = 0.0;
            char[] array = s.ToCharArray();
            for (int i = 0; i < array.Length; i++)
            {
                char ch = array[i];
                if (Char.IsDigit(ch))
                {
                    stack.Push((double)(ch - '0')); //Push digit as double
                }
                else //Char is a operator
                {
                    if (stack.Count == 0)
                        Error(1);
                    else
                        op2 = stack.Pop();                    if (stack.Count == 0)
                        Error(2);
                    else
                        op1 = stack.Pop();                    res = Evaluate(ch, op1, op2);
                    stack.Push(res);
                }
            }            if (stack.Count == 0)
                Error(4);
            else
                res = stack.Pop();            if (stack.Count != 0)
                Error(5);            return res;
        }        public double EvaluatePN(String s)
        {
            double op1 = 0.0, op2 = 0.0, res = 0.0;
            char[] array = s.ToCharArray();
            for (int i = array.Length-1; i >=0; i--)
            {
                char ch = array[i];
                if (Char.IsDigit(ch))
                {
                    stack.Push((double)(ch - '0')); //Push digit as double
                }
                else //Char is a operator
                {
                    if (stack.Count == 0)
                        Error(1);
                    else
                        op2 = stack.Pop();                    if (stack.Count == 0)
                        Error(2);
                    else
                        op1 = stack.Pop();                    res = Evaluate(ch, op1, op2);
                    stack.Push(res);
                }
            }            if (stack.Count == 0)
                Error(4);
            else
                res = stack.Pop();            if (stack.Count != 0)
                Error(5);            return res;
        }        private double Evaluate(char ch, double op1, double op2)
        {
            switch (ch)
            {
                case '+': return op1 + op2;
                case '-': return op1 - op2;
                case '*': return op1 * op2;
                case '/': return op1 / op2;
                case '^': return Math.Pow(op1, op2);
                default: Error(3); return 0;
            }
        }        private void Error(int num)
        {
            Console.WriteLine("Error number: " + num);
            Environment.Exit(num);
        }
    }

解决方案 »

  1.   


        class Trans
        {
            Stack<char> stack = null;
            Stack<char> stackInAndOut = null;        public Trans()
            {
                stack = new Stack<char>();
                stackInAndOut = new Stack<char>();
            }        //Trans: translate input arith expr to RPN string
            //Rules for each input char (go on to next input char unless otherwise stated)
            //Fetch next char, call it ch
            //1. If ch is an operand, move it to output
            //From now on ch is an operator or '(' or ')'.
            //2. If stack is empty, add ch to stack
            //3. If ch is '(', add ch to stack
            //From now on, stack is not empt. Use top for its top char
            //4. If ch is ')', remove chars from stack and output down to '(' on stack, whick is thrown away.
            //5. If top is '(', add ch to stack.
            //From now on, both ch and top are regular operators
            //6. If prec(ch)>prec(top), add ch to stack.
            //7. If prec(ch)<prec(top), move top to output, and DO NOT MOVE ON TO NEXT INPUT CHAR.
            //8. if prec(ch)==prec(top) and left-to-right associativity, move top to output, and DO NOT MOVE ON TO NEXT INPUT CHAR.
            //9. if prec(ch)==prec(top) and right-to-left associativity, add top to stack.
            //10. At end, move everything on stack to output.
            public string TranslateRPN(string s)
            {
                double op1 = 0.0, op2 = 0.0, op3 = 0.0;
                string output = ""; //Output string
                char ch, top;
                int i = 0; //Index in input string
                char[] arrary = s.ToCharArray();            while (i < arrary.Length)
                {
                    bool moveOn = true;
                    ch = arrary[i]; //Before rule 1
                    if (Char.IsDigit(ch)) //Rule 1: digit to output
                        output += ch;
                    else if (stack.Count == 0 || ch == '(') //Rule 2 and 3
                        stack.Push(ch);
                    else //Stack isn't empty
                    {
                        top = stack.Peek(); //Before rule 4
                        if (ch == ')') //Rule 4
                            while (true)
                            {
                                if ((top = stack.Pop()) == '(')
                                    break; //normal termination
                                output += top;
                                if (stack.Count == 0)
                                    Error(1);
                            }
                        else if (top == '(') //Rule 5
                            stack.Push(ch);
                        else if (Prec(ch) > Prec(top) || (Prec(ch) == Prec(top) && Assoc(ch) == 'r')) //Rule 6 and 9
                            stack.Push(ch);
                        else if (Prec(ch) < Prec(top) || (Prec(ch) == Prec(top) && Assoc(ch) == 'l')) //Rule 7 and 8
                        {
                            output += top; //move top to output
                            stack.Pop();
                            moveOn = false;
                        }
                    }                if (moveOn)
                        i++;
                }            while (stack.Count != 0) //Rule 10
                    output += stack.Pop();            return output;
            }        //Trans: Translate the input arith expr to prev string
            //Reverse the input string
            //Rules for each input char (go on to next input char unless otherwise stated)
            //Fetch next char, call it ch
            //1. If ch is an operand, move it to output
            //From now on ch is an operator or '(' or ')'.
            //2. If stack is empty, add ch to stack
            //3. If ch is ')', add ch to stack
            //From now on, stack is not empt. Use top for its top char
            //4. If ch is '(', remove chars from stack and output down to ')' on stack, whick is thrown away.
            //5. If top is ')', add ch to stack.
            //From now on, both ch and top are regular operators
            //6. If prec(ch)>prec(top), add ch to stack.
            //7. If prec(ch)<prec(top), move top to output, and DO NOT MOVE ON TO NEXT INPUT CHAR.
            //8. if prec(ch)==prec(top) and left-to-right associativity, move top to output, and DO NOT MOVE ON TO NEXT INPUT CHAR.
            //9. if prec(ch)==prec(top) and right-to-left associativity, add top to stack.
            //10. At end, move everything on stack to output.
            //11. Reverse the output string
            public string TranslatePN(string s)
            {
                double op1 = 0.0, op2 = 0.0, op3 = 0.0;
                string output = ""; //Output string
                char ch, top;
                //int i = 0; //Index in input string
                char[] arrary = s.ToCharArray();            for (int j = 0; j < arrary.Length; j++)
                {
                    stackInAndOut.Push(arrary[j]);
                }            while (stackInAndOut.Count!=0)
                {
                    bool moveOn = true;
                    ch = stackInAndOut.Peek();
                    if (Char.IsDigit(ch))  //Rule 1
                        output += ch;
                    else if (stack.Count == 0 || ch == ')')  //Rule 2 and 3
                        stack.Push(ch);
                    else  //Stack is not empty
                    {
                        top = stack.Peek();
                        if (ch == '(')  //Before rule 4
                            while (true)
                            {
                                if ((top = stack.Pop()) == ')')
                                    break;
                                output += top;
                                if (stack.Count == 0)
                                    Error(1);
                            }
                        else if (top == ')')  //Rule 5
                            stack.Push(ch);
                        else if (Prec(ch) > Prec(top) || (Prec(ch) == Prec(top) && Assoc(ch) == 'r')) //Rule 6 and 9
                            stack.Push(ch);
                        else if (Prec(ch) < Prec(top) || (Prec(ch) == Prec(top) && Assoc(ch) == 'l')) //Rule 7 and 8
                        {
                            output += top; //move top to output
                            stack.Pop();
                            moveOn = false;
                        }
                    }                if (moveOn)
                        stackInAndOut.Pop();
                }            while (stack.Count != 0) //Rule 10
                    output += stack.Pop();            if (stackInAndOut.Count != 0)
                    Error(1);
                char[] chars = output.ToCharArray();
                for (int j = 0; j < chars.Length; j++)
                {
                    stackInAndOut.Push(chars[j]);
                }            output = "";
                while (stackInAndOut.Count != 0)
                    output += stackInAndOut.Pop();            return output;
            }        private void Error(int num)
            {
                Console.WriteLine("Error number: " + num);
                Environment.Exit(num);
            }        //prec: return int precedence of operators
            private int Prec(char ch)
            {
                switch (ch)
                {
                    case '+':
                    case '-':
                        return 1;
                    case '*':
                    case '/':
                        return 2;
                    case '^':
                        return 3;
                    default:
                        return -1;
                }
            }        //assoc: return 'l' for left-to-right, and 'r' for right-to-left
            private char Assoc(char ch)
            {
                switch (ch)
                {
                    case '+':
                    case '-':
                    case '*':
                    case '/':
                        return 'l';
                    case '^':
                        return 'r';
                    default:
                        return '?';
                }
            }
        }
    }