編程體會:有效的流程很關鍵

寫程序的時候,正確合適的工作流程能夠確保高效地完成工作目標,這篇文章將主要介紹從頭到尾解決編程問題的策略,與各位在編程之路上共勉。應用這一結構化的流程能儘可能地縮減令人沮喪地調試過程,在更少的時間裏寫成更清晰更正確的代碼。

一步步介紹

給出一個示例練習題用來說明。
問題:給定兩個字符串sourceString和searchString,返回searchString出現在sourceString中的第一個索引。如果searchString未在sourceString中出現,則返回-1。

第一步:畫出來

直接從寫代碼開始實際上是一個荒謬又懶惰的思路。在寫一篇文章之前,你首先會搞清楚你的假設和證據,以確保你的論證是合理的。如果你不這樣做,後面當你發現寫的內容整體無法合適地組織起來時,你又要重新開始,這就浪費了很多時間。寫代碼也是這樣,甚至可能更糟,就像把洗髮水揉進眼睛裏。

通常而言,一個問題的解決方案並不是淺顯直觀的,即使乍看起來很簡單。在紙上琢磨一下能讓你找到解決方案並驗證該方案在一些不同場景中的效果。所有這些工作都應該在寫下任何一行代碼之前完成。

所以,先不要寫代碼。甚至不要去想代碼。後面會有足夠的時間去添加分號和括號。現在你只需要搞清楚你作爲一臺人體計算機,會如何解決這個問題。

畫圖。使用箭頭。在小方框裏填寫數字。只要能讓你可視化這個問題,那就去做吧。你的目標是解決問題,你能用紙張和筆去盡情發揮,而不受限於鍵盤。

首先找一些簡單的輸入。例如,假設你的函數是取一個字符串abc。搞清楚正確的結果是什麼,然後去想如何解決這個問題以及所涉及到的步驟。

我們假設我們的字符串有以下值:

sourceString = "sahjfansjd"
searchString = "fan"

我的想法是像下面這樣展開的:

好吧,我看到sourceString包含searchString。但我是怎麼看出來的呢?額,首先我從sourceString的開頭開始閱讀,檢查每3個字符構成的片段是否與詞fan匹配,直到結束。比如,我看到了sah、ahj、hjf等組合,當我看到索引4時,我找到了fan,所以我確定找到了匹配並且是從索引4開始。

當我們寫下我們的算法時,需要確保我們表達了一切並能夠處理所有可能的情況。當我們確實找到匹配時,返回正確的答案當然很好,當我們也需要在沒找到匹配的時候同樣能返回正確答案。

我們再以另一對字符串爲例:

sourceString = "sahjfasjd"
searchString = "fan"

這裏,我們同樣首先從sourceString的開頭開始閱讀,檢查每3個字符構成的片段是否與詞fan匹配,直到結束,字符串末尾,最後我們確定其中沒有匹配,因此返回==-1==。

我們已經確定瞭解決這個問題的一系列步驟(在編程領域,我們稱之爲算法),也已經嘗試了一些不同的場景,每一步都得到了正確的結果。現在,我們已經相信我們的算法有效了,是時候形式化這個算法了,這就是下一個步驟。

第二步:寫成普通話

想想第一步確定的算法,然後用平實易懂的語言把它寫下來。這能使這些步驟顯得具體,讓我們在寫代碼時能夠回顧參考。

  1. 從字符串開頭開始檢查
  2. 檢查每3個字符構成的片段
  3. 如果其中有任何片段等於searchString,就返回當前索引
  4. 如果直到該字符串結束也沒找到任何匹配,就返回== -1==

看起來,還不錯喲!

第三步:寫僞代碼

僞代碼並不是真正的代碼,但卻模仿了代碼的結構。下面是爲上面的算法寫的僞代碼:

for each index in sourceString:
    N = len(searchString)
    match = sourceString[index, index + N]
    if match == searchString:
        return index
return -1

僞代碼與代碼的接近程度完全由我們自己決定,慢慢地練習,會發現最適合自己的風格。

第四步:將你能做到的部分翻譯成代碼

對於更簡單的問題,這個步驟可以和上一步一起完成。

這是整個流程中,我們第一次必須考慮句法、函數參數和語法規則。也許沒法寫出所有的一切,但沒有關係,把我們能寫出來的部分先寫出來。

def myfunc(sourceString, searchString):
    n = len(searchString)
    for index in range(len(sourceString)):
        match = sourceString[index: index + n]
        if match == searchString:
            return index
    return -1
    
myfunc(sourceString, searchString)

在寫下上面這段代碼的時候,我們已經開始調動我們的編程知識,將能運行的代碼寫出來了,中間肯定會有報錯和調試的過程。

第五步:不要猜測

代碼新人常會犯一個錯誤:在互聯網上找一下寫着可能有效的東西,然後不加測試地將其插入到自己地程序中。你的程序中你不理解地片段越多,就越不可能得到最後正確的解決方案。

每增加一個你不確定的東西,你的程序可能出錯的方式都會翻一倍。對某事不確定?ok—如果代碼無效,那麼這裏可能就是問題所在。

你的程序可能出錯的方式遵循梅森序列:a(n)=2n1{a(n)=2^n-1}

首先測試你的新代碼。在網上找東西是可以的,但是在將其插入你的程序之前應該在另一個單獨的小空間裏測試一下它,以確保其工作方式和你所想的一樣。

在前一步寫正式代碼的時候,我忘記字符切片是怎麼做的了,所以第一次運行的時候報了錯,好在找到了想起來怎麼做了,把問題解決了就ok了。

如果你讀到了這裏,我現在只想說:試試這種策略。回到你上週因爲受挫而擱置一旁的編程問題。保證你能立馬看到效果。祝好運,編程快樂。

===========================

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章