Как я могу сделать калькулятор со строкой, которая использует несколько операций и скобки?C # - PullRequest
0 голосов
/ 13 ноября 2018

Мой калькулятор работает почти идеально без скобок (в нем есть некоторые ошибки).Этот калькулятор может выполнять несколько операций (например, 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 голосов
/ 14 ноября 2018

Возможно, вы захотите разбить уравнение Строков на отдельные токены и использовать что-то вроде Алгоритма Шунтирования-Ярда для анализа / вычисления результата.

0 голосов
/ 14 ноября 2018

Ваш код сейчас теоретически знает, как анализировать и оценивать правильные простые математические выражения. Под простыми выражениями я имею в виду выражения, состоящие только из известных унарных и двоичных операторов и чисел (без скобок)

Выражение, которое вы сейчас пытаетесь проанализировать: либо:

  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. Вы закончили.

Круто в этом то, что синтаксический анализатор может обрабатывать, теоретически, бесконечные вложенные выражения ... проблема в том, что ваш компьютер, вероятно, не может.

...