public class CalculatorModel {
public double calculate(String expression) {
return evaluateExpression(expression);
}
private double evaluateExpression(String expression) {
return new Object() {
int pos = -1, ch;
void nextChar() {
ch = (++pos < expression.length()) ? expression.charAt(pos) : -1;
}
boolean eat(int charToEat) {
while (ch == ' ') nextChar();
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
double parse() {
nextChar();
double x = parseExpression();
if (pos < expression.length()) throw new RuntimeException("Lỗi: Biểu thức không hợp lệ");
return x;
}
double parseExpression() {
double x = parseTerm();
for (;;) {
if (eat('+')) x += parseTerm();
else if (eat('-')) x -= parseTerm();
else return x;
}
}
double parseTerm() {
double x = parseFactor();
for (;;) {
if (eat('*')) x *= parseFactor();
else if (eat('/')) x /= parseFactor();
// else if (eat('%')) x %= parseFactor(); // Thêm phép chia lấy dư
else return x;
}
}
private double parseFactor() {
// Xử lý các toán tử một ngôi (+,-,√) trước
if (eat('+')) return parseFactor();
if (eat('-')) return -parseFactor();
if (eat('√')) return Math.sqrt(parseFactor());
double x;
int startPos = this.pos;
if (eat('(')) {
x = parseExpression();
eat(')');
} else if ((ch >= '0' && ch <= '9') || ch == '.') {
while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
x = Double.parseDouble(expression.substring(startPos, this.pos));
// Xử lý % ngay sau số
if (eat('%')) {
x = x / 100.0;
}
} else {
throw new RuntimeException("Lỗi: Ký tự không hợp lệ");
}
// Xử lý toán tử mũ SAU khi có toán hạng đầu tiên
if (eat('^')) {
x = Math.pow(x, parseFactor());
}
return x;
}
}.parse();
}
}
package ll;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionListener;
public class CalculatorView extends JFrame {
private JTextField displayExpression; // Hiển thị biểu thức
private JTextField displayResult; // Hiển thị kết quả
private JButton[] buttons; // Mảng chứa các nút
public CalculatorView() {
// Thiết lập cửa sổ chính
setTitle("Calculator");
setSize(300, 400);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
// Tạo panel chính với BorderLayout
JPanel mainPanel = new JPanel(new BorderLayout());
// Tạo panel hiển thị
JPanel displayPanel = new JPanel(new GridLayout(2, 1));
displayExpression = new JTextField();
displayExpression.setEditable(false);
displayExpression.setFont(new Font("Arial", Font.PLAIN, 18));
displayExpression.setHorizontalAlignment(JTextField.RIGHT);
displayResult = new JTextField();
displayResult.setEditable(false);
displayResult.setFont(new Font("Arial", Font.BOLD, 24));
displayResult.setHorizontalAlignment(JTextField.RIGHT);
displayPanel.add(displayExpression);
displayPanel.add(displayResult);
// Tạo panel bàn phím
JPanel buttonPanel = new JPanel(new GridLayout(6, 4, 5, 5)); // Thêm hàng cho nút "C"
// Các nút số và phép toán
String[] buttonTexts = {
"√", "^", "%", "C",
"H", "(", ")", "←",
"7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"
};
buttons = new JButton[buttonTexts.length]; // Khởi tạo mảng nút
for (int i = 0; i < buttonTexts.length; i++) {
buttons[i] = new JButton(buttonTexts[i]);
buttons[i].setFont(new Font("Arial", Font.BOLD, 18));
buttonPanel.add(buttons[i]); // Thêm nút vào giao diện
}
// Thêm các panel vào cửa sổ chính
mainPanel.add(displayPanel, BorderLayout.NORTH);
mainPanel.add(buttonPanel, BorderLayout.CENTER);
add(mainPanel);
}
// Getter
public JTextField getDisplayExpression() {
return displayExpression;
}
public JTextField getDisplayResult() {
return displayResult;
}
// Thêm ActionListener cho tất cả các nút
public void addButtonListener(ActionListener listener) {
for (JButton button : buttons) {
button.addActionListener(listener);
}
}
}
package ll;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class CalculatorController {
private CalculatorModel model;
private CalculatorView view;
private String currentExpression = "";
private boolean resultDisplayed = false;
public CalculatorController(CalculatorModel model, CalculatorView view) {
this.model = model;
this.view = view;
view.addButtonListener(new ButtonClickListener());
}
private class ButtonClickListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
handleButtonPress(e.getActionCommand());
}
}
private void handleButtonPress(String command) {
if (command.matches("\\d") || command.equals(".")) {
handleNumberInput(command);
} else {
switch (command) {
case "C":
clearAll();
break;
case "←":
deleteLastDigit();
break;
case "=":
performCalculation();
break;
case "H":
showHelp();
break;
case "√":
case "^":
case "%":
handleSpecialOperator(command);
break;
default:
handleOperator(command);
}
}
}
// private void handleNumberInput(String input) {
// if (resultDisplayed) {
// currentExpression = input;
// resultDisplayed = false;
// } else {
// currentExpression += input;
// }
// view.getDisplayExpression().setText(currentExpression);
// }
private void handleNumberInput(String input) {
if (resultDisplayed) {
currentExpression = input;
resultDisplayed = false;
} else {
// Nếu trước đó là dấu ), thêm * trước số
if (!currentExpression.isEmpty()) {
char lastChar = currentExpression.charAt(currentExpression.length() - 1);
if (lastChar == ')') {
currentExpression += "*";
}
}
currentExpression += input;
}
view.getDisplayExpression().setText(currentExpression);
}
// private void handleSpecialOperator(String operator) {
// if (!currentExpression.isEmpty()) {
// switch (operator) {
// case "√":
// currentExpression = currentExpression +"*√(";
// break;
// case "^":
// currentExpression += "^";
// break;
// case "%":
// currentExpression += "%";
// break;
// }
// view.getDisplayExpression().setText(currentExpression);
// }else
// {
// if (operator.equals("√")) {
// currentExpression ="√(";
// view.getDisplayExpression().setText(currentExpression);
// };
//
// }
//
// }
// private void handleSpecialOperator(String operator) {
// if (!currentExpression.isEmpty()) {
// switch (operator) {
// case "√":
// currentExpression = currentExpression + "√(";
// break;
// case "^":
// currentExpression += "^";
// break;
// case "%":
// currentExpression += "%";
// break;
// }
// view.getDisplayExpression().setText(currentExpression);
// } else {
// if (operator.equals("√")) {
// currentExpression = "√(";
// view.getDisplayExpression().setText(currentExpression);
// }
// }
// }
private void handleSpecialOperator(String operator) {
if (operator.equals("√")) {
if (!currentExpression.isEmpty()) {
char lastChar = currentExpression.charAt(currentExpression.length() - 1);
// Nếu trước đó là số hoặc dấu ), thêm *√(
if (Character.isDigit(lastChar) || lastChar == ')') {
currentExpression += "*√(";
} else {
currentExpression += "√(";
}
} else {
currentExpression = "√(";
}
} else if (operator.equals("^")) {
currentExpression += "^";
} else if (operator.equals("%")) {
currentExpression += "%";
}
view.getDisplayExpression().setText(currentExpression);
}
private void clearAll() {
currentExpression = "";
resultDisplayed = false;
view.getDisplayExpression().setText("");
view.getDisplayResult().setText("");
}
private void deleteLastDigit() {
if (!currentExpression.isEmpty()) {
currentExpression = currentExpression.substring(0, currentExpression.length() - 1);
view.getDisplayExpression().setText(currentExpression);
}
}
private void performCalculation() {
if (!currentExpression.isEmpty()) {
try {
double result = model.calculate(currentExpression);
// view.getDisplayResult().setText(String.valueOf(result));
String formattedResult = (result == (long) result) ? String.format("%d", (long) result)
: String.valueOf(result);
view.getDisplayResult().setText(formattedResult);
resultDisplayed = true;
} catch (RuntimeException ex) {
view.getDisplayResult().setText("Lỗi");
System.err.println("Lỗi tính toán: " + ex.getMessage());
}
}
}
// private void handleOperator(String operator) {
//
// if (currentExpression.isEmpty()) {
// // Không cho bắt đầu bằng +, *, /
// if ("+*/".contains(operator))
// return;
// } else {
//
// // Lấy ký tự cuối
// char lastChar = currentExpression.charAt(currentExpression.length() - 1);
//
// // Nếu ký tự cuối là toán tử và người dùng lại bấm thêm toán tử (ngoại trừ mở
// // ngoặc)
// if ("+-*/".indexOf(lastChar) != -1 && !operator.equals("(")) {
// return;
// }
// if (currentExpression.matches("\\d") && operator.equals("(")){
// currentExpression = currentExpression+"*";
// }
// if (lastChar == ')') {
// currentExpression += "*";
// }
// }
//
// if (resultDisplayed) {
// currentExpression = String.valueOf(view.getDisplayResult().getText());
// resultDisplayed = false;
// }
// currentExpression += operator;
// view.getDisplayExpression().setText(currentExpression);
// }
private void handleOperator(String operator) {
if (currentExpression.isEmpty()) {
// Không cho bắt đầu bằng +, *, /
if ("+*/".contains(operator)) return;
} else {
// Lấy ký tự cuối
char lastChar = currentExpression.charAt(currentExpression.length() - 1);
// Không cho nhập 2 toán tử liên tiếp (trừ khi là "(" sau toán tử)
if ("+-*/".indexOf(lastChar) != -1 && !operator.equals("(")) {
return;
}
// Nếu nhập "(" sau số hoặc sau ")": thêm dấu nhân trước (
if (operator.equals("(") && (Character.isDigit(lastChar) || lastChar == ')')) {
currentExpression += "*";
}
}
// Nếu vừa hiển thị kết quả, dùng lại kết quả làm biểu thức mới
if (resultDisplayed) {
currentExpression = view.getDisplayResult().getText();
resultDisplayed = false;
}
currentExpression += operator;
view.getDisplayExpression().setText(currentExpression);
}
private void showHelp() {
view.getDisplayExpression().setText("Hướng dẫn: Nhập số và phép toán");
}
}
package ll;
import javax.swing.SwingUtilities;
public class CalculatorApp {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
CalculatorModel model = new CalculatorModel();
CalculatorView view = new CalculatorView();
new CalculatorController(model, view);
view.setVisible(true);
});
}
}
Không có nhận xét nào:
Đăng nhận xét