第二次作业-熟悉使用工具
GIT地址 | https://github.com/cddchen |
GIT用户名 | cddchen |
学号后五位 | 62232 |
博客地址 | https://www.cnblogs.com/cddchen/ |
作业链接 | https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/homework/2793 |
一.作业导读
阿超家里的孩子上小学一年级了,这个暑假老师给家长们布置了一个作业:家长每天要给孩子出一些合理的,但要有些难度的四则运算题目,并且家长要对孩子的作业打分记录。
作为程序员的阿超心想,既然每天都需要出题,那何不做一个可以自动生成小学四则运算题目与解决题目的命令行 “软件”呢。他把老师的话翻译一下,就形成了这个软件的需求:
-
程序接收一个命令行参数 n,然后随机产生
n
道加减乘除(分别使用符号+-*/
来表示)练习题,每个数字在0
和100
之间,运算符在2
个 到3
个之间。 -
由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中不得出现非整数,比如不能出现
3÷5+2=2.6
这样的算式。 -
练习题生成好后,将生成的
n
道练习题及其对应的正确答案输出到一个文件subject.txt
中。
二.具体操作
1.安装VS2017,因为之前专业课已学习c#,故安装操作省略
2.注册github账号,并安装git软件
3.进入班级仓库https://github.com/Jupi4ter/AchaoCalculator,fork进自己的账号
4.使用git软件,命令git clone讲项目克隆到本地
5.在克隆的文件夹中新建自己github账号命名的文件夹用于创建C#项目
6.使用VS新建项目并使用算法和数据结构解决问题
(1)根据问题创建了Problem类
public class Problem
{
private int problem_cnt;
private Random rd = new Random();
private char[] op_int2char = { '+', '-', '*', '/' };
public Problem() {}
(2)根据输入数量生成问题,每次按要求随机产生2/3运算符,再调用生成单个等式函数
//创建等式函数
private void CreateEquation(int problem_cnt)
{
this.problem_cnt = problem_cnt;
for (int i = 0; i < this.problem_cnt; ++i)
{
int op_cnt = rd.Next(2, 4); //随机产生2-3个运算符
CreateNum(op_cnt); //调用生成问题函数
}
for(int i = 0; i < this.problem_cnt; ++i)
{
Console.WriteLine("{0}=", pro[i].equation);
}
Write2File();
}
}
(3)根据运算符数量生成运算符数量+1个数,且每个数在【1,100)之间;
计算式子结果时觉得采用将中缀表达式转换成后缀表达式计算并检查结果是否合法
private void CreateNum(int op_cnt)
{
while (true)
{
//生成等式
for (int i = 0; i < op_cnt; ++i)
{
op[i] = op_int2char[rd.Next(0, 4)];
arr[i] = rd.Next(1, 100);
}
arr[op_cnt] = rd.Next(1, 100);
SolveAndCheck(op_cnt); //调用解决并检查函数
}
}
(4)转换为后缀表达式后,计算结果并检查可行性,如果可行保存到结构体数组内
为了解决后缀表达式结点问题,使用了结构体保存不同的数据类型如整数、运算符。
public string SolveAndCheck(int op_cnt)
{
output.Clear();
stack.Clear();
st.Clear();
//转换为后缀表达式
for (int i = 0; i < op_cnt + 1; ++i)
{
output.Add(new node(false, arr[i], ' '));
if (i < op_cnt)
{
while (stack.Count != 0)
{
if (check(op[i], stack.Peek()))
{
output.Add(new node(true, 0, stack.Pop()));
}
else break;
}
stack.Push(op[i]);
}
}
if (stack.Count != 0) output.Add(new node(true, 0, stack.Pop()));
//检查等式是否合法
bool flg = true;
for (int i = 0; i < output.Count; ++i)
{
if (output[i].type == false) st.Push(output[i].val);
else
{
char op_type = output[i].op;
int a = st.Pop(), b = st.Pop();
int c = 0;
if (!cal(a, op_type, b, ref c))
{
flg = false;
break;
}
else st.Push(c);
}
}
if (flg)
{
string tit = arr[0].ToString();
for (int i = 0; i < op_cnt; ++i)
{
tit += op[i].ToString();
tit += arr[i + 1].ToString();
}
pro.Add(new problem(tit, st.Pop()));
return tit + "=" + pro.Last().ans.ToString();
}
return null;
}
计算结果时调用cal函数,并检查计算过程是否出现除0或小数情况
//计算并检查是否合法
private bool cal(int lef, char op, int rig, ref int ans)
{
if (op == '+') ans = lef + rig;
else if (op == '-') ans = lef - rig;
else if (op == '*') ans = lef * rig;
else
{
if (rig == 0) return false;
else if (lef % rig != 0) return false;
else ans = lef / rig;
}
return true;
}
(5)输出到终端后,按要求写入文件
//写入到文件
private void Write2File()
{
StreamWriter sw = new StreamWriter(@".\subject.txt", false, Encoding.UTF8);
foreach(problem p in pro) {
sw.WriteLine("{0}={1}", p.equation, p.ans);
}
sw.Close();
}
(6)调用problem类
class Program
{
static void Main(string[] args)
{
int n = int.Parse(Console.ReadLine());
Problem problem = new Problem();
problem.CreateEquation(n);
Console.Read();
}
}
(7)运行截图
7.设置单元测试
8.设置断点
9.设置条件断点
10.性能分析