用Java把记事本中的算式进行逐行读取并计算结果

吹泡泡捏 2019-12-28 10:06:27
在Java中编了个简单的计算器,然后我想在TXT文档中输入一列算式,例如“2+3=”这种算式,然后怎样能够直接从TXT文档中逐行读取,并且用编的计算器计算出结果,我是初学者,请求大神
...全文
206 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
KeepSayingNo 2020-01-06
  • 打赏
  • 举报
回复
你这个考察2点
1. 读取文件,用inputstream读取文件流
2. 栈的使用,每个字符要采用入栈和出栈实现计算
三仙半 2019-12-29
  • 打赏
  • 举报
回复
楼上说得对啊,按行读取txt文件不是大问题,关键是字符串的解析。下面是一个读txt文件的范例:

BufferedReader br = new BufferedReader(new FileReader(new File(path)));
String line = br.readLine();
while (line != null) {
System.out.println(line);
line = br.readLine();
}
br.close();

作为计算器输入字符串的解析,其本质上是一个中缀表达式转前缀表达式的过程,下面是这个过程的描述,仅供参考:
1)求输入串的逆序。
2)检查输入的下一元素。
3)假如是操作数,把它添加到输出串中。
4)假如是闭括号,将它压栈。
5)假如是运算符,则
i)假如栈空,此运算符入栈。
ii)假如栈顶是闭括号,此运算符入栈。
iii)假如它的优先级高于或等于栈顶运算符,此运算符入栈。
iv)否则,栈顶运算符出栈并添加到输出串中,重复步骤5。
6)假如是开括号,栈中运算符逐个出栈并输出,直到遇到闭括号。闭括号出栈并丢弃。
7)假如输入还未完毕,跳转到步骤2。
8)假如输入完毕,栈中剩余的所有操作符出栈并加到输出串中。
9)求输出串的逆序。
mr_foxsand 2019-12-29
  • 打赏
  • 举报
回复
初学的都上手这么有难度的问题,厉害啊! 你这个问题难点不在于读取文件内容以及算术运算,难点在于去解析字符串内容!你这要写一堆拆分字符串的规则。
三仙半 2019-12-29
  • 打赏
  • 举报
回复
写了一个简单的四则运算实现,不支持单目操作符“-”,不支持浮点数,没有什么实际意义,只是回忆一下相关知识点。

import java.util.HashMap;
import java.util.Map;
import java.util.Stack;

