第二次作业-程序员宅基地

技术标签: git  java  c/c++  

git地址  https://github.com/JPL1988
git用户名  JPL1988
学号后5位 62131
博客链接 https://www.cnblogs.com/l123456l/p/10593365.html
作业链接 https://edu.cnblogs.com/campus/xnsy/SoftwareEngineeringClass1/homework/2793

Part 0. 背景

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

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

  • 程序接收一个命令行参数 n,然后随机产生 n 道加减乘除(分别使用符号+-*/来表示)练习题,每个数字在 0 和 100 之间,运算符在 2 个 到 3 个之间。
  • 由于阿超的孩子才上一年级,并不知道分数。所以软件所出的练习题在运算过程中不得出现非整数,比如不能出现 3÷5+2=2.6 这样的算式。
  • 练习题生成好后,将生成的 n 道练习题及其对应的正确答案输出到一个文件 subject.txt 中。
  • 当程序接收的参数为4时,以下为一个输出文件示例。

    13+17-1=29
    11*15-5=160
    3+10+4-16=1
    15÷5+3-2=4

这次阿超选择使用他最拿手的 C++ 语言来完成这样的需求,工欲善其事必先利其器,第一步就需要先安装一个好用的 IDE ,在这里我们推荐使用 Visual Studio 2017

代码设计思路

1.我通过random产生随机数和计算符,把每一个符号和数字存入字符串数组

2,把中缀表达式转为后缀表达式

3,,计算每个子表达式的值,若为负数或小数,删去整个表达式,重新取值。

程序代码

 

using System;
using System.Collections.Generic;
using System.Text;

namespace ConsoleApp1
{
    class wuyu
    {
        public static void Main(string[] args)
        {
            Program program = new Program();
            program.Calculation(10000000);
        }
    }
    public class Program
    {
        StringBuilder lastresult = new StringBuilder();
        caculator caculators = new caculator();
        private Random random = new Random();
        public void Calculation(int n)
        {
            for (int i = 0; i < n; i++)
            {
                int sign = random.Next(2, 3);              
                if (sign == 2)
                    Calculation2();
                else
                    Calculation3();
            }
            System.IO.File.WriteAllText("D://homework.txt",lastresult.ToString(),Encoding.Default);

        }
        private void Calculation3()
        {
            string[] s = new string[5];
            int d = random.Next(1, 101);
            char z = getchar();
            StringBuilder str = two(s);
            str.Append(z);
            str.Append(d);
            int result = caculators.compute(s);
            if (result == -1)
                Calculation3();
            else
            {
                str.Append('=');
                str.Append(result);
                str.Append(' ');
                lastresult.Append(str);
            }           
        }
        public void Calculation2()
        {
            string[] s = new string[5];
            StringBuilder str = two(s);
            int result =caculators.compute(s);
            if (result == -1)
                Calculation2();
            else
            {
                str.Append('=');
                str.Append(result);
                str.Append(' ');
                lastresult.Append(str);
            }           
        }

        private char getchar()
        {
            Char res = '+';
            int x = random.Next(0, 4);
            switch (x)
            {
                case 1:
                    break;
                case 2:
                    res = '-';
                    break;
                case 3:
                    res = '*';
                    break;
                default:
                    res = '/';
                    break;
            }
            return res;
        }       
        public StringBuilder two(string[] strings)
        {
            int a = random.Next(1, 101);
            int b = random.Next(1, 101);
            int c = random.Next(1, 101);
            char x = getchar();
            char y = getchar();
            StringBuilder str = new StringBuilder();
            strings[0] = a.ToString();
            strings[1] = x.ToString();
            strings[2] = b.ToString();
            strings[3] = y.ToString();
            strings[4] = c.ToString();
            str.Append(a);
            str.Append(x);
            str.Append(b);
            str.Append(y);
            str.Append(c);
            return str;
        }
    }

