问题:
理解问题的关键点是什么。即便在有些时候会出现一些令人喜出望外的意外,程序实现了当初并没有想到的有用功能。可我们想要的只是一个程序可以简洁地解决我们需要解决的问题。
建议考察的问题:
- 描绘设计图,列举编程技术
- 探索那些程序员需要做出的决定对比所做的决定作一个重新考虑
- 不要使用太多的新语言的架构
- 程序是否太复杂而需要考虑设计思想
- 考虑解决方案中多种变化
- 解决一个容易理解的问题
- 实现一个小到不能再小的解决方案以完全地理解和表现(问题)。
问题描述
让计算机根据我们输入的算术表达式做数学的计算。例如:
输入 2+ 1*4 程序将会输出6。
思索问题
考虑问题以及如何解决它
- 程序要干什么,如何进行交互
- 如何写这个程序。写一个草稿或是简洁的解决方案,看一下初始的想法中有什么样的问题,尝试去解释出现这个问题的原因并讨论一个解决方案出来。
- 考虑问题的过程中我们可能存在纰漏甚至是错误,我们必须一步一步来解决问题,不能心急,同时保持怀疑态度。
(开发的过程不可能是一下子就可以完成的)
开发三个阶段
- 分析
记录当前对问题的理解,确定一个需求集合 (a specification)
- 设计
创建一个总体的系统结构实现其中的一个较小的模块
- 实现
写代码,调试,测试,修改代码......
策略
- 明确问题是什么。。。。要站在用户的角度去考虑
- 问题是否被表述清楚了,一个要注意问题的实质,另一方面要警惕要求过多或过少的陷阱
- 在有限的时间、技术条件、工具下,这个问题是否可以掌控。不能完成倒不如不要启动,当然,也可以削减需求。
- 将程序分解成多个可以控制的部分
- 有帮助的工具,如何判定这个工具能够对我们有帮助
- 在别的解决方案中找出可以复用的部分借用别的程序中可以共用的部分,自己就不用那么麻烦再去写这些东西了。新手要从代码开始写是因为他们需要了解这些工具是怎么构建出来的为将来自己构建工具的时候打好基础,而在实际开发中一切都从代码开始就完全不可行了。
- 写一个小的可控制的版本。
- 要理解核心问题光靠思考和工具还是不够的。必须通过实验性的代码让我们对问题有一个硬性的理解,将我们在理解问题,思想和工具上的问题暴露出来。
- 考量每一行代码,看是否要改变这些代码来时问题变得可控制。在分析问题的过程中我们并不能预期所有的问题,只有在写代码和调试的时候得到一些反馈的基础上才能不断改进自己的设计。(我们将这种实验性的程序称作原型)如果我们的第一个版本不行就推翻重写直到完成一个自己满意的版本为止。在这个时候千万不能凌乱,否则,随着时间推移,会越来越乱。
- 生成一个完整解决方案的程序。
初次尝试int main()
{
cout << "Please enter expression (we can handle + and -):";
int lval = 0;
int rval;
char op;
int res = 0;
cin >> lval >> op >> rval;
if( op == '+')
res = lval + rval;
else if( op == '-')
res = lval - rval;
cout << "Result:" << res << '\n';
keep_window_open();
}
int main()
{
cout << "Please enter expression (we can handle + and -):";
int lval = 0;
int rval;
char op;
int res = 0;
cin >> lval >> op >> rval;
if( op == '+')
res = lval + rval;
else if( op == '-')
res = lval - rval;
cout << "Result:" << res << '\n';
keep_window_open();
}
升级版
int main()
{
cout << "Please enter expression (we can handle +,-,* and /)\n";
cout << "add an x to end expression (e.g. 1+2*3;):";
int lval = 0;
int rval = 0;
char op;
cin >> lval;
if(!cin) error("no firs operand");
while (cin >> op)
{
if (op != ';')
{
cin >> rval;
}
if (!cin)
{
error("no second operand");
}
switch(op)
{
case '+':
lval += rval;
break;
case '-':
lval -= rval;
break;
case '*':
lval *= rval;
break;
case '/':
lval /= rval;
break;
default:
cout << "Result:" << lval << '\n';
keep_window_open();
return 0;
}
}
error("bad expression");
}
相较于上一个版本,在升级版中添加了:
- 更干净的代码
- 添加了对乘法和除法的支持
- 支持多个操作符
但是还存在一些问题:
- 运算法则的优先权(数值计算的顺序)
- 一行表达式
- 如何找到运算操作符,区别于数字
- 记录操作符所处的位置
- 如何处理那些严格从左到右的式子
(待续...)
全文参考C++编程原理与实践