public class Calculator {

private static final Map<String, Integer> OP_LEVEL = new HashMap<>();
static {
OP_LEVEL.put("+", 1);
OP_LEVEL.put("-", 1);
OP_LEVEL.put("*", 2);
OP_LEVEL.put("/", 2);
OP_LEVEL.put("(", 3);
OP_LEVEL.put(")", 3);
}

public static void main(String[] args) {
// String src = "10+20*(5+6)-70+6/3";
String src = "16/2+(9-4)*17";
Calculator c = new Calculator();
System.out.println(src + "=" + c.calc(src));
}

/**
* 对输入字符串执行简单四则运算
*
* @param ex
* 四则运算表达式
* @return
*/
public double calc(String ex) {
// 1)求输入串的逆序。
ex = reverse(ex);

// 一步循环中要处理的字符
char ch;
// 用于保存数字的临时变量
StringBuilder builder = new StringBuilder();
// 操作数栈
Stack<Double> operand = new Stack<>();
// 运算符栈
Stack<Character> operator = new Stack<>();
// 执行单步运算的临时变量(操作数1,操作数2,中间结果)
double num1, num2, tmp;
// 执行单步操作的运算符
char op;

// 2)检查输入的每一个字符
for (int i = 0; i < ex.length(); i++) {
ch = ex.charAt(i);
if (isNumber(ch)) {
// 3)假如是数字,保存到临时变量中。
// 因为字符串逆序导致数字也是倒序的,所以,在将字符添加到StringBuilder中时,总是增加到头部。
builder.insert(0, ch);
} else {
// 如果保存数字的临时变量不空,则将它转成Double值,压入操作数栈中。
if (builder.length() > 0) {
operand.push(Double.parseDouble(builder.toString()));
builder = new StringBuilder();
}
if (ch == ')') {
// 4)假如是闭括号,将它压栈。
operator.push(ch);
} else {
if (isOperator(ch)) {
// 5)假如是运算符,则
if (operator.isEmpty()) {
// i)假如栈空,此运算符入栈。
operator.push(ch);
} else if (operator.peek() == ')') {
// ii)假如栈顶是闭括号,此运算符入栈。
operator.push(ch);
} else if (compareOperator(ch, operator.peek()) >= 0) {
// iii)假如它的优先级高于或等于栈顶运算符,此运算符入栈。
operator.push(ch);
} else {
// iv)否则,栈顶运算符出栈执行运算,重复步骤5。
while (!operator.isEmpty() && compareOperator(ch, operator.peek()) < 0) {
num1 = operand.pop();
num2 = operand.pop();
op = operator.pop();
tmp = step(op, num1, num2);
operand.push(tmp);
}
operator.push(ch);
}

} else {
if (ch == '(') {
// 6)假如是开括号,栈中运算符逐个出栈执行运算,直到遇到闭括号,闭括号出栈并丢弃。
while (operator.peek() != ')') {
num1 = operand.pop();
num2 = operand.pop();
op = operator.pop();

tmp = step(op, num1, num2);
operand.push(tmp);
// 直到运算符栈为空,还没有见到‘闭括号’,证明表达式格式有问题:括号不配对。
if (operator.isEmpty()) {
throw (new Error("四则运算表达式中存在不匹配的括号!"));
}
}
operator.pop();
} else {
// 存在不是括号、不是运算符、不是数字的字符
throw (new Error("四则运算表达式中存在非法字符!"));
}
}
}
}
}
if (builder.length() > 0) {
operand.push(Double.parseDouble(builder.toString()));
}
// 8)输入串处理完毕,栈中剩余的所有操作符出栈执行运算。
while (!operator.isEmpty()) {
num1 = operand.pop();
num2 = operand.pop();
op = operator.pop();
tmp = step(op, num1, num2);
operand.push(tmp);
}

return operand.pop();
}

/**
* 求输入串的逆序
*
* @param src
* @return
*/
private String reverse(String src) {
StringBuilder builder = new StringBuilder(src);
builder.reverse();
return builder.toString();
}

/**
* 判断一个字符是否为运算符
*
* @param ch
* @return
*/
private boolean isOperator(char ch) {
char[] operators = new char[] { '+', '-', '*', '/' };
for (int i = 0; i < operators.length; i++) {
if (ch == operators[i]) {
return true;
}
}
return false;
}

/**
* 判断字符是否是数字
*
* @param ch
* @return
*/
private boolean isNumber(char ch) {
return ch > 47 && ch < 58;
}

/**
* 比较运算符的优先级
*
* @param op1
* 运算符1
* @param op2
* 运算符2
* @return 1(运算符1优先级高)/0(二者优先级相同)/-1(运算符2优先级高)
*/
private int compareOperator(char op1, char op2) {
int op1_level = OP_LEVEL.get(op1 + "");
int op2_level = OP_LEVEL.get(op2 + "");
if (op1_level > op2_level) {
return 1;
} else if (op1_level < op2_level) {
return -1;
} else {
return 0;
}
}

/**
* 执行一步运算
*
* @param op
* 运算符
* @param num1
* 操作数1
* @param num2
* 操作数2
* @return
*/
private double step(char op, double num1, double num2) {
switch (op) {
case '+':
return num1 + num2;
case '-':
return num1 - num2;
case '*':
return num1 * num2;
case '/':
return num1 / num2;

default:
if (op == ')') {
throw (new Error("四则运算表达式中存在不匹配的括号!"));
} else {
throw (new Error("四则运算表达式中存在非法的字符!"));
}
}
}
}

58,441

社区成员

发帖
与我相关
我的任务
社区描述
Java Eclipse
社区管理员
  • Eclipse
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