【问题标题】:How can i make a calculator with string that uses multiple operations and brackets? C#如何使用使用多个操作和括号的字符串制作计算器? C#
【发布时间】:2023-03-03 11:58:02
【问题描述】:

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

【问题讨论】:

  • 第 0 步:定义表达式语法
  • 这闻起来像作业!还有我会尝试作为 TDD Kata 的东西
  • 其实这不是作业,但我在书中找到了一些东西,然后我想到了,所以我决定试着去做。

标签: c# string calculator


【解决方案1】:

您可能希望考虑将字符串方程分解为单独的标记,并使用 Shunting-Yard-Algorithm 之类的东西来解析/计算结果。

【讨论】:

  • 虽然理论上这可以回答这个问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
【解决方案2】:

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

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

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

如果是第一种情况,那么您已经知道如何处理它;解析它,你就完成了。

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

如果是第 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 这样的算法更简单、更快。
  • @3Dave 我知道,只是指出替代方法。编写自己的解析器非常有指导意义。
  • 感谢您的提示。
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多