    public class caculator
    {
        private static string Operator = "+-*/";
        Queue<string> postfix;//队列储存后缀表达式
        Stack<string> stack;//栈储存计算后缀表达式时的数字
        public int compute(string[] s)
        {
            convert(s);//计算后缀表达式
            stack = new Stack<string>(7);
            int symbol;
            int length = postfix.Count;
            for (int i = 0; i < length; i++)
            {
                symbol = isOperator(postfix.Peek());
                if (symbol > -1)//是否为操作符
                {
                    postfix.Dequeue();//把操作符从队列里面移除
                    int d2 = int.Parse(stack.Pop());
                    int d1 = int.Parse(stack.Pop());//取出数据进行计算
                    int d3 = 0;
                    switch (symbol)
                    {
                        case 0:
                            d3 = d1 + d2;
                            break;
                        case 1://排除负数结果
                            d3 = d1 - d2;
                            if (d3 < 0)
                                return -1;
                            break;
                        case 2:
                            d3 = d1 * d2;
                            break;
                        case 3://排除小数结果
                            d3 = d1 / d2;
                            if (d3 * d2 != d1)
                                return -1;
                            break;
                    }
                    stack.Push(d3.ToString());//将计算结果压入数字栈
                }
                else
                {
                    stack.Push(postfix.Dequeue());//将数字压入数字栈
                }
            }
            return int.Parse(stack.Pop());//返回最终结果
        }


        public void convert(string[] strings)
        {
            postfix = new Queue<string>(strings.Length);
            stack = new Stack<string>(7);
            for (int i = 0; i < strings.Length; i++)
            {
                String tempc = strings[i];
                if (i % 2 == 1)//说明是操作符
                {
                    if (stack.Count == 0)//栈为空则将数据直接压入计算符栈
                    {
                        stack.Push(tempc);
                    }
                    else
                    {
     //栈不为空则和栈顶符号的优先级比较,将比当前优先级高的符号移除,并加进后缀表达式
                        while (stack.Count != 0 && priority(tempc, stack.Peek()))
                        {
                            postfix.Enqueue(stack.Pop());
                        }
                        stack.Push(tempc);//将当前符号压入栈顶
                    }
                }
                else
                {
                    postfix.Enqueue(tempc);//若是数字则直接加进后缀表达式
                }
            }
            while (stack.Count > 0)
            {
                postfix.Enqueue(stack.Pop());//将剩余操作符加进后缀表达式
            }
        }

        public int isOperator(string c)
        {
            return Operator.IndexOf(c);
        }

        public bool priority(String o1, String o2)
        {
            return getPriority(o1) <= getPriority(o2);
        }

        public int getPriority(String c)
        {
            switch (c)
            {
                case "+":
                case "-":
                    return 1;
                default:
                    return 2;
            }
        }
    }
}

 

 

 

Part 1. 配置环境

最开始安装成了企业版,然后有个插件安装失败,也不能使用,重装几次的时候发现装错了版本。

 

Part 2. 克隆项目

拷贝成功,我的用户名JPL1988

安装git,克隆到本地,最开始安装的Git的桌面版,然后重新装的bash版

 part3,单元测试

在单元测验时,遇到了一个较大的问题,那就是被测试的类如果确实静态Main方法无法被测试,报确实静态Main方法错误,但是由于之前做Java测试不需要Main方法。最后发现他人博客里的测试都要一个空类和空的Main方法,然后才测试成功。只是还不明白为什么,也没有查到。

单元测试运行

单元测试代码

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ConsoleApp1;

namespace UnitTestcalculator
{   
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            caculator ca = new caculator();
            string[] s = new string[] {
    "1","-","5","*","8" };
            Assert.IsTrue(ca.compute(s)==-1);
        }
        [TestMethod]
        public void TestMethod2()
        {
            caculator ca = new caculator();
            string[] s = new string[] { "1", "+", "5", "*", "8" };
            Assert.IsTrue(ca.compute(s) == 41);
        }
        [TestMethod]
        public void TestMethod3()
        {
            caculator ca = new caculator();
            string[] s = new string[] { "1", "/", "5", "*", "8" };
            Assert.IsTrue(ca.compute(s) == -1);
        }
        [TestMethod]
        public void TestMethod4()
        {
            caculator ca = new caculator();
            string[] s = new string[] { "5", "/", "1", "*", "8" };
            Assert.IsTrue(ca.compute(s) == 40);
        }
        [TestMethod]
        public void TestMethod5()
        {
            caculator ca = new caculator();
            string[] s = new string[] { "1", "*", "5", "+", "8" };
            Assert.IsTrue(ca.compute(s) == 13);
        }
    }
}

 

