第六步驟的流程圖

對於結構化的程式來說,流程圖已經在很多地方無用武之地了,可是對於比較複雜的條件控制敘述,運用流程圖來設計還是有一定程度的幫忙,對於這種程式來說讀規律化的流程圖會比讀程式要容易,比較不會忽略掉一些可能性。以下我們逐步地設計這個轉換的流程:

 
內容

步驟 1

初步的想法:

從大處著眼 --『要解決問題先找最一般化的規則, 先能解決大部分的狀況再說, 先不要看那些特別的例子』

(資訊系同學有的時候被固執愚笨的機器或是線上測試系統搞得有一點失心瘋的, 不看問題中最重要的部份, 滿腦袋只看到特殊的地方, 不一樣的地方 -- 根本是一種見樹不見林的概念)

找一個標準的範例 135 ==> 一百三十五

135 = 1*100+3*10+5, N=135, H=1, T=3, O=5

請注意上面這個描述方法說明 N, H, T, O 要滿足的關係, 當然各自還要滿足 0<=N<=999, 0<=H<=9, 0<=T<=9, 0<=O<=9, 但是這並沒有告訴電腦給它 N 的數值, 怎樣找到 H, T 和 O

在我們第一節課就有講到 C 是一種命令式的語言, 不是宣告式的, 寫程式的人不能只描述 H, T, O 要滿足的條件, 就希望電腦可以自己找到符合的數值, 寫程式的人需要找到計算的步驟, 一步一步教電腦去求出 H, T, O 的數值, 例如: O 的數值 5 是 135 除以 10 的餘數, 如果把 135 除以 10 的商 13 當成新的 N 值, 則 T 的數值 3 是 13 除以 10 的餘數, 如此一層一層可以算出 O, T, H 的數值 (甚至更多位數都可以算出來)

接下來簡單分析一下轉換的規則, 發現

  1. 如果 100<=N, 就會印出 "H 百", 如果 N<100, 則 H==0, 百位數字 H 以及 "百" 就都不印出
  2. 如果 10<=N<=99 , 就會印出 "T 十", 如果 N<10, 則 T==0, 十位數字 T 以及 "十" 就都不印出
  3. 如果 1<=N<=9 , 就會印出 "O", 如果 O==0 不需印出個位數字 O

好像可以用下面流程圖來實現 (完整功能的程式是一步一步慢慢修正設計得到的, 一開始有一些錯誤不見得很糟糕)

It's not at all important to get it right the first time. It's vitally important to get it right the last time. (Andrew Hunt and David Thomas)

問題:

  1. 10 ==> 十 (不好, 十就好了), 15 ==> 十五 (不好, 十五就好了)
  2. 105 ==> 一百五 (不對, 應該是一百五)

分析:

  1. 上面這個流程圖其實把 H, T, O 三個位數的數值分開來想了; 對於 "H" 和 "百" 的列印是對的, 但是列印 "T" 和 "十" 的時候, 不能不考量 "H" 和 "O" 的數值
  2. 列印 "T" 和 "十" 在 1<=N<=19 和 101<=N<=119 (201<=N<=219, ...) 有特別的規則, 例如:
    05 ==> 五, 105 ==> 一百
    15 ==> 五, 115 ==> 一百一十
    所以在下一步驟裡我們檢查 H 是否大於 0, 然後各自做進一步的判斷, 再檢查 T 是否大於 0, 以及 T 是否大於 1, 然後各自做進一步的判斷

步驟 2

請特別注意因為我們用圖形來表示, 我們也特別以規律的方法來畫, 例如 N 小的畫在左邊, N 大的畫在右邊, 又特別用紅字標示每一塊所處理的 N 數值, 這樣可以很方便地檢查是不是考慮時有漏掉任何狀況, 這樣子做你才會看到為什麼像這樣比較複雜的判斷邏輯不直接寫程式碼


問題: N == 0 的時候什麼都不印

問題: 許多程式碼不斷地重複

步驟 3

使用函數去除重複的程式碼

步驟 4

進一步簡化流程的方法:

上面這個流程圖還是蠻複雜的, 雖然可以確定已經考慮所有的狀況了, 可是轉換成程式還是挺複雜的, 如果不用函數的話, 會出現三層的 if 敘述

if (...)
{
    if (...)
    {
        if (...)
        {
            ...
        }
        else
        {
            ...
        }
    }
    else
    {
        ....
    }
}

讓我們再分析一下, 看能不能有更直覺的方式來設計: 其實關鍵問題只在於三種狀況

  1. 10 <= N <= 19 的時候, 不要印出 "一十" 而印 "十"
  2. H01 <= N <= H09 (101<=N<=109, 201<=N<=209, ..., 901<=N<=909) 的時候, 要多印出 "零"
  3. N==0 時印出 "零"

如此就可以再修改步驟一裡的流程圖變成下圖

概念上是不是稍微簡化一些呢? 換成程式以後會變成連續的 5 個 if 敘述, 其中第二個會是兩層的巢狀 if 敘述, 雖然設計起來有點複雜, 但是最後的程式不算複雜, 這是因為我們有好好設計的成果, 如果你是電腦打開就寫的話, 大部分都會寫出一個邏輯很混亂的程式, 很難偵錯也很難看得懂, 也許還有某些部份沒有完整考慮, 甚至留下一些 bug 在程式裡

請記得把列印 H, T, O 的三個部份用 switch 或是 if 寫在一個獨立函數裡

你在自己機器上要怎樣測試這個程式呢? 不要只是執行看看, 隨意輸入幾個狀況就滿意了, 其實你可能應該寫一個迴圈, 讓你的程式由 0 做到 999 把每一個數字都轉換出來, 寫到一個檔案裡, 然後和別人的結果比對看看, 也不是用眼睛看啦, 要嘛寫一個程式比對, 要不然就用現成的編輯器 notepad++ 提供的比對功能

程式設計課程 首頁

製作日期: 10/06/2012 by 丁培毅 (Pei-yih Ting)
E-mail: pyting@mail.ntou.edu.tw TEL: 02 24622192x6615
海洋大學 電機資訊學院 資訊工程學系 Lagoon