Итак, стек. Для реализации стека я создал дополнительный класс описывающий один элемент, ну а все остальное по теории создания связных списков.
public class Stack<T> {
class Item
{
T value;
Item next;
public Item(T p_value, Item p_next)
{
value = p_value;
next = p_next;
}
}
Item head;
int count;
public Stack()
{
head = null;
count = 0;
}
public boolean isEmpty()
{
return count == 0;
}
public void push(T p_newItem)
{
count++;
head = new Item(p_newItem, head);
}
public T pop()
{
if (count > 0)
{
count--;
T returnValue = head.value;
head = head.next;
return returnValue;
}
throw new RuntimeException("Список пуст");
}
public int count()
{
return count;
}
}
* This source code was highlighted with Source Code Highlighter.
Основную часть задания, я разбил на два метода, добавив вспомогательный класс лексема. На первом шаге входной текст преобразуется в список лексем, для каждой из которых мы храним по мимо ее текста является она операндом или операцией. На втором шаге собственно вычисления при помощи стека описанного выше.
public class PostfixCalculator {
class Lexem
{
String text;
boolean isConst;
public Lexem(String p_text, boolean p_isConst)
{
text = p_text;
isConst = p_isConst;
}
}
static List<Lexem> lexecalAnalyzer(String p_string)
{
PostfixCalculator p = new PostfixCalculator();
List<Lexem> lexems = new LinkedList<Lexem>();
int currentCharIndex = 0;
List<String> operations = new ArrayList<String>(10);
operations.add("+");
operations.add("-");
operations.add("*");
operations.add("/");
List<String> digits = new ArrayList<String>(4);
for (int i = 0; i < 10; i++)
{
digits.add(String.valueOf(i));
}
while (currentCharIndex < p_string.length())
{
String currentChar = p_string.substring(currentCharIndex, ++currentCharIndex);
if (operations.contains(currentChar))
{
lexems.add(p.new Lexem(currentChar, false));
}
else if (currentChar.equals(")") || currentChar.equals("("))
{
// Самое интересное, что тут делать ничего не надо ))
}
else if (digits.contains(currentChar))
{
String number = currentChar;
while (digits.contains(p_string.substring(currentCharIndex, currentCharIndex + 1)))
{
number += p_string.substring(currentCharIndex, ++currentCharIndex);
}
lexems.add(p.new Lexem(number, true));
}
else if (currentChar.equals(" "))
{
// Опять же, ничего не делаем
}
else
{
throw new RuntimeException("Строка содержит недопустимые символы");
}
}
return lexems;
}
public static int Calc(String p_string) {
Stack<Integer> operands = new Stack<Integer>();
List<Lexem> lexems = lexecalAnalyzer(p_string);
for (Lexem currentLexem : lexems)
{
if (currentLexem.isConst)
{
operands.push(Integer.valueOf(currentLexem.text));
}
else
{
if (operands.count() > 1)
{
int firstOperand = operands.pop();
int secondOperand = operands.pop();
int result = secondOperand / firstOperand;
if (currentLexem.text.endsWith("+"))
{
result = secondOperand + firstOperand;
}
else if (currentLexem.text.equals("-"))
{
result = secondOperand - firstOperand;
}
else if (currentLexem.text.equals("*"))
{
result = secondOperand * firstOperand;
}
operands.push(result);
}
else
{
throw new RuntimeException("Синтаксическая ошибка в исходном выражении");
}
}
}
if (operands.count() == 1)
{
return operands.pop();
}
throw new RuntimeException("Синтаксическая ошибка в исходном выражении");
}
}
* This source code was highlighted with Source Code Highlighter.
Что меня неприятно поразило при выполнении данного задания? А вот что - в статическом методе я не могу вызвать конструктор вложенного класса не создав объект класса в который вложены статический метод и собственно вложенный класс.
О чем я?
Обратили внимание вот на эту строку: PostfixCalculator p = new PostfixCalculator(); ?
Согласитесь бред создавать экземпляр класса содержащего два статических метода? А вот и нет, исходя из точки зрении разработчиков Java, вот такая конструкция бредом не является:
p.new Lexem(currentChar, false).
Хотя, может я чего и не понимаю, и у всего этого есть некий сакраментальный смысл. Надо будет спросить...
Комментариев нет:
Отправить комментарий