part4回归测试

回归测试我是和断点调试一起使用的,纠正了求值过程中的很多错误结果和判断。

 part5,断点调试

 在编写后缀表达式计算过程中多次使用了,断点调试,添加监视,由于对后缀表达式不熟悉,在进行运算后,没有吧运算符出队列。仔细琢磨了很久。

part6效能测试

根据效能分析可知,string.indexof,和int32.tostring花费时间较长。可以优化,其实可以考虑有switch代替indexof.

 part7,上传github

在第一次上传时,安装git add [D:\file]的提交方式出现错误,不需要加中括号

git提交时要把厂库里的所有更新文件都进行git add和git commit 否则在进行git status 验证时不会通过

 git push成功

 提交成功

 

part8. 感想

 由于之前做个Java单元测试,所以本次对于c#做单元测试中,被测试类需要一个main方法,不是很理解,我一直以为单元测试的地方就是程序入口。其次,github的使用不是很熟悉,项目由于我是在本地测试的所以没有在修改后就提交到git。本次实验我学会了后缀表达式求值,熟悉了对队列和栈的使用。

 

转载于:https://www.cnblogs.com/l123456l/p/10593365.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30378311/article/details/98548780

智能推荐

UIAutomator2.0详解(UIDevice篇----Wait)_uidevice wait-程序员宅基地

文章浏览阅读9.7k次,点赞2次,收藏7次。感觉拖了好久,今天将Wait接口的总结补上,顺便把SearchCondition也捎带结了。 直接上图。Wait方法含义:查看查询条件是否符合,若符合,则返回结果。若不符合,则继续等待,直至超时。 返回结果可能为UIObject2对象或者UIObject2对象列表,或者布尔类型。其中,传参SearchCondition是一个抽象类,若想获取其实体对象,需要调用Until工具类。 该类提供了4个_uidevice wait

SpringBoot——入门案例之“Hello SpringBoot“-程序员宅基地

文章浏览阅读8.1k次,点赞2次,收藏4次。SpringBoot——入门案例之“Hello SpringBoot“_hello springboot

Docker精华 ,超全文档!-程序员宅基地

文章浏览阅读1.2k次。我们的口号是:人生不设限!! 学习规划:继续上篇 《Docker入门》https://www.cnblogs.com/dk1024/p/13121389.html 继续讲解:一、容器数据卷1、什么是容器数据卷:Docker是将应用和环境打包成一个镜像,发布到服务器,这个跑起来的容器如果不小心删除掉,呢么数据就会全部丢失,尤其是Mysql之类的容器,name现在就有一个需求,数..._avtxt

Java高级特性之XML_java xml示“收藏信息.xml”文件中收藏的手机品牌和型号-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏15次。XML 简介、编写规范、Java 解析 XML(DOM 解析 XML、DOM4J 解析 XML)……关于 Java 高级特性之 XML 比较详细、系统的整理。_java xml示“收藏信息.xml”文件中收藏的手机品牌和型号

笔记:《高效能人士的七个习惯》第九章 习惯六 统合综效——创造性合作的原则_高效能人士的七个习惯 第九章统合综效-程序员宅基地

文章浏览阅读6.4k次。1、统合综效的基本心态是:如果一位具有相当聪明才智的人跟我意见不同,那么对方的主张必定有我尚未体会的奥妙,值得加以了解。2、与人合作最重要的是,重视不同个体的不同心理、情绪与智能,以及个人眼中所见到的不同世界。与所见略同的人沟通,益处不大,要有分歧才有收获。3、我以圣者的期望自勉:对关键事务——团结,对重大事务——求变,对所有事务——宽大。——美国前总统乔治.布什(George Bush)_高效能人士的七个习惯 第九章统合综效

