现代软件工程讲义 个人项目和结对项目练习 四则运算

简介:

很多老师反映教软件工程和程序设计的时候没有合适的题目,下面一些题目,都是从简单的解题思路入手,逐步增量改进。学生们可以复习基本的编程技能,然后逐步加入模块化,文件处理,单元测试,信息隐藏,面向对象的分析,MVC 等概念和实践。  大家可以选用:

    - 黄金点游戏和单词频率问题

    - 四则运算练习

    - 计算程序文件的行数 (《构建之法》第二章)

    - 电梯调度

    - 网页前端技术的练习题

下面的题目, 从简单的数据结构开始,让同学们逐步练习。

 

第一步: 像《构建之法》的人物阿超那样,花二十分钟写一个能自动生成小学四则运算题目的命令行 “软件”, 分别满足下面的各种需求。

下面这些需求都可以用命令行参数的形式来指定:

a) 一次可以出一千道道题目,并且没有重复的,把题目写入一个文件中。我们大家都知道,(1+2) 和 (2+1) 是重复的题目。 高级要求: 怎么严格定义题目重复呢,请看详细题目要求

和同学们比较一下各自程序的功能、性能、实现方法的异同等等。

b) 当你有多于一个运算符的时候,如何对一个表达式求值?逐步扩展功能和可以支持的表达式类型,最后希望能支持下面类型的题目 (最多 10 个运算符,括号的数量不限制):

         25 - 3 * 4 - 2 / 2 + 89 = ?
     1/2 + 1/3 - 1/4 = ? 
    (5 - 4 ) * (3 +28) =?

提示:很多学生在开始的时候用简单的条件判断来处理运算,如果只有一个运算符,那还是比较简明的,运算符多了之后,怎么办呢?  一些学生就用很多条件判断来处理运算的优先级,这是某学生代码片段:

复制代码
复制代码
        public void jisuan(double a, string operation1,double b, string operation2,double c, string rightanswer)
        {
            bool aa = false;
            if (operation1 == "+" || operation1 == "-")
            {
                if (operation2 == "*" || operation2 == "/")
                {
                    aa = true;
                }
                else
                {
                    aa = false;
                }

            }
            else
            {
                aa = false;
            }
            if (aa == true)
...
复制代码
复制代码

那如果有 3 个运算符呢?怎么办,继续增加不同的 if/else 来解决?4个运算符呢?... 显然这不是一个好的算法, 一个好的算法,即使问题变得更复杂,算法本身应该依然是简明的, 并且程序本身的代码量并不会变得异常复杂。 我们看看有什么好的数据结构能高效地表示四则运算。

请参考调度场算法: 

          http://hczhcz.github.io/2014/02/27/shunting-yard-algorithm.html  

          https://en.wikipedia.org/wiki/Shunting-yard_algorithm  

 

c) 除了整数以外,还要支持真分数的四则运算。 (例如:  1/6 + 1/8 = 7/24  )

d) 让程序能接受用户输入答案,并判定对错。 最后给出总共 对/错 的数量。

e) 到目前为止,这个程序的界面都是中文的, 随着这个应用大受欢迎,别的国家的用户也要用,那么怎么能高效地让这个 App 支持不同文字界面互换呢?你是在程序里面不断插入 if ... else ... 来处理中英文,还是有高效率,可以扩展的办法?这个程序最终会扩展为支持10种语言,而且每个语言的用户需要符合他们文化的图标。请问你还是用 if/else 来解决么?

例如:你的程序已经支持了两种语言,并且中文界面有一个符合中国用户期望的图标,英文界面有一个符合美国用户期望的图标,  现在你要支持第三个语言 - 日文,并且需要一个符合日本用户的图标(假设是富士山的图像)。 然后还有另外 7 个语言 (德国、法国、意大利、...)和不同的图像要支持。那么,这可以用if/else 来解决, 还是有更高效的办法?

当显示文字直接放在代码中,例如像下面这样:

复制代码
if (isEnglish)

    UIControl.setText("Welcome to my calculator app");

else if (isChinese)

    UIControl.setText("欢迎使用我的四则运算程序");

else if ...
复制代码

 

