Строковый калькулятор. Ошибка присваивания значения
У меня есть стак, в котором хранятся числа. (1, 2, 3, 4, 2 ...) Я беру последние два числа (сначала 2 потому 4 по логике) и передаю методу, который выполняет операцию (деление, но это не важно могут быть также +, -, *) Для проверки я вывожу (number2 + " " + operation + " " + number1) выражение в консоль. И получается выводится 2 / 2, вместо 4 / 2 (вычисляется соответственно). Я поменял 2 -> 1 и теперь выводит 1/1, вместо 4 / 2 (вычисляется соответственно). Так же я думал что проблема в передаче и стал присваивать отдельно и передавать, но проблема осталась.
Код будет главный метод класса (EquationSolution) и метод вычисления (Сalculation). Внизу отдельно запишу класс Stack (Написал сам по методичке)
public double EquationSolution(string str)
{
//Индикатор конца строки
str += '!';
//Удалим пробелы
str = str.Replace(" ", "");
//Проверим правильность введённой строки
string mistake = CheckingTheEnteredString(str);
if (mistake != "")
{
//Если есть ошибки, то выведем в консоль ошибку
Console.WriteLine(mistake);
return -1;
}
//Храним числа
var numbers = new Models.Stack<double>();
//Храним число пока полностью не считаем из строки
string number = "";
double number1, number2;
//Храним операции Операции
var operetions = new Models.Stack<char>();
char[] elements = { '(', ')', '*', '/', '+', '-' };
//Каждый раз писать str[0], чтобы взять первый элемент строки стало лень поэтому я выделил отдельный чар
char e;
while (str.Length != 0)
{
e = str[0];
//Если это оператор или скобка
if (elements.Any(element => element == e))
{
//Считываение числа закончилось, можно и в стек добавить
if (number.Length != 0 && number != "-")
{
numbers.Add(Convert.ToDouble(number));
number = "";
}
//Плюсик
if (e == '+')
{
while (!operetions.IsEmpty)
{
if (!(operetions.Look() == '('))
{
numbers.Add(Сalculation(numbers.PickUp(), numbers.PickUp(), operetions.PickUp()));
}
else
break;
}
operetions.Add(e);
}
//Открывающая скобка
else if (e == '(')
{
operetions.Add('(');
}
//Умножить разделить
else if(e == '*' || e == '/')
{
if(operetions.IsEmpty || operetions.Look() == '+' || operetions.Look() == '-' || operetions.Look() == '(')
{
operetions.Add(e);
}
else
{
while (!operetions.IsEmpty && operetions.Look() == '(')
{
numbers.Add(Сalculation(numbers.PickUp(), numbers.PickUp(), operetions.PickUp()));
}
operetions.Add(e);
}
}
//Закрывающая скобка
else if (e == ')')
{
while(operetions.Look() != '(')
{
numbers.Add(Сalculation(numbers.PickUp(), numbers.PickUp(), operetions.PickUp()));
}
operetions.Delete();
}
//Минус
else
{
if (numbers.IsEmpty )
{
number += '-';
}
else if(operetions.IsEmpty)
{
operetions.Add(e);
}
else
{
while (!operetions.IsEmpty)
{
if (!(operetions.Look() == '('))
{
number1 = numbers.PickUp();
number2 = numbers.PickUp();
numbers.Add(Сalculation(number1, number2, operetions.PickUp()));
}
else
break;
}
operetions.Add(e);
}
}
}
//Если это конец строки
else if (e == '!')
{
if (number.Length != 0)
{
numbers.Add(Convert.ToDouble(number));
number = "";
}
while (!operetions.IsEmpty)
numbers.Add(Сalculation(numbers.PickUp(), numbers.PickUp(), operetions.PickUp()));
}
//Это либо число, либо запятая
else
{
number += e;
}
//Удаляем первый элемент строки
str = str.Remove(0, 1);
}
return numbers.PickUp();
}
static double Сalculation(double number1, double number2, char operation)
{
Console.WriteLine(number2 + " " + operation + " " + number1);
switch (operation)
{
case '+':
return (double)(number1 + number2);
case '-':
return (double)(number2 - number1);
case '*':
return (double)(number1 * number2);
case '/':
return (double)(number2 / number1);
}
return 0;
}
class Stack
{
private List<T> items = new List<T>();
public bool IsEmpty => items.Count == 0;
public void Add(T item)
{
items.Add(item);
}
public T PickUp()
{
if (!IsEmpty)
{
var item = items.LastOrDefault();
items.Remove(item);
return item;
}
else
{
throw new NullReferenceException("Стек пуст");
}
}
public T Look()
{
if (!IsEmpty)
{
return items.LastOrDefault();
}
else
{
throw new NullReferenceException("Стек пуст");
}
}
public void Delete()
{
if (!IsEmpty)
{
var item = items.LastOrDefault();
items.Remove(item);
}
else
{
throw new NullReferenceException("Стек пуст");
}
}
}
Ответы (1 шт):
Ошибка будет если в списке есть два и более одинаковых значения.
Ошибка здесь:
public T PickUp()
{
if (!IsEmpty)
{
var item = items.LastOrDefault();
items.Remove(item); // <- здесь
return item;
}
//...
Метод возвращает последний элемент из списка items, но удаляет не его, а первое вхождение этого значения (см. мануал к Remove()). Т.е. например после первого применения PickUp() на список (1, 2, 3, 4, 2) останется не (1, 2, 3, 4), как вы думаете, а (1, 3, 4, 2). Удалится не последняя двойка, а первая.
Можно попробовать так:
items.RemoveAt(LastIndexOf(item));
за работоспособность не ручаюсь, в с# не разбираюсь.