четверг, 8 апреля 2010 г.

Решения для 4-го занятия по Java

Напоминаю, если вы не решили еще задачи, то далее не нажимаем.





Итак, стек. Для реализации стека я создал дополнительный класс описывающий один элемент, ну а все остальное по теории создания связных списков.


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).

Хотя, может я чего и не понимаю, и у всего этого есть некий сакраментальный смысл. Надо будет спросить...

Комментариев нет:

Отправить комментарий