Калькулятор , приоритет умножения и деления C#
Самодельный калькулятор который принимает значения с ввода пользователя и затем должен посчитать то что он написал, и чтобы учитывался приоритет деления или умножения, к примеру : 2+2 * 2 = 6 Проблема с логикой приоритетов, ломал голову как бы сделать , вроде сделал же , 2+2 * 2 = 6 всё нормально, но почему то когда 2+2*2+2 уже exception выбивает , в чём может быть проблема ? или как правильно сделать логику по приоритетам умножения и деления
class Program
{
static void Main(string[] args)
{
try
{
string text = Console.ReadLine();
string[] nums = text.Split('*', '/', '+', '-');
List<string> symbols = new List<string>();
SymbolFinder(text, ref symbols);
List<string> result = new List<string>();
List<string> numbers = new List<string>();
Prioritets(symbols, nums, ref numbers, ref result);
Calculation(result, numbers);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void SymbolFinder(string text, ref List<string> symbols)
{
for (int i = 0; i < text.Length; i++)
{
switch (text[i])
{
case '+':
case '-':
case '*':
case '/':
symbols.Add(Convert.ToString(text[i]));
break;
}
}
}
private static void Prioritets(List<string> symbols, string[] nums, ref List<string> numbers, ref List<string> result)
{
for (int i = 0; i < symbols.Count; i++)
{
switch (Convert.ToChar(symbols[i]))
{
case '*':
numbers.Add(Convert.ToString(Convert.ToInt32(nums[i]) * Convert.ToInt32(nums[i + 1])));
break;
case '/':
numbers.Add(Convert.ToString(Convert.ToInt32(nums[i]) / Convert.ToInt32(nums[i + 1])));
break;
case '+':
if (i != 0 && (symbols[i - 1] == "*" | symbols[i - 1] == "/"))
{
result.Add("+");
break;
}
else
{
numbers.Add(nums[i]);
result.Add("+");
break;
}
case '-':
if (i != 0 && (symbols[i - 1] == "*" | symbols[i - 1] == "/"))
{
result.Add("-");
break;
}
else
{
numbers.Add(nums[i]);
result.Add("-");
break;
}
}
}
}
static void Calculation(List<string> res , List<string> nums)
{
int sum = Convert.ToInt32(nums[0]);
for (int i = 0; i < res.Count; i++)
{
switch (Convert.ToChar(res[i]))
{
case '+':
sum += Convert.ToInt32(nums[i + 1]);
break;
case '-':
sum -= Convert.ToInt32(nums[i + 1]);
break;
}
}
Console.WriteLine("Result of calculation = " + sum + ".");
}
}
P.S. видимо где то ошибка в методе Prioritets
Ответы (1 шт):
Как хорошо, когда знаешь Linq. На самом деле примеры всяких калькуляторов выражений здесь пролетали и ранее, следовало лучше поискать, но из тех что я видел, все с поддержкой скобок и не все с поддержкой приоритета операторов.
Допустим, выражение состоит только из целых положительных чисел, операций */+- и не содержит скобок, тогда код получится такой.
static void Main(string[] args)
{
Console.Write("Введите выражение: ");
string expString = Console.ReadLine();
try
{
Console.WriteLine($"Результат: {ParseExpression(expString)}");
}
catch (Exception ex)
{
Console.WriteLine($"Ошибка: {ex.Message}");
}
Console.ReadKey();
}
private static readonly char[] supportedOperators = "*/+-".ToCharArray();
private static readonly char[] allDigits = "0123456789".ToCharArray();
private static readonly int[] priorities = new[] { 0, 0, 1, 1 };
private static int ParseExpression(string expString)
{
expString = expString.Replace(" ", "");
List<char> ops = expString.Split(allDigits, StringSplitOptions.RemoveEmptyEntries).Select(s => s[0]).ToList();
List<int> numbers = expString.Split(supportedOperators, StringSplitOptions.RemoveEmptyEntries).Select(s => int.Parse(s)).ToList();
if (ops.Count + 1 != numbers.Count)
throw new FormatException("Некорректное математическое выражение");
foreach (int priority in priorities.Distinct())
{
List<char> operators = new List<char>();
for (int i = 0; i < priorities.Length; i++)
{
if (priorities[i] == priority)
operators.Add(supportedOperators[i]);
}
for (int i = 0; i < ops.Count; i++)
{
if (operators.Contains(ops[i]))
{
numbers[i] = Calculate(numbers[i], numbers[i + 1], ops[i]);
numbers.RemoveAt(i + 1);
ops.RemoveAt(i);
i--;
}
}
}
return numbers[0];
}
private static int Calculate(int left, int right, char op) => op switch
{
'*' => left * right,
'/' => left / right,
'+' => left + right,
'-' => left - right,
_ => throw new NotSupportedException("Неподдерживаемый оператор")
};
Можно вводить выражение с пробелами, можно без, они игнорируются.
Разберите как работает этот код, выполните пошагово. Если вам не знаком Linq и непонятно то, как я получаю 2 массива с числами и с операторами, вы можете получить их любым другим удобным для вас способом (на самом деле запрос преобразования .Select можно заменить простым циклом foreach). Вся суть и логика данного алгоритма там, где массивы уже получены, то есть начиная с цикла foreach.
Метод Calculate в старом дедовском синтаксисе
private static int Calculate(int left, int right, char op)
{
switch (op)
{
case '*': return left * right;
case '/': return left / right;
case '+': return left + right;
case '-': return left - right;
default: throw new NotSupportedException("Неподдерживаемый оператор");
}
}