作者poyenc (发箍)
看板C_and_CPP
标题Re: [问题]请教一下for与while为甚麽答案不一样?
时间Wed Sep 16 22:35:35 2020
安安, 其实这题不需要真的执行啦! 只要善用简单的
静态分析 (static
analysis) 技巧就可以知道问题在哪边. 首先是 for 回圈的基本定义, 我们可
以用
判断程式码品质时常用的方法:
资料视觉化 (data visualization) 来
为
程式码片段做着色. for 回圈里的程式码依照责任可以分成四个区块:
for (
(1) ;
(2) ;
(3) ) {
(4)
}
虽然通常每个区块做的事情都不同, 但求值顺序却是固定的, 如果我们想知道
回圈的商业逻辑, 我们会直接看
(4) , 想知道问题的范围/大小就看
(2) , 依
此类推. while 回圈也有这四个区块存在, 只是写得比较分散一点:
(1)
while (
(2) ) {
(4)
(3)
}
从上面可以看到, while 回圈的
(4) 和
(3) 同样都写在回圈的本体内, 在阅
读上和 for 相比多了区分两区块的步骤, 而且
(1) 容易和前面的程式码混在
一起, 可读性较差. 因为两种回圈是可以互转的, 在发现有这个问题时, 就可
以尝试将回圈改写, 改写前先将程式码着色
(从 for 回圈出发):
int i=0,a;
for(
a=0;
i<n;
a++) {
if(a%3==2 && a%5==3 && a%7==2)
i++;
}
如果转成 while 回圈的话会变成这个样子:
int i=0,
a=0;
while (
i<n) {
if(a%3==2 && a%5==3 && a%7==2)
i++;
a++;
}
有没有发现这个 while 回圈和你写的不太一样? 这个就是问题所在:
它们的结
构是不一样的.
程式码结构不同, 导致了求值顺序甚至是语意的改变, 所以你
跑出来的结果才会有差. 为了验证这件事情, 我们可以用简易的方法来
比较程
式码结构:
将已经着色的程式码区块依照求值顺序排成有多种颜色的线段, 然
後比较两线段的颜色差异. 假设回圈迭代 3 次, 你的 for 回圈和 while 回圈
画成线段後会长成下面的样子:
(for-loop)
(while-loop)
————————————————————————→
time
如上图所示, 排出来的线段颜色相同, 才表示这两份程式码做的事情是等价的;
你的例子因为
a++ 和
if 语句 顺序对调的缘故, 已经产生出不同的程式.
--
[P1389R1] Standing Document for SG20: Guidelines for
Teaching C++ to Beginners
https://wg21.link/p1389r1
SG20 Education and Recommended Videos for Teaching C++
https://www.cjdb.com.au/sg20-and-videos
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.193.76.216 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1600266941.A.787.html
1F:→ Lipraxde: 其实就原 po 不熟悉 for 语法而已... 09/16 23:10
如果发文只为了解决原 po 的问题, 那就太无趣惹 :(
2F:→ kobe8112: 这一篇文章值 392 Ptt币 你赢了XDDD 09/16 23:45
3F:推 james732: 也太精美了 XD 09/17 01:00
4F:→ ckvir: 我觉得不需要把简单问题复杂化 你这样写更难看的懂 09/17 01:21
5F:推 kaneson: 我是觉得(3),(4)反过来就讲完了,不过我喜欢楼主的(1)~(4) 09/17 06:57
6F:→ kaneson: 的说明方式 09/17 06:57
後面的方法可以用来分析奇形怪状的回圈, 只是原 po 的问题简单到好像没什
麽必要, 但作为范例还是不错滴 ;)
7F:推 derekjj: 这个要给推,太神了 09/17 09:42
8F:推 v86861062: 赞哦 09/17 10:31
9F:推 jack82822005: 这篇文章赚喔XD 09/17 10:35
骗吃骗吃 :D
10F:推 GankTw: 推,分析的真好 09/17 12:21
11F:推 MOONRAKER: 赞 09/17 12:42
12F:推 Kashir: 谢谢版大的精准分析!受益良多 09/17 15:52
13F:推 VSei: 分析透彻易懂,大推 09/17 17:13
14F:推 ggBird: 推 09/17 21:35
15F:推 FY4: 推 09/18 00:12
16F:推 annheilong: 谢谢大大教我如何赚 P 币XDDDD 09/18 10:29
阿捏手会很辛苦喔! xD
17F:推 michael0728n: 这招酷喔推推 09/18 14:17
※ 编辑: poyenc (61.216.75.43 台湾), 09/18/2020 14:51:40
18F:推 VictorTom: 推精美:) 09/20 17:24
19F:推 eopXD: 推推 09/22 17:24
20F:推 stock999: 哪一种比较好呢?? 09/27 14:18
21F:推 TuChinJui: 太强了,P币大师4ni? 10/01 11:29