65.9K
CodeProject is changing. Read more.
Home

Converting InFix to PostFix using C#

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.36/5 (9 votes)

Apr 21, 2012

CPOL
viewsIcon

74278

How to convert infix to postfix using c# in simple expressions. But the base is not defferent for complicated expressions.

Introduction

Most of compilers use PostFix to generat native code. For more information about PostFix, refer here.

I want to talk about a simple code in C# to preception it.

Using the code

The program is under Console. The operands have to be one digit numbers in this program. Here the main code:

static void Main(string[] args)
{
   string inFix, postFix = string.Empty;
   while (true)
   {
      Console.Write("Enter InFix Expression: ");
      inFix = Console.ReadLine().Replace(" ", string.Empty);
      if (IsValid(inFix))//Validates InFix Expression
      {
         Console.WriteLine("\nPostFix: {0}",ConvertToPostFix(inFix));
         break;
      }
   Console.WriteLine("\nNot a valid Epression!\n");
   }
   Console.ReadKey();
}

All right, I used some methods and wanted to declare them.

Declaring ConvertToPostFix:

private static string ConvertToPostFix(string inFix)
{
   StringBuilder postFix = new StringBuilder();
   char arrival;
   Stack<char> oprerator = new Stack<char>();//Creates a new Stack
   foreach (char c in inFix.ToCharArray())//Iterates characters in inFix
   {
      if (Char.IsNumber(c))
         postFix.Append(c);
      else if (c == '(')
         oprerator.Push(c);
      else if (c == ')')//Removes all previous elements from Stack and puts them in 
                        //front of PostFix.  
      {
         arrival = oprerator.Pop();
         while (arrival != '(')
         {
            postFix.Append(arrival);
            arrival = oprerator.Pop();
         }
      }
      else
      {
         if (oprerator.Count != 0 && Predecessor(oprerator.Peek(), c))//If find an operator
         {
            arrival = oprerator.Pop();
            while (Predecessor(arrival, c))
            {
               postFix.Append(arrival);

               if (oprerator.Count == 0)
                  break;

               arrival = oprerator.Pop();
            }
            oprerator.Push(c);
         }
         else
            oprerator.Push(c);//If Stack is empty or the operator has precedence 
      }
   }
   while (oprerator.Count > 0)
   {
      arrival = oprerator.Pop();
      postFix.Append(arrival);
   }
   return postFix.ToString();
}

In this code if user enters 12+3-55+c, it will raise error for 12 and c. Because it's a simple program and compares characters one by one. They sould be numeric. The best input is an expression like this: (9*(1-3))-4*(3+3*4) and the result will be: 913-*4334*+*-

Comparing the precedences:

private static bool Predecessor(char firstOperator, char secondOperator)
{
   string opString = "(+-*/%";

   int firstPoint, secondPoint;

   int[] precedence = { 0, 12, 12, 13, 13, 13 };// "(" has less prececence

   firstPoint = opString.IndexOf(firstOperator);
   secondPoint = opString.IndexOf(secondOperator);

   return (precedence[firstPoint] >= precedence[secondPoint]) ? true : false;
}

Clear!

Validation Mehod:

Private static bool IsValid(string input)
{
   Regex operators = new Regex(@"[\-+*/%]", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
   if (string.IsNullOrEmpty(input))
      return false;

   if (input.ToCharArray().Select(c => c == '(').Count() != input.ToCharArray().Select(c => c == ')').Count())
      return false;

   string tempString = operators.Replace(input, ".");

   if (tempString.EndsWith("."))
      return false;

   string[] contains = new string[] { "(.)", "()", "..", ".)" };

   foreach (string s in contains)
   {
      if (tempString.Contains(s))
         return false;
   }

   operators = new Regex(@"[().]", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
   tempString = operators.Replace(tempString, string.Empty);

   foreach (char c in tempString.ToCharArray())
   {
      if (!Char.IsNumber(c))
         return false;
   }

   if (input.Contains("."))
      return false;

   tempString = input;

   operators = new Regex(@"[1234567890]", RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled);
   tempString = operators.Replace(tempString, ".");

   if (tempString.Contains(".."))
      return false;
   if (input.StartsWith("*") || input.StartsWith("/") || input.StartsWith("%") 
                                             || input.StartsWith("+") || input.StartsWith("-"))
      return false;

   contains = new string[] {"(%","(/","(*","*","(+","(-" };
   foreach (string s in contains)
   {
      if (input.Contains(s))
         return false;
   }

   int begin = 0, end = 0;
   foreach (char c in input)
   {
      if (c == '(')
         begin++;
      if (c == ')')
         end++;
      if (end > begin)
         return false;
}
return true;
} 

(Thanks to OriginalGriff for some advising)

Validation method, unlike its harash exterior, works easy.

It checks all parenthesis:

  • Number of "(" and ")" if doesn't match, returns false.
  • If for example: ((1+3)))(, return's false
  • if "*1" or "/5" or "%9" or ...
  • if "(+" or "(-" or ...
  • ...

And for all invalid expression, returns false.