1. 程式人生 > >迴避複雜—《狂人C》習題解答(第3章題7)

迴避複雜—《狂人C》習題解答(第3章題7)

題目: 5個小孩圍成一圈分糖果。最初第一個小孩有66塊糖果,第二個有35塊,第三個有24塊,第四個有7塊,第五個有34塊。第一個小孩把自己的一半分給第二個小孩,然後第二個小孩把自己現有的一半分給第三個小孩……最後第五個小孩把自己現有的一半分給第一個小孩。程式設計模擬這個過程,輸出最後每個小孩的糖果數。(每個孩子的糖果數始終為整數) 由於在計算過程中需要記住每個小孩的糖果數目,所以使用變數儲存。這些變數都有初值,因此可在定義這些變數時直接給這些變數賦初值。 #include #include #define PORTION 2 int main( void ) { int num_1 = 66 , num_2 = 35 , num_3 = 24 , num_4 = 7 , num_5 = 34 ; system("PAUSE"); return 0; } 然後逐步模擬分配的過程。首先是“第一個小孩把自己的一半分給第二個小孩” #include #include #define PORTION 2 int main( void ) { int num_1 = 66 , num_2 = 35 , num_3 = 24 , num_4 = 7 , num_5 = 34 ; //第一個小孩把自己的一半分給第二個小孩 num_2 += num_1 / PORTION ; num_1 /= PORTION ; system("PAUSE"); return 0; } 如果寫出這樣的程式碼,邏輯上是有問題的。因為第二條語句本應該寫成“num_1 -= num_1 / PORTION ;”(num_1 - num_1 / 2 => num_1 ),儘管其結果與“num_1 /= PORTION;”( num_1 / 2 => num_1 )相同,但“num_1 /= PORTION”實際上是程式設計者代替程式對“num_1 -= num_1 / PORTION”(num_1 - num_1 / 2 => num_1 )進行了進一步的演算和簡化得到的。一般情況下,程式設計者應該把計算交給程式而不應該越俎代庖。如果題目改成了“第一個小孩把自己的三分之一分給第二個小孩”就會發現“num_1 -= num_1 / PORTION”(num_1 - num_1 / 3 => num_1 )依然正確,而“num_1 /= PORTION”( num_1 / 3 => num_1 )則是錯誤的。 但是 num_2 += num_1 / PORTION ; num_1 -= num_1 / PORTION ; 對次序有嚴格的要求,必須先執行第一句,再執行第二句。這就要求程式設計者在程式設計時付出更多的思考和謹慎,這也意味著出錯的可能性更大些。如果一個寫法比另一個寫法更不容易出錯,在兩者都正確的前提下,顯然第一種寫法更好。學習程式設計只學習把程式碼寫正確是遠遠不夠的,更高的境界是學習寫簡單輕鬆的程式碼,不容易出錯的程式碼。一定要學會迴避複雜。把程式碼寫得複雜以至於沒有明顯的錯誤固然不太容易,但程式設計更高的境界是,把程式碼寫得非常簡單以至於明顯沒有錯誤。 在本題目中,這種簡單輕鬆和不易出錯體應現在:擺脫或減少對次序的強依賴,避免複雜的表示式。這可以通過增加一個臨時變數實現。 { int num_to_send ; num_to_send = num_1 / PORTION ; num_1 -= num_to_send ; num_2 += num_to_send ; } 這個寫法後面兩條語句不存在對次序的依賴,避免了“num_2 += num_1 / PORTION”這樣的複雜的表示式,更直接、更簡潔,因而是更好的寫法。 臨時變數,有時也叫中間變數,通常用於儲存計算過程中的中間計算結果。恰當地使用中間變數可以達到簡化表示式,提高可讀性的效果。 下面是該問題解答的完整程式碼。 #include #include #define PORTION 2 int main( void ) { int num_1 = 66 , num_2 = 35 , num_3 = 24 , num_4 = 7 , num_5 = 34 ; //第一個小孩把自己的一半分給第二個小孩 { int num_to_send ; num_to_send = num_1 / PORTION ; num_1 -= num_to_send ; num_2 += num_to_send ; } //第二個小孩把自己現有的一半分給第三個小孩 { int num_to_send ; num_to_send = num_2 / PORTION ; num_2 -= num_to_send ; num_3 += num_to_send ; } //第三個小孩把自己現有的一半分給第四個小孩 { int num_to_send ; num_to_send = num_3 / PORTION ; num_3 -= num_to_send ; num_4 += num_to_send ; } //第四個小孩把自己現有的一半分給第五個小孩 { int num_to_send ; num_to_send = num_4 / PORTION ; num_4 -= num_to_send ; num_5 += num_to_send ; } //第五個小孩把自己現有的一半分給第一個小孩 { int num_to_send ; num_to_send = num_5 / PORTION ; num_5 -= num_to_send ; num_1 += num_to_send ; } printf("最後每個小孩的糖果數分別為" "%d,%d,%d,%d,%d\n" , num_1,num_2,num_3,num_4,num_5 ) ; system("PAUSE"); return 0; } 推薦閱讀: IT程式設計研究