Постфикс калькулятор Java

Итак, мне нужно прочитать постфиксное выражение из файла. В постфиксном выражении должны быть пробелы для разделения каждого оператора или операнда. То, что у меня есть, пока работает только в том случае, если во входном файле нет пробелов между операторами или операндами. (т. е. если файл имеет 12+, я получаю результат 3.) Чтобы сделать это, я думаю, что мне нужно токенизировать ввод, но я не уверен, как это сделать. Это то, что у меня есть до сих пор. Спасибо за любые ответы.

import java.util.*;
import java.io.*;
public class PostfixCalc{
public static void main (String [] args) throws Exception {
File file = new File("in.txt");
Scanner sc = new Scanner(file);
String input = sc.next();
Stack<Integer> calc = new Stack<Integer>();
while(sc.hasNext()){
for(int i = 0; i < input.length(); i++){
    char c = input.charAt(i);
    int x = 0;
    int y = 0;
    int r = 0;
    if(Character.isDigit(c)){
       int t = Character.getNumericValue(c);
        calc.push(t);
    }
    else if(c == '+'){
        x = calc.pop();
        y = calc.pop();
        r = x+y;
        calc.push(r);
    }
     else if(c == '-'){
        x = calc.pop();
        y = calc.pop();
        r = x-y;
        calc.push(r);
    }
     else if(c == '*'){
        x = calc.pop();
        y = calc.pop();
        r = x*y;
        calc.push(r);
    }
     else if(c == '/'){
        x = calc.pop();
        y = calc.pop();
        r = x/y;
        calc.push(r);
    }
}
 }
 int a = calc.pop();
System.out.println(a);
 }
 } 

person Jmamz06    schedule 04.09.2012    source источник
comment
Взгляните на StringTokenizer. По умолчанию он токенизирует пробелы (пробелы, табуляции, новые строки и т. д.).   -  person Brian    schedule 04.09.2012


Ответы (3)


Есть несколько вещей, которые вам нужно изменить, и вы можете сделать это шаг за шагом.

  1. Объявите, что ваш Stack содержит Integer, а не Character.
  2. В коде, который считывает ввод, используйте Strings вместо Characters.
  3. Разобрать операнды с помощью Integer.parseInt(). Это преобразует Strings в Integers. (На самом деле он преобразует их в ints, но в вашем случае эта разница не имеет значения.)
  4. Установите разделитель сканера с помощью Scanner.useDelimiter() на \s+, это будет соответствовать последовательности любых пробельных символов.

Конечно, существует множество других способов обработки вашего ввода, но я попытался дать вам представление о том, как изменить существующий код, чтобы он делал то, что ему нужно.

person biziclop    schedule 04.09.2012

Для токенизации вы можете использовать String.split() с одним пробелом в качестве разделителя;

String[] inputs = input.split(" ");

Вот полное решение, которое я только что написал и которое использует реализацию Stack на основе односвязного списка для создания постфиксного калькулятора;

A - PostFixCalculator

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class PostFixCalculator {

    private static final String ADD = "+"; 
    private static final String SUB = "-";
    private static final String MUL = "*";
    private static final String DIV = "/";

    public void calculateFile(String fileName) throws IOException {
        BufferedReader br = null;
        StringBuilder sb = null;
        try {
            FileReader fileReader = new FileReader(fileName);
            br = new BufferedReader(fileReader);

            sb = new StringBuilder();
            String line = br.readLine();

            while (line != null) {
                sb.append(line);
                line = br.readLine();
            }

            String input = sb.toString();
            System.out.println(input + " = " + calculate(input));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            br.close();
        }
    }

    private int calculate(String input) {
        SinglyLinkedListStack<Integer> stack = new SinglyLinkedListStack<>();

        String[] inputs = input.split(" ");

        return handleCalculation(stack, inputs);
    }

    private static int handleCalculation(SinglyLinkedListStack<Integer> stack, String[] el) {
        int operand1, operand2;

        for(int i = 0; i < el.length; i++) {
            if( el[i].equals(ADD) || el[i].equals(SUB) || el[i].equals(MUL) || el[i].equals(DIV) ) {
                operand2 = stack.pop();
                operand1 = stack.pop();
                switch(el[i]) {
                    case ADD: {
                        int local = operand1 + operand2;
                        stack.push(local);
                        break;
                    }

                    case SUB: {
                        int local = operand1 - operand2;
                        stack.push(local);
                        break;
                    }

                    case MUL: {
                        int local = operand1 * operand2;
                        stack.push(local);
                        break;
                    }

                    case DIV: {
                        int local = operand1 / operand2;
                        stack.push(local);
                        break;
                    }
                }
            } else {
                stack.push(Integer.parseInt(el[i]));
            }
        }

        return stack.pop();
    }

}

B — стек односвязных списков

public class SinglyLinkedListStack<T> {

    private int size;
    private Node<T> head;

    public SinglyLinkedListStack() {
        head = null;
        size = 0;
    }

    public void push(T element) {
        if(head == null) {
            head = new Node(element);
        } else {
            Node<T> newNode = new Node(element);
            newNode.next = head;
            head = newNode;
        }

        size++;
    }

    public T pop() {
        if(head == null)
            return null;
        else {
            T topData = head.data;

            head = head.next;
            size--;

            return topData;
        }
    }

    public T top() {
        if(head != null)
            return head.data;
        else
            return null;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    private class Node<T> {
        private T data;
        private Node<T> next;

        public Node(T data) {
            this.data = data;
        }

    }

}

С - Демо

import java.io.IOException;

public class PostFixCalculatorDemo {
    public static void main(String[] args) throws IOException {
        PostFixCalculator calc = new PostFixCalculator();
        calc.calculateFile("postfix.txt");
    }
}

D — Образец входного файла: «postfix.txt»

6 5 2 3 + 8 * + 3 + * 

E - демонстрационный вывод

6 5 2 3 + 8 * + 3 + *  = 288
person Levent Divilioglu    schedule 10.08.2016

вам не нужен сканер

просто используйте BufferedReader для чтения файла, затем используйте это метод readLine для получения строки

Затем используйте

String tokens[] = line.split("\\s+?") 

и вы получите массив «токенов», которые можно обрабатывать в вашем коде.

чтобы определить номер, вы можете использовать следующее регулярное выражение:

Pattern isNumber = Pattern.compile("^\\d+?$")
if (isNumber.matcher(token).matches()) {
    push(Integer.parseInt(token));
}
person jdevelop    schedule 04.09.2012
comment
На самом деле здесь проще использовать сканер. next() по умолчанию извлекает следующий токен, разделенный пробелами. Выкройки, конечно, можно использовать потом. - person E_net4 the curator; 04.09.2012