作者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://www.ptt.cc/bbs/C_and_CPP/M.1600266941.A.787.html
→ Lipraxde: 其實就原 po 不熟悉 for 語法而已... 09/16 23:10
如果發文只為了解決原 po 的問題, 那就太無趣惹 :(
→ kobe8112: 這一篇文章值 392 Ptt幣 你贏了XDDD 09/16 23:45
推 james732: 也太精美了 XD 09/17 01:00
→ ckvir: 我覺得不需要把簡單問題複雜化 你這樣寫更難看的懂 09/17 01:21
推 kaneson: 我是覺得(3),(4)反過來就講完了,不過我喜歡樓主的(1)~(4) 09/17 06:57
→ kaneson: 的說明方式 09/17 06:57
後面的方法可以用來分析奇形怪狀的迴圈, 只是原 po 的問題簡單到好像沒什
麼必要, 但作為範例還是不錯滴 ;)
推 derekjj: 這個要給推,太神了 09/17 09:42
推 v86861062: 讚哦 09/17 10:31
推 jack82822005: 這篇文章賺喔XD 09/17 10:35
騙吃騙吃 :D
推 GankTw: 推,分析的真好 09/17 12:21
推 MOONRAKER: 贊 09/17 12:42
推 Kashir: 謝謝版大的精準分析!受益良多 09/17 15:52
推 VSei: 分析透徹易懂,大推 09/17 17:13
推 ggBird: 推 09/17 21:35
推 FY4: 推 09/18 00:12
推 annheilong: 謝謝大大教我如何賺 P 幣XDDDD 09/18 10:29
阿捏手會很辛苦喔! xD
推 michael0728n: 這招酷喔推推 09/18 14:17
※ 編輯: poyenc (61.216.75.43 臺灣), 09/18/2020 14:51:40
推 VictorTom: 推精美:) 09/20 17:24
推 eopXD: 推推 09/22 17:24
推 stock999: 哪一種比較好呢?? 09/27 14:18
推 TuChinJui: 太強了,P幣大師4ni? 10/01 11:29