如何使用带多个运算符和括号的字符串制作计算器? C#

时间:2018-11-13 20:58:47

标签: c# string calculator

我的计算器在没有括号的情况下几乎可以完美工作(它有一些错误)。该计算器可以执行多种操作(例如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();
    }
    

2 个答案:

答案 0 :(得分:4)

您可能想研究将String方程分解为单独的标记,并使用类似Shunting-Yard-Algorithm之类的方法来分析/计算结果。

答案 1 :(得分:3)

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

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

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

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

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

在#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. 您完成了。

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