я пытался сделать калькулятор в консоли С#

avatar
Alptuğ Turan
8 августа 2021 в 16:29
132
1
0

Я хочу, чтобы пользователь ввел математическое уравнение в виде строки, затем разделил их на символы, а затем преобразовал их в двойные, чтобы я мог их использовать, но у меня проблемы с преобразованием char в двойные

public  void Cal()
        {
            Console.WriteLine("Enter the transaction without spaces");
            string transaction = Console.ReadLine();
            char[] characters = transaction.ToArray();

            for(int i = 0; i < characters.Length; i++)
            {
                Console.Write(characters[i] + " ");
                if (i % 2 == 1)
                {
                    Convert.ToDouble(characters[i]);
                }
            }
            
        }
static void Main(string[] args)
        {
            Calculate calc = new Calculate();
            bool quit = false;
            
            while (quit == false)
            {
                calc.Cal();
                Console.ReadLine();
                Console.WriteLine("to clear pres C to quit the app pres Q");
                Console.Write(" : ");
                string b = Console.ReadLine().ToUpper();
                if (b == "C")
                {
                    Console.Clear();
                }else 
                {

                    quit = true;
                    Console.ReadLine();

                }
            }
        }
Источник
Flydog57
8 августа 2021 в 16:37
0

Что вы ожидаете в качестве входных данных? Транзакция не очень специфична.

Alptuğ Turan
8 августа 2021 в 16:43
0

математическая транзакция, например 34 * 5

Flydog57
8 августа 2021 в 17:14
0

Это простое/одинарное инфиксное выражение с двумя аргументами, подобное этому каждый раз, или это может быть 1 + 2 * 4 (и если последнее, то каковы правила приоритета - результат этого 12 или 9)? Что такое разрешающие операторы? Выражение типа 34 / 5 приводит к 6 или 6.8?

Flydog57
8 августа 2021 в 17:18
0

By the way, in normal nomenclature, that's an expression, not a transaction and what you are doing is parsing it and then evaluating Это. Если вы ищете анализатор математических выражений, вы, вероятно, найдете пример кода

Flydog57
8 августа 2021 в 19:35
0

Один из способов решить эту проблему — определить токены (в 34+5 есть три токена: 34, + и 5, два из которых представляют числа, а другой — оператор). Вам нужно выяснить, из чего состоит токен (5 — число, это -12.34). Затем разберитесь с грамматикой (в вашем случае. number operator number составить выражение). Наконец, вам нужен способ оценки этих выражений. В качестве последней подсказки, вы будете счастливее, если будете использовать decimal, а не double в качестве основного числового типа (это более точно)

Ответы (1)

avatar
GoldenAxe
8 августа 2021 в 21:14
1

Если вам нужен очень простой математический оценщик, вы должны пройти через char[] для определения операторов. Затем вы можете оценить выражение, преобразовав сегменты char[] между операторами или вне одного оператора в числовой тип и передав их в качестве операндов для каждого оператора и представив результат. Это сложнее, если вы поддерживаете вложения в скобках. (см. ниже)

Чтобы преобразовать сегменты char[] между операторами, поскольку вы используете C#, вы можете:

  • Используйте свою строку "транзакция" и вызовите .Substring(startidx, endidx), ограничив ее до или между операторами, а затем вызовите .Trim(), чтобы удалить пробелы и вернуть вам строку. Пример: "string expression = transaction.Substring(0, opidx-1).Trim()" Эта строка (числа) может быть отправлена ​​​​в функцию double.Parse(), чтобы вернуть вам двойное значение, которое вы можете оценить с помощью используя оператор(ы) и другие значения, проанализированные и преобразованные таким образом. Пример: "double val = double.Parse(выражение)".

  • Или вы можете вызвать функцию для пошагового перехода каждого индекса char в диапазоне до оператора, используя char.IsNumber() для поиска начала и конца диапазона непробельных символов, а затем также можете использовать строку транзакции и .Substring с этими индексами для вывода строки, содержащей число для анализа, как указано выше, с помощью double.Parse(). В противном случае вы можете добавить числовые символы в строку.

Если вам нужен более мощный анализатор формул и выражений, вам нужно подойти к нему немного сложнее.

Однажды я написал анализатор кода C#, включая полный анализатор математических выражений/формул. Разбор потенциально сложного математического выражения является важным шагом для программы, оценивающей математические функции. Скобки могут влиять на порядок вычисления.

В основном шаги, которые я предпринял, помимо определения комментариев и литеральных зон (специфичных для синтаксического анализатора кода), заключаются в следующем:

  • Создайте массив индексов открывающих и закрывающих скобок внутри вашего выражения. Рекурсивная функция наиболее эффективна. Вызовите функцию FindCloseParan, задав ей индекс открытого парана, и если она найдет открытый паран перед закрытым параном за ним, она снова вызовет FindCloseParan, в противном случае она может вернуть символ закрытого парана, что позволит вам сохранить каждый совпадающий открытый паран. уровень закрывает паран в массиве. Затем вы можете позже сделать вызовы функции GetCloseParan для индекса открытого парана, чтобы получить соответствующий индекс закрытия парана уровня, без необходимости повторного использования тогда потенциально неэффективной (перекрывающейся повторяющейся работы) рекурсивной функции FindCloseParan, и вы можете использовать соответствующий открывать и закрывать индексы paran для запуска функции выражения синтаксического анализа в каждой зоне. (Если вам нужен простой математический оценщик без поддержки круглых скобок, вы можете опустить это)

  • Запустите функцию для разбора логического выражения. Он должен идентифицировать следующий индекс оператора (или И, или ИЛИ) и проверять, находится ли он перед следующим открытым параном. Если индекс следующего оператора находится после открытого парана, он должен искать следующего оператора после закрытого парана на том же уровне парана, что и открытый паран. Если он находит что-либо за пределами parans, он должен вызвать функцию логического выражения синтаксического анализа, чтобы проанализировать выражение с каждой стороны каждого оператора. Если оператора нет, он может проанализировать блок, чтобы сохранить его как тип класса выражения. Если на одном уровне корпуса parans есть несколько операторов, он может хранить индекс каждого типа оператора в массиве операторов и массиве типов выражений, которые чередуются с операторами. (Выражение, Оператор, Выражение, Оператор, Выражение и т. д.)

Идентификация символа, который может быть первым символом оператора, приводит к проверке возможного двухсимвольного оператора. Из моего кода:

CSharpTypeWalker.firstcharoperatorsarrray = new char[] { '+', '-', '~', '*', '/', '%', '^', '!', '&', '| ', '<', '>', '=', '?' };

CSharpTypeWalker.alloperatorsarray = new string[] { "+", "-", "~", "*", "/", "%", "^", "!", "&", "| ", "<", ">", "<<", ">>", "&&", "||", "==", "!=", "<=", "=>", " >=", "=<", "?:", "+=", "-=", "++", "--" };