0

My goal is to make a math expression interpreter with c#, for example if you type "A=3", it'll save the A as a dictionary key and 3 as its value, this program has more features so if you type "B=3" and then "A=B+3" and then "Show(A)", it must display "6" as the answer.

Everything is right until I type something like "A=10" "B=10" "C=A+B" and finally "Show(C)", because Variables' value are 2-digit (or more) numbers in this case, when producing the final result, numbers are saved in the string like "01+01" instead of "10+10" (because A and B values are 10 so A+B should be 10+10), so it's kinda reversed.

I tried to reverse the string and then evaluate the answer but that didn't work as well, simply it gives me "1+1" for some reason!

Notes:

  1. expression evaluation is done by "return Convert.ToInt32(new DataTable().Compute(result, null));"

  2. because strings are immutable in c#, when every expression like "A+B" or "3+5" comes in the method, I create a new empty string like (string result = " ";) and then with the help of "result = ValidExpression[i] + result.Remove(counter, 0);", I change the variables with values (note = if all the elements of input are numbers, answer is right) like "A" with "23" and put them in the new string and then evaluate the final string. But as I said, it saves the 23 as 32 so the answer will be wrong.

This is my code and the bug is probably in the LongProcessing method. Thanks for your helps.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Data;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Welcome To The Program\nCorrect Syntax:");
            Console.WriteLine("A=10\nB=15\nC=A+B\nD=13/4-2+A-C+B\nShow(D)");
            Console.WriteLine("\nEnter your input:");

            Expression E = new Expression();
            string expression = "start";
            while (expression != "exit")
            {
                expression = Console.ReadLine();
                // for show command
                if (expression.Contains("Show") == true)
                    try { E.Show(expression[5]); }
                    catch (Exception e)
                    {
                        Console.WriteLine("input is not correct, Can not show anything. please try again");
                    }

                if (E.Validation(expression) == false)
                    Console.WriteLine("input is not correct, please try again");
                else
                    E.Processing(expression);
            }
            Console.ReadKey();
        }
    }

    class Expression
    {
        public Dictionary<Char, String> Variables = new Dictionary<Char, String>();
        public Expression()
        { }

        public Boolean Validation(string expression)
        {
            // true if c is a letter or a decimal digit; otherwise, false  &&  true if c is a decimal digit; otherwise, false.
            if (!Char.IsLetterOrDigit(expression[0]) || Char.IsDigit(expression[0]))
                return false;
            else
                return true;
        }

        public void Processing(String ValidExpression)
        {
            // Update Dictionary with new values per key
            if (Variables.ContainsKey(ValidExpression[0]))
                Variables.Remove(ValidExpression[0]);

            string temp = "                ";
            if (ValidExpression.Length > 2 && !ValidExpression.Contains("Show") && !ValidExpression.Contains("exit"))
            {
                // removing the variable name and "=" from the string
                for (int i = 2; i < ValidExpression.Length; i++)
                    temp = ValidExpression[i] + temp.Remove(i, 0);

                Variables.Add(ValidExpression[0], LongProcessing(temp).ToString());
            }
        }
         
        // something is wrong in this method
        public int LongProcessing(String ValidExpression)
        {
            string temp;
            int counter = 0;
            string result = "                   ";
            for (int i = 0; i < ValidExpression.Length; i++)
            {
                //changing variables (letters) with values
                if (Char.IsLetter(ValidExpression[i]))
                {
                    if (Variables.ContainsKey(ValidExpression[i]))
                    {
                        Variables.TryGetValue(ValidExpression[i], out temp);
                        for (int j = 0; j < temp.Length; j++)
                        {
                            result = temp[j] + result.Remove(counter, 0);
                            counter++;
                        }
                    }
                }
                else
                {
                    result = ValidExpression[i] + result.Remove(counter, 0);
                    counter++;
                }
            }
            // checks if all of the string elements are numbers
            if (ValidExpression.All(char.IsDigit))
                return Convert.ToInt32(ValidExpression);
            else
            {
                return Convert.ToInt32(new DataTable().Compute(result, null));
            }
        }
        
        public void Show(Char ValidExpression)
        {

            Console.WriteLine(Variables[ValidExpression]);
        }
    }
}
Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
  • 1
    Please review [MCVE] guidance on posting code and [edit] question accordingly. Also remember that dictionaries don't have order of items - so complaining that iterating items in dictionary does not preserve order does not make much sense. – Alexei Levenkov Nov 24 '20 at 04:31

2 Answers2

0

Here are some suggestions:

Start by looking at the value of "temp" in "Processing". To assist in your debugging, add a "Console.WriteLine" statement.

public void Processing(String ValidExpression)
{
    // Update Dictionary with new values per key
    if (Variables.ContainsKey(ValidExpression[0]))
        Variables.Remove(ValidExpression[0]);

    string temp = "                ";
    if (ValidExpression.Length > 2 && !ValidExpression.Contains("Show") && !ValidExpression.Contains("exit"))
    {
        // removing the variable name and "=" from the string
        for (int i = 2; i < ValidExpression.Length; i++)
        {
            temp = ValidExpression[i] + temp.Remove(i, 0);
            Console.WriteLine("    temp: " + temp); //added for debugging
        }
                    

        Variables.Add(ValidExpression[0], LongProcessing(temp).ToString());
    }

}

A couple of other things:

  • The user is never informed how to exit.

  • There is a class named "Expression" and a string variable named "expression". This is likely to cause confusion.

You may also want to look at this post: how to convert a string to a mathematical expression programmatically

Tu deschizi eu inchid
  • 4,117
  • 3
  • 13
  • 24
0

This is broken:

for (int i = 2; i < ValidExpression.Length; i++)
  temp = ValidExpression[i] + temp.Remove(i, 0);

temp.Remove(i, 0) is a non op, you might as well just write temp

So let's plot the loop:

Assume ValidExpression is "A=10"

Temp starts out as "                "
First iteration, temp is "1                " 
Second iteration, temp is "01                "

Any operation that works left to right through a string, character by character, pulling a character out and sticking it on the start of a growing string, will reverse the string

Perhaps you meant to not have a loop and instead do temp = ValidExpression.Substring(2) ?

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • Thanks, actually "temp = ValidExpression.Substring(2)" was the key to the answer! I used it in processing and also long processing method and it preserved the order so everything is working now. – mostafa abbac Nov 24 '20 at 11:39