这种用户显示的文字和代码逻辑放在一起的设计,我们称之为紧耦合。 程序员精通代码逻辑,但未必精通各国语言,也不太会设计各种图标,那我们会让懂法语和德语的团队成员(或者临时请来的专家)直接在代码上面改么?似乎他们会觉得代码编辑器的界面好难掌握哦... 改错了,程序编译不过去怎么办?我们可以想象,如果这些和逻辑无关的资源能够放在一个单独的地方, 这样负责文字和图像的人员(他们可能不太懂编程)能去修改,然后在主程序里,我们把各种语言的处理抽象为下面的操作:

    UIControl.setText(GetStringByLanguage(language_Id, string_id);   //根据当前显示的语言,拿到适当的文字,然后显示。 

 

这样会不会更好?逻辑代码和现实的资源各自分开, 通过良好定义的渠道(language_id, string_id) 结合起来了, 这是一种松耦合。 

程序可以用很多办法来提高效率保持简明:抽象 (把复杂的操作抽象为一个名字/类/函数,把复杂的处理隐藏在内),循环(高效地把类似的事情做 N 遍),递归(在处理问题的时候,发现这个子问题也是类似的,那我就调用自己来处理),组合(把各个操作组合起来完成复杂任务)... 等

    

第二步,增加一个运算符,程序应该有怎样的改变?不得不扔掉全部重写么,还是可以只改部分模块?

 

一些高年级的老师看到这个程序,希望让他们的同学也来用,但是有一个新需求, 要支持乘方 (power) 运算,我们都知道,乘方运算的优先级高于乘除法。如何表示乘方, 有两种表示方法:

 

1. 4 ^ 2 = 16,   4 的二次方等于 16。  这里, ^ 表示乘方

 

2. 4 ** 2 = 16,   4 的二次方等于16。这里, **  表示乘方 (** 之间不能有空格,否则是错误的算式)

 

由于历史的原因, 不同的学校用了不同的表示方法, 老师希望这两种表示方法都要支持,可以通过设置来选择。 

 

 

 

第三步,每个同学选一个方向,把程序扩展一下:

a) 把程序变成一个 Windows/Mac/Linux 电脑图形界面的程序 (取决于你目前使用的电脑),同时增加 “倒计时” 功能, 每个题目必须在 20 秒钟完成,如果完不成,则得0 分并进入下一题。增加“历史纪录” 功能, 把用户做题的成绩记录下来并可以展现历史记录。 

 

b) 把程序变成一个智能手机程序 (你正在用什么手机, 就写那个手机的程序), 增加倒计时,和历史纪录功能(见上)。

 

c) 把程序变成一个网页程序, 用户通过设定参数,就可以得到各种题目。

 

d) 选一个你从来没有学过的编程语言,试一试实现基本功能。

     估计做好这个软件需要的时间,并且写出大概的设计步骤和实现算法。

 

e)把这个程序的思路变成一个可以一步一步演示的动画。写一个带有图形界面的程序:

  输入:一个正常的四则运算句子

  输出:程序用动画表示分词的过程,后序转换的过程,处理不同运算符优先级的过程, 根据调度场工作的原理,逐步算出得出结果的过程。

         如果能做到这一步, 这个程序所牵涉到的 “知识点” 就能说 “精通” 了。

    

可以开始做相关的第二个作业

 

第三步,程序理解和扩展

我们说了程序要能输出不重复的题目,大家有不同的实现方法,那么能否比较一下各自的异同? 例如这个实现方法:

https://gist.github.com/vczh/2c058aed996effc0a519ed3d265a3eb5  

1) 能否读一下这个程序,注释一下它的核心设计是什么,写一篇博客分析一下?

2) 如果我们要让这个程序增加一个运算 -- 乘方运算。  你要在现有程序中做什么样的修改,才能让这个程序比较优雅地实现这个新的需求。 




本文转自SoftwareTeacher博客园博客,原文链接:http://www.cnblogs.com/xinz/p/7417960.html,如需转载请自行联系原作者

目录
相关文章
|
8月前
|
算法 程序员 Go
[软件工程导论(第六版)]第6章 详细设计(复习笔记)
[软件工程导论(第六版)]第6章 详细设计(复习笔记)
|
8月前
|
算法 图计算
[软件工程导论(第六版)]第6章 详细设计(课后习题详解)
[软件工程导论(第六版)]第6章 详细设计(课后习题详解)
|
4月前
|
存储
第六章:数组实训
第六章:数组实训
18 0
|
8月前
|
数据可视化 程序员 开发工具
[软件工程导论(第六版)]第1章 软件工程学概述(课后习题详解)
[软件工程导论(第六版)]第1章 软件工程学概述(课后习题详解)
|
8月前
|
数据安全/隐私保护
[软件工程导论(第六版)]第3章 需求分析(课后习题详解)
[软件工程导论(第六版)]第3章 需求分析(课后习题详解)
|
8月前
|
自然语言处理 算法 安全
[软件工程导论(第六版)]第8章 维护(课后习题详解)
[软件工程导论(第六版)]第8章 维护(课后习题详解)
|
8月前
|
测试技术 BI uml
[软件工程导论(第六版)]第9章 面向对象方法学引论(课后习题详解)
[软件工程导论(第六版)]第9章 面向对象方法学引论(课后习题详解)
|
8月前
|
算法 BI 数据库
[软件工程导论(第六版)]第5章 总体设计(课后习题详解)
[软件工程导论(第六版)]第5章 总体设计(课后习题详解)
|
12月前
|
C++
AcWing语法基础课笔记 第六章 C++中的函数
函数让代码变得更加简洁。 ——闫学灿
76 0
|
12月前
|
数据安全/隐私保护 C++
AcWing语法基础课笔记 第五章 C++中的字符串
字符串是计算机与人类沟通的重要手段。 ——闫学灿
80 0