软工第二次作业——熟悉使用工具

GIT地址 我的GITHUB地址
GIT用户名 NyimaC
学号后五位 61111
博客地址 我的博客地址
作业链接 链接

Part1.环境配置

因为之前已经用JAVA写过程序,所以环境是已经配好了的,在此没有遇到太大的问题。
JAVA版本是JAVA8.0 编译器使用的是IDEA


Part2.代码编写

编码题目:

阿超家里的孩子上小学一年级了,这个暑假老师给家长们布置了一个作业:家长每天要给孩子出一些合理的,但要有些难度的四则运算题目,并且家长要对孩子的作业打分记录。

作为程序员的阿超心想,既然每天都需要出题,那何不做一个可以自动生成小学四则运算题目与解决题目的命令行 “软件”呢。他把老师的话翻译一下,就形成了这个软件的需求:

程序接收一个命令行参数 n,然后随机产生 n 道加减乘除(分别使用符号+-*/来表示)练习题,每个数字在 0 和 100 之间,运算符在 2 个 到 3 个之间。

由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中不得出现非整数,比如不能出现 3÷5+2=2.6 这样的算式。

练习题生成好后,将生成的 n 道练习题及其对应的正确答案输出到一个文件 subject.txt 中。

使用语言:JAVA

与题目不同的地方的声明:

1、运算符存在差异。题目上的是(+-*/) 我的是(+-×÷)

2、我的文件名为“题目.txt”

编码思路:

思维导图:

代码部分(主要部分):

"Talk is cheap. Show me the code."

结构

生成题目的类

public class FormulaMakerTest {
/**
 * 生成题目的类
 */

public LinkedList<String> questionMaker(int total)
{
	//用于存放生成的运算式
	String[] formulas = new String[total];
	LinkedList<String> questionList = new LinkedList<>();
	Numbers numbers = new Numbers();
	OperationImpl operation = new OperationImpl();
	OperationStringImpl operationString = new OperationStringImpl();

	//循环开始的参数(一个用于外循环,一个用于循环)
	int start1;
	int start2;
	//用于保存每次运算的结果
	int result;
	//用于标识运算是否会出现小数
	int judge = 0;
	for(start1=0; start1<total; start1++) {
		//标识结果集的下标
		//生成随2~3个的运算符
		numbers.operationNumber = (int)(2+Math.random()*(3-2+1));
		//存放每次运算的结果集
		//生成3~4个参与运算的数字
		numbers.numbers = new Integer[numbers.operationNumber+1];
		for(start2=0; start2<=numbers.operationNumber; start2++) {
			numbers.numbers[start2] = (int)(0+Math.random()*(100-0+1));
		}
		//生成运算符
		numbers.operations = new Integer[numbers.operationNumber];
		for(start2=0; start2<numbers.operationNumber; start2++) {
			numbers.operations[start2] = (int)(1+Math.random()*(4-1+1));
		}
		//运算此表达式的运算结果(重点)
		//1、判断此算式是否满足条件(主要看除法是否满足)
		for(start2=0; start2<numbers.operationNumber; start2++){
			if(numbers.operations[start2] == 4) {
				if(!operation.judgeDivision(numbers.numbers[start2], numbers.numbers[start2+1])) {
					//不满足 重新生成算式
					judge++;
				}else {
					continue;
				}
			}
		}
		//若满足除法后无小数,则此算式成立
		//算式中没有小数,可以生成表达式并打印
		if(judge == 0) {
			//算式中没有小数,可以生成表达式并打印
			formulas[start1] = operationString.operationSplicing(numbers.operationNumber, numbers.numbers, numbers.operations);
			System.out.println(formulas[start1]);
		}else {
			judge = 0;
			start1--;
			continue;
		}

		//调用计算函数计算结果
		CalculateMaker maker = new CalculateMaker();
		java.util.Queue<String> queue = new LinkedList<>();
		queue = maker.calculateResult(numbers.numbers, numbers.operations);
		result = maker.calculate(queue);
		formulas[start1] += String.valueOf(result);
		questionList.add(formulas[start1]);
	}
	return questionList;
	}
}

栈进行四则运算的类

