我怎样才能制作一个带有使用多个操作和括号的字符串的计算器? C#

How can i make a calculator with string that uses multiple operations and brackets? C#

我的计算器在没有括号的情况下几乎可以完美运行(它有一些错误)。此计算器可以进行多项运算(例如 12+345*2-100 //602)。 我希望将括号和其中的字符串替换为结果,然后继续计算。 我怎样才能修复括号的方法使其按预期工作?

计算步骤:

  1. 找到一个符号
  2. 找到符号周围的数字
  3. 进行计算并用字符串中的结果替换数字和符号
  4. 检查任何符号,如果有则重新开始
  5. 给出数学题的结果

    //Finds numbers around an symbol
    static void FindNumbers(string equation, int start, char symbol)
    {
        number1 = 0;
        number2 = 0;
        number1String = string.Empty;
        number2String = string.Empty;
    
        if (equation[start] == symbol)
        {
            for (int j = start - 1; j >= 0; j--)//Finds left number around the symbol
            {
                if (char.IsDigit(equation[j]))
                {
                    number1String = equation[j] + number1String;
                }
                else
                {
                    break;
                }
            }
            for (int j = start + 1; j < equation.Length; j++)//Finds right number around the symbol
            {
                if (char.IsDigit(equation[j]))
                {
                    number2String += equation[j];
                }
                else
                {
                    break;
                }
            }
            number1 = int.Parse(number1String);
            number2 = int.Parse(number2String);
        }
        return;
    }
    
    //Devision and Multiplication
    static void Priority1(string equation, int start)
    {
        for (int i = start; i < equation.Length; i++)//Multiplication
        {
            if (equation[i] == '*')
            {
                symbol = equation[i];
                FindNumbers(equation, i, symbol);
    
                currentresult = number1 * number2;
    
                equation = equation.Replace(number1.ToString() + symbol + number2.ToString(),
                    currentresult.ToString());
            }
        }
        for (int i = 0; i < equation.Length; i++)//Devision
        {
            if (equation[i] == '/')
            {
                symbol = equation[i];
                FindNumbers(equation, i, symbol);
    
                currentresult = number1 / number2;
    
                equation = equation.Replace(number1.ToString() + symbol + number2.ToString(),
                    currentresult.ToString());
            }
        }
        Priority2(equation, 0);
    }
    
    //Addition and Devision
    static void Priority2(string equation, int start)
    {
        for (int i = start; i < equation.Length; i++)//Addition
        {
            if (equation[i] == '+')
            {
                symbol = equation[i];
                FindNumbers(equation, i, symbol);
    
                currentresult = number1 + number2;
    
                equation = equation.Replace(number1.ToString() + symbol + number2.ToString(),
                    currentresult.ToString());
            }
        }
        for (int i = 0; i < equation.Length; i++)//Devision
        {
            if (equation[i] == '-')
            {
                symbol = equation[i];
                FindNumbers(equation, i, symbol);
    
                currentresult = number1 - number2;
    
                equation = equation.Replace(number1.ToString() + symbol + number2.ToString(),
                    currentresult.ToString());
            }
        }
        for (int i = 0; i < equation.Length; i++)//Checks if there are more symbols in the string
        {
            if (char.IsSymbol(equation[i]))
            {
                Priority1(equation, 0);
            }
        }
        tempresult = equation;
        Console.WriteLine("Result : " + equation);
    }
    
    //Brackets
    static void Brackets(string equation, int index)
    {
        for (int i = index; index < equation.Length; index++)
        {
            if (equation[index] == '(')
            {
                index += 1;
                Brackets(equation, index);
    
                for (int j = index; j < equation.Length; j++)
                {
                    if (equation[j] == ')')
                    {
                        tempresult = temp;
                        Console.WriteLine("..." + tempresult);
                        break;
                    }
                    temp += equation[j];
                }
    
                Priority1(tempresult, index);
                equation = equation.Replace('(' + temp.ToString() + ')', tempresult.ToString());
                Console.WriteLine("." + equation);
            }
        }
        Priority1(equation, 0);
    }
    
    static void Main(string[] args)
    {
        equation = Console.ReadLine();
    
        Brackets(equation, 0);
        Console.ReadKey();
    }
    

你的代码现在理论上知道如何解析和评估正确的简单数学表达式。通过简单的表达式,我指的是仅由已知的一元和二元运算符和数字组成的表达式(无括号)

您现在尝试解析的表达式是:

  1. 一个简单的表达式
  2. 带括号的表达式
  3. 由简单表达式和括号表达式组成的复杂表达式

如果是案例#1,那么你已经知道如何处理了;解析它,你就完成了。

如果是情况 #2,只需删除括号并解析其中的表达式。

如果是第 3 种情况,那么你将获取顶级括号内的表达式并解析它们;您将进入第 1 步或第 2 步或第 3 步,嘿!你猜怎么着?你已经知道如何处理这些了。

最终你会把你的表达式分解成简单的表达式。然后你只需要在回来的路上回溯评估。

用简单的英语来说,你需要一个递归解析器;一个可以调用自身并解析和评估嵌套表达式的解析器。

考虑例如:

e0: 1 + (2 * (3 - 2))
  1. e0: 你解析 1 + p0
  2. p0: 你解析 2 * p1
  3. p1: 你解析 3 - 2
  4. 您已完成解析
  5. p1:计算结果为 1
  6. p0:计算结果为 2
  7. e0:计算结果为 3
  8. 你完成了。

很酷的是解析器理论上可以处理无限嵌套表达式...问题是您的计算机可能不能。

您可能想要研究将字符串方程分解成单独的标记,并使用类似 Shunting-Yard-Algorithm 的东西来 parse/calculate 结果。