结对项目
结对项目
课程链接 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34 |
---|---|
作业要求 | https://edu.cnblogs.com/campus/gdgy/CSGrade22-34/homework/13230 |
作业目标 | 实现四则运算程序,掌握结对合作完成项目的技巧 |
成员1 | 沈思敏 3122004877 |
成员2 | 郑灿嘉 3122004887 |
github地址
https://github.com/SiMON-Shen11/FormulCalculate
PSP表格
psp2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 80 | 80 |
Estimate | 估计这个任务需要多少时间 | 40 | 40 |
Development | 开发 | 250 | 250 |
Analysis | 需求分析 (包括学习新技术) | 40 | 50 |
Design Spec | 生成设计文档 | 20 | 30 |
Design Review | 设计复审 | 20 | 20 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 10 | 10 |
Design | 具体设计 | 50 | 70 |
Coding | 具体编码 | 100 | 90 |
Code Review | 代码复审 | 10 | 10 |
Test | 测试(自我测试,修改代码,提交修改) | 60 | 120 |
Reporting | 报告 | 30 | 50 |
Test Repor | 测试报告 | 10 | 20 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 30 |
合计 | 770 | 880 |
程序结构及效能分析
式子生成—代码覆盖率
式子生成—方法调用频率、内存分配
答案检查—代码覆盖率
答案检查—方法调用频率、内存分配
代码说明
MyApp类实现输入、输出
`public static void creatFormalu() {
System.out.print("请输入生成的题目数:");
int num = scanner.nextInt();
System.out.print("请输入生成的最大的数值:");
int max = scanner.nextInt();
UtilClass.deleteFile("Exercises.txt");
UtilClass.deleteFile("Answers.txt");
FormulaBuilder.startCreate(num, max);
System.out.print("题目生成完毕");
}
public static void checkFormula() {
System.out.print("请输入Exercises.txt的文件路径:");
String exePath = scanner.next();
System.out.print("请输入Answers.txt文件路径:");
String workPath = scanner.next();
UtilClass.deleteFile("Correct.txt");
UtilClass.deleteFile("Grade.txt");
FormulaBuilder.startCheck(exePath, workPath);
System.out.print("答案校对完毕");
}`
UtilClasss类
LCM求公倍数
public static int GCD(int first, int second) {
int remainder;
if (first < second) {
remainder = first;
first = second;
second = remainder;
}
for(remainder = first % second; remainder != 0; remainder = first % remainder) {
first = second;
second = remainder;
}
return second;
}
public static int LCM(int first, int second) {
int gcd = GCD(first, second);
return first * second / gcd;
}`
中缀后缀表达式求值
`
public static String trunToSuffixString(String infixString) {
String[] split = infixString.split(" ");
List<String> list = new ArrayList();
String[] var3 = split;
int var4 = split.length;
String item;
for(int var5 = 0; var5 < var4; ++var5) {
item = var3[var5];
list.add(item);
}
Stack<String> s1 = new Stack();
List<String> s2 = new ArrayList();
Iterator var10 = list.iterator(); while(true) {
while(var10.hasNext()) {
item = (String)var10.next();
if (isElement(item)) {
s2.add(item);
} else if (item.equals("(")) {
s1.push(item);
} else if (item.equals(")")) {
while(!((String)s1.peek()).equals("(")) {
s2.add((String)s1.pop());
}
s1.pop();
} else {
while(!s1.empty() && UtilClass.Operation.getPrio(item) <= UtilClass.Operation.getPrio((String)s1.peek())) {
s2.add((String)s1.pop());
}
s1.push(item);
}
}
while(!s1.empty()) {
s2.add((String)s1.pop());
}
String suffixString = new String();
String item;
for(Iterator var12 = s2.iterator(); var12.hasNext(); suffixString = suffixString + item + " ") {
item = (String)var12.next();
}
return suffixString;
}
}
public static String getResult(String suffixString) {
String[] split = suffixString.split(" ");
List<String> list = new ArrayList();
String[] var3 = split;
int var4 = split.length;
for(int var5 = 0; var5 < var4; ++var5) {
String ele = var3[var5];
list.add(ele);
}
Stack<String> stack = new Stack();
Iterator var10 = list.iterator();
while(var10.hasNext()) {
String item = (String)var10.next();
if (isElement(item)) {
stack.push(item);
} else {
Element num2 = Element.parseElement((String)stack.pop());
Element num1 = Element.parseElement((String)stack.pop());
String res = null;
if (item.equals("+")) {
res = num1.add(num2).toString();
} else if (item.equals("-")) {
res = num1.sub(num2).toString();
} else if (item.equals("×")) {
res = num1.mul(num2).toString();
} else if (item.equals("÷")) {
res = num1.div(num2).toString();
} else {
System.out.println("运算符输入错误");
}
stack.push(res);
}
}
return (String)stack.pop();
}`
标准化输出答案
`
public static String standard(String firstResult) {
Element element = Element.parseElement(firstResult);
if (element.isDivision()) {
if (element.getDowm() == 0 || element.getUp() == 0) {
return "0";
}
int times;
if (element.getUp() != 0 && GCD(element.getUp(), element.getDowm()) != 1) {
times = GCD(element.getUp(), element.getDowm());
element.setUp(element.getUp() / times);
element.setDowm(element.getDowm() / times);
}
if (element.getUp() * element.getDowm() < 0 && element.getUp() > 0) {
element.setUp(element.getUp() * -1);
element.setDowm(element.getDowm() * -1);
}
if (element.getUp() >= element.getDowm()) {
times = element.getUp() / element.getDowm();
element.setUp(element.getUp() - times * element.getDowm());
if (element.getUp() == 0) {
return "" + times;
}
return "" + times + "'" + element.toString();
}
if (element.getDowm() == 1) {
element.setDivision(false);
}
}
return element.toString();
}
`
FormulaBuilder类执行运算式子的生成和修饰
`
public class FormulaBuilder {
private static Random random = new Random();
private static StringBuilder sb = new StringBuilder(64);
public FormulaBuilder() {
}
public static void startCreate(int num, int max) {
Formula[] formulas = new Formula[num];
for(int i = 0; i < num; ++i) {
Formula sigleFormula = new Formula(max);
UtilClass.wirteTxt("Exercises.txt", sigleFormula.getSb().toString() + "\n");
UtilClass.wirteTxt("Answers.txt", i + 1 + "." + sigleFormula.getResult() + "\n");
}
}
public static void startCheck(String exePath, String workPath) {
String exeString = UtilClass.readTxt(exePath);
String[] exeSpilt = exeString.split(" =");
exeSpilt[0] = exeSpilt[0].replace("null", "");
int index = 1;
String[] var6 = exeSpilt;
int var7 = exeSpilt.length;
for(int var8 = 0; var8 < var7; ++var8) {
String item = var6[var8];
String record = UtilClass.standard(UtilClass.getResult(UtilClass.trunToSuffixString(item)));
int var10001 = index++;
UtilClass.wirteTxt("Correct.txt", "" + var10001 + "." + record + "\n");
}
String ansString = UtilClass.readTxt(workPath);
String[] ansSpilt = ansString.split("[.]");
String corString = UtilClass.readTxt("Correct.txt");
String[] corSpilt = corString.split("[.]");
List<Integer> rightList = new ArrayList();
List<Integer> wrongList = new ArrayList();
for(int i = 1; i < corSpilt.length; ++i) {
if (ansSpilt[i].equals(corSpilt[i])) {
rightList.add(i);
} else {
wrongList.add(i);
}
}
String gradeContent;
for(gradeContent = "Correct:" + rightList.size() + " ("; !rightList.isEmpty(); gradeContent = gradeContent + String.valueOf(rightList.remove(0)) + ",") {
}
if (gradeContent.charAt(gradeContent.length() - 1) == ',') {
gradeContent = gradeContent.substring(0, gradeContent.length() - 1);
}
for(gradeContent = gradeContent + ")\nWrong: " + wrongList.size() + " ("; !wrongList.isEmpty(); gradeContent = gradeContent + String.valueOf(wrongList.remove(0)) + ",") {
}
if (gradeContent.charAt(gradeContent.length() - 1) == ',') {
gradeContent = gradeContent.substring(0, gradeContent.length() - 1);
}
gradeContent = gradeContent + ")";
UtilClass.wirteTxt("Grade.txt", gradeContent);
}
}
`
Element类管理分数并提供相应计算方法
`
public class Element {
private boolean isDivision = false;
private static Random random = new Random();
private int max;
private int up;
private int dowm = -1;
public Element() {
}
public Element(boolean isDivision, int max) {
this.isDivision = isDivision;
this.max = max;
if (isDivision) {
this.dowm = random.nextInt(max - 2) + 2;
this.up = random.nextInt(this.dowm - 1) + 1;
} else {
this.dowm = -1;
this.up = random.nextInt(max - 1) + 1;
}
}
public Element add(Element anotherElement) {
if (this.isDivision && anotherElement.isDivision) {
try {
int sameDown = UtilClass.LCM(this.getDowm(), anotherElement.getDowm());
this.up = this.up * sameDown / this.dowm;
this.dowm = sameDown;
anotherElement.up = anotherElement.up * sameDown / anotherElement.dowm;
anotherElement.dowm = sameDown;
} catch (Exception var3) {
PrintStream var10000 = System.out;
int var10001 = this.getDowm();
var10000.println("" + var10001 + " " + anotherElement.getDowm());
}
this.up += anotherElement.up;
return this;
} else if (!this.isDivision && !anotherElement.isDivision) {
this.up += anotherElement.up;
return this;
} else if (this.isDivision) {
this.up += anotherElement.up * this.dowm;
return this;
} else {
anotherElement.up += this.up * anotherElement.dowm;
return anotherElement;
}
}
public Element sub(Element anotherElement) {
if (this.isDivision && anotherElement.isDivision) {
try {
int sameDown = UtilClass.LCM(this.getDowm(), anotherElement.getDowm());
this.up = this.up * sameDown / this.dowm;
this.dowm = sameDown;
anotherElement.up = anotherElement.up * sameDown / anotherElement.dowm;
anotherElement.dowm = sameDown;
} catch (Exception var3) {
PrintStream var10000 = System.out;
int var10001 = this.getDowm();
var10000.println("" + var10001 + " " + anotherElement.getDowm());
}
this.up -= anotherElement.up;
return this;
} else if (!this.isDivision && !anotherElement.isDivision) {
this.up -= anotherElement.up;
return this;
} else if (this.isDivision) {
this.up -= anotherElement.up * this.dowm;
return this;
} else {
this.isDivision = true;
this.up = this.up * anotherElement.dowm - anotherElement.up;
this.dowm = anotherElement.dowm;
return this;
}
}
public Element mul(Element anotherElement) {
if (this.isDivision && anotherElement.isDivision) {
this.up *= anotherElement.up;
this.dowm *= anotherElement.dowm;
return this;
} else if (!this.isDivision && !anotherElement.isDivision) {
this.up *= anotherElement.up;
return this;
} else if (this.isDivision) {
this.up *= anotherElement.up;
return this;
} else {
anotherElement.up *= this.up;
return anotherElement;
}
}
public Element div(Element anotherElement) {
if (this.isDivision && anotherElement.isDivision) {
this.up *= anotherElement.dowm;
this.dowm *= anotherElement.up;
return this;
} else if (!this.isDivision && !anotherElement.isDivision) {
this.isDivision = true;
this.dowm = anotherElement.up;
return this;
} else if (this.isDivision) {
this.dowm *= anotherElement.up;
return this;
} else {
anotherElement.dowm *= this.up;
return anotherElement;
}
}
public static Element parseElement(String str) {
Element ele = new Element();
if (str.matches("-?\\d+/-?\\d+")) {
ele.isDivision = true;
String[] split = str.split("/");
ele.up = Integer.parseInt(split[0]);
ele.dowm = Integer.parseInt(split[1]);
} else {
ele.isDivision = false;
ele.up = Integer.parseInt(str);
}
return ele;
}
public String toString() {
return this.isDivision ? this.up + "/" + this.dowm : "" + this.up;
}
public int getMax() {
return this.max;
}
public void setMax(int max) {
this.max = max;
}
public int getUp() {
return this.up;
}
public void setUp(int up) {
this.up = up;
}
public int getDowm() {
return this.dowm;
}
public void setDowm(int dowm) {
this.dowm = dowm;
}
public boolean isDivision() {
return this.isDivision;
}
public void setDivision(boolean division) {
this.isDivision = division;
}
}
`
测试运行结果
题目及答案
项目总结
- 在本项目中,我们成功实现了一个命令行程序,能够根据用户指定的数量和范围自动生成小学四则运算题目,并记录相关答案。程序功能完整,确保题目计算过程不产生负数,设计了用户友好的命令行参数,使得生成过程简便高效。此外,题目和答案被有效存储在文本文件中,便于阅卷和统计,增强了程序的可扩展性,满足了不同用户的需求。
- 在实施过程中,我们遇到了一些挑战,包括逻辑复杂性、性能优化的时间消耗和团队协作的挑战。通过有效的沟通和代码审查,我们克服了这些问题,提升了工作效率。此次经历不仅增强了我们的编程能力,也让我们认识到良好沟通、合理时间管理和关注细节的重要性。未来,我们将继续保持这种合作精神,追求更高的项目质量。