【实用工具】几款常用GIS/测绘工具分享_坐标转换工具-程序员宅基地

文章浏览阅读846次。笑脸工具,用于坐标转换。_坐标转换工具

随便推点

基于法向量的点云分割方法及Matlab实现-程序员宅基地

文章浏览阅读36次。在本文中,我们介绍了基于法向量的点云分割方法,并提供了Matlab实现代码。该方法通过分析点云中的法向量信息,可以有效地划分点云数据集,识别出不同的表面和物体。基于法向量的点云分割方法将点云中的每个点的法向量信息作为关键特征来进行分割。基于法向量的点云分割方法将点云中的每个点的法向量信息作为关键特征来进行分割。该方法通过分析点云中的法向量信息,可以有效地划分点云数据集,识别出不同的表面和物体。点云分割是计算机视觉和模式识别领域的重要任务之一,它的目标是将点云数据集划分为具有不同属性或语义的子集。

【OpenVINO】C#调用OpenVINO部署Al模型项目开发-2.软件安装_vs2022如何安装openvino c# api-程序员宅基地

文章浏览阅读630次。C#调用OpenVINOTM部署Al模型项目开发项目,简称OpenVinoSharp,这是一个示例项目,该项目实现在C#编程语言下调用Intel推出的 OpenVINO 工具套件,进行深度学习等Al项目在C#框架下的部署。该项目由C++语言编写OpenVINO API接口,并在C#语言下实现应用。..._vs2022如何安装openvino c# api

Flyway提供的六种命令_flyway命令-程序员宅基地

文章浏览阅读2.4k次,点赞2次,收藏4次。Flyway对数据库进行版本管理主要由Metadata表(默认是flyway_schema_history)和6种命令完成,Metadata主要用于记录每次执行的脚本和version等信息,下面一一介绍。Metadata表(flyway_schema_history)Flyway中最核心的就是用于记录所有版本执行结果和状态的Metadata表,在Flyway首次启动时会创建默认名为flywa..._flyway命令

Android常见Crash介绍_android crash-程序员宅基地

文章浏览阅读1.8k次,点赞2次,收藏7次。Crash问题分析定位:通过Log文件夹下全局搜am_crash,此时会把log文件下下所有的包含am_crash的行显示出来一.导致Android Crash 问题的主要类型4)Other由上图可见,在APP层面我们出现并能解决的BUG 集中在App Crash 和System crash 层;_android crash

curl 访问https接口_php使用curl获取https请求的方法-程序员宅基地

文章浏览阅读1.1k次。这篇文章主要介绍了php使用curl获取https请求的方法,涉及curl针对https请求的操作技巧,非常具有实用价值,需要的朋友可以参考下本文实例讲述了php使用curl获取https请求的方法。分享给大家供大家参考。具体分析如下:今日在做一个项目,需要curl获取第三方的API,对方的API是https方式的。之前使用curl能获取http请求,但今天获取https请求时,出现了以下的错误提..._curl 访问 api ssl

Redis cluster集群搭建_redis cluster 搭建-程序员宅基地

文章浏览阅读1.1k次,点赞23次,收藏21次。1.2数据存储采用分片存储方式,整个redis集群有16384个哈希槽,集群中的每个节点负责一部分哈希槽,现在集群中三个主节点,就会把这些哈希槽平均分配给三个主节点,即节点A存储的哈希槽范围是:0 – 5500,节点B存储的哈希槽范围是:5501 – 11000,节点C存储的哈希槽范围是:11001 – 16384,当需要扩容主节点时会将ABC的哈希槽数据提取一部分到新的主节点D上,若是删除主节点A,就需要先将A中的哈希槽数据转移到BC节点上再进行删除。因为redis是用c实现的,所有要进行编译操作;_redis cluster 搭建

推荐文章

热门文章

相关标签