public class CalculateMaker {
/**
 * 用于获得后缀表达式
 * @return
 */
public Queue<String> calculateResult(Integer[] num, Integer[] operations) {
	//用于存放之前的算式
	Queue<String> queue1 = new LinkedList<>();
	//用于存放后缀表达式
	Queue<String> queue2 = new LinkedList<>();
	int i;
	//把运算式放入队列
	for(i=0; i<num.length; i++) {
		queue1.offer(String.valueOf(num[i]));
		if(i<operations.length){
			switch (operations[i]){
				case 1:
					queue1.add("+");
					break;
				case 2:
					queue1.add("-");
					break;
				case 3:
					queue1.add("×");
					break;
				case 4:
					queue1.add("÷");
					break;
				default:
					break;
			}
		}
	}

	//用于存放运算符
	Stack<String> stack = new Stack<>();
	//用于标注队列中运算符的位置
	i = 2;
	while(!queue1.isEmpty()) {
		//此位置是运算符
		if(i%2==1) {
			i++;
			int num1, num2;
			//把运算符放进去
			if(stack.empty()) {
				stack.push(queue1.poll());
			}else {
				//取队首元素的值(用Unicode码来判断,加减号的值小于100,乘除号的值大于100)
				num1 = Translate.translateToInt(queue1.poll());
				if(num1<100) {
					while (!stack.isEmpty()) {
						queue2.offer(stack.pop());
					}
					stack.push(Translate.translateToString(num1));
				}else {
					num2 = Translate.translateToInt(stack.peek());
					if(num2<100) {
						stack.push(Translate.translateToString(num1));
					}else {
						queue2.offer(stack.pop());
						if(stack.isEmpty()) {
							stack.push(Translate.translateToString(num1));
						}else {
							while(!stack.isEmpty()) {
								if(stack.isEmpty()) {
									stack.push(Translate.translateToString(num1));
									break;
								}
								num2 = Translate.translateToInt(stack.peek());
								if(num2<100) {
									stack.push(Translate.translateToString(num1));
									break;
								}else {
									queue2.offer(stack.pop());
								}
							}
						}
					}
				}
			}
		}else {
			i++;
			queue2.offer(queue1.poll());
			if(queue1.isEmpty()){
				while(!stack.isEmpty()) {
					queue2.offer(stack.pop());
				}
			}
		}
	}
	//打印后缀表达式并返回
	return queue2;
}

/**
 * 根据后缀表达式计算结果
 * @param queue2
 * @return
 */
public int calculate(Queue queue2) {
	/**
	 * 用于进行后缀计算
	 */
	OperationImpl operation = new OperationImpl();
	//保存计算结果
	int x = 0;
	int y = 0;
	int result = 0;
	Stack<String> stack = new Stack<>();
	stack.push((String)queue2.poll());
	while(!queue2.isEmpty()) {

		String str = (String) queue2.poll();
        //遇到运算符,出栈运算,结果入栈
		if(!operation.judgeOperation(str)) {
			stack.push(str);
		}else {
				 y = Integer.valueOf(stack.pop());
				 x = Integer.valueOf(stack.pop());
				 result = operation.calculateNumber(x, y, str);
				 stack.push(String.valueOf(result));
				 //如果最终只有一个元素,则为计算的结果
				 if(stack.size() == 1 && queue2.isEmpty()) {
				 	return Integer.valueOf(stack.pop());
				}
		}
	}
	return y;
}

}

主函数

public static void main(String[] args) {
	//输入想要的题目数
	System.out.println("请输入想要创建题目的数目:");
	//生成题目的数目
	Scanner scanner = new Scanner(System.in);
	int total = scanner.nextInt();
	//生成题目生成器
	FormulaMakerTest maker = new FormulaMakerTest();
	//题目集
	LinkedList<String> questionList = 	maker.questionMaker(total);
	System.out.println(questionList);
	//将题目存入文件中
	FileWriting writing = new FileWriting();
	writing.WriteStringToFile(questionList);
}

控制台打印的题目

文件中保存的题目


Part3.使用github克隆项目以及提交代码

下载与安装

官网上下确实有点慢,找同学要的其他资源下的。

配置个人信息

指令:

git config --global user.name "用户名"

git config --global user.email 邮箱

克隆项目

进入这里
点这里,复制这里的url

在Git的文件夹下创建一个新的文件夹,在新的文件夹内右键选择Git Bash Here, 然后再在界面上输入git clone + 刚才复制网址,即 https://github.com/Cherish599/AchaoCalculator

提交代码

成功后便会多出一个文件夹,在里面创建一个和自己github用户名一致的文件,将程序源码放进去。

然后转到AchaoCalculator文件目录下(cd 文件的路径)
然后输入git add . , 再输入git commit -m "分支名称",最后输入 输入 git push,在这里会弹出框让你输入GitHub的用户名和密码即可

最后在GitHub上就能看到你提交的文件啦

遇到的问题

1、第一次接触GitHub,大多是看着教程操作的,以后需要多多熟悉

2、很多指令不熟悉,有的教程上的地方我用起来会出现错误,在其他地方找了解决的办法


Part4.单元测试

因为在编程过程中有很多需要单元测试的地方,也有很多bug需要及时修改,所以没有细致的记录,在此简单的描述一下

JAVA的单元测试可以基于Junit,并需要在测试的方法前加上@Test注解且测试方法不能存在参数

同时也可以基于main()方法来测试,并在需要的地方输出语句

主要遇到的问题

1、表达式的生成(字符串的拼接)出现错误。因为运算符是运用1~4的随机数来保存的,所以生成算式时需要转化为加减乘除对应的符号,思考后得以解决。

2、后缀表达式生成出现错误。因为对中缀表达式转化为后缀表达式的理解还存在一些偏差。在仔细阅读概念,并不断得打印后缀表达式后,找出了代码中出现的问题,最后得以解决

3、得到后缀表达式后计算结果出现错误。后缀表达式存在一个队列中,队列中元素的出队,以及数字元素的压栈、出栈操作出现问题。在条件语句中多次进行打印操作后,找出了错误出现的位置,找到原因,最终得以解决。

4、如果除法存在小数如何解决。我才用的方法是将此次循环作废,即将循环因子的值减一,并不进行拼接操作。


Part5.回归测试

单元测试时会存在许多问题,解决了这些问题,也就是进行了回归测试,同样在编程过程中有很多的回归测试,所以没有过多去记录

这是进行单元测试后,再进行回归测试才得出的判断运算结果是否为小数的方法。

得出的判断方法:看两个整数相除后的结果与其强转成浮点型后的结果是否一样,一样则是整数,反之则是小数


Part6.总结

说实话感觉这次作业还是很有难度的。主要是编写代码部分就需要大量的时间与精力。数据结构在学栈的部分学习过四则运算优先级判断,但是当时没有用代码实现,所以还花时间去学习了一下。

学习Git的使用过程中,好在有很多文章可以参考,虽然陌生但是操作起来还是比较容易。

环境因为是以前就配好的,同时单元测试和回归测试其实在代码的编写中以及有所使用了,这方面进行的还是比较顺利。

总之这次作业还是让我收获颇丰,无论是对编程语言JAVA,还是数据结构中栈和队列,以及Git的使用都得到了很好的练习

posted @ 2019-09-18 10:21  NyimaC  阅读(394)  评论(4编辑  收藏  举报