2013年5月7日 星期二

[C語言] 簡單的程式技巧



筆者在就學時,讀的是電子工程而不是資訊工程,所以在寫程式上,其實還是和所謂資工系的高手有一段落差,這在上班時,會有很明顯的認知,尤其是在分工清楚的公司,更甚明顯。不過畢竟術業有專攻,大家也別太枉自匪薄,只要多看,注意一些小細節,總是會有機會的。




以寫程式為例,電子工程相關的人的心態是:
可以動就好。而資訊工程講求的是程式的高閱讀性和維護性。所以今天我們要探討的就是如何讓程式保有高閱讀性和維護性。




以下是一個非常簡單的程式,或許compiler 不會過,但只要抓到重點就可以了:




if(test_flag1==1){




        test_data=1;




}




else if(test_flag2==0){




        test_data=2;




}




else{




        test_data=0;




}




 




        以上的程式,盡可能的讓程式碼「擠」在一起,雖然版面可以塞得下較多的程式,但因為都滿擠的,當程式看久了,常常會讓眼精非常的吃力。而且如果不了解數值的內容的話,閱讀上就會很辛苦。大家不仿可以試試看下面的寫法:




 




        #define
TRUE                1




        #dfeine
FALSE              0




 




        #define
FRUIT_APPLE         0




        #define
FRUIT_BANANA    1




        #define
FRUIT_GRAPAS     2




 




        if ( TRUE == test_flag_1)




        {




                test_data
= FRUIT_BANANA;




        }




        else if ( FALSE == test_flag_2)




        {




                test_data
= FRUIT_ GRAPAS;




        }




        else




        {




                test_data
= FRUIT_ APPLE;




        }




 




 




        不知道個位客倌有沒有覺得上面的寫法比較容易閱讀且容易維護,(謎之音: 你虎爛。) 沒關係,
就讓筆者慢慢解說上面的程式有幾件事的差別。




 




 


 





差別1:擠在一起常常會有搞混的情況發生,盡可能的讓程式中間穿插空白,增加閱讀的方便性。






差別2 盡可能的讓常數使用巨集(#define)的方式,定義一個有意義的名稱。


        這邊要有2個地方值得注意:




(a)常數最好使用大寫的英文,因為這是一個不成文的規定,所以以後你在閱讀別人的程式時,遇到大寫時,第一直覺就可以知道這是「常數」。




(b)相同的巨集,最好前面帶有一個表示相同類型使用到的英文,以避免亂用巨集的情況發生,導致閱讀的混亂(就是呼叫到不該呼叫的巨集)




差別3,大括號({ }  最好分2行, 因為有專案開發時,常常會遇到需要把判斷式省略或是做測試使用。
舉個簡單舉子:如果我要讓test_data
永遠都只會是” FRUIT_
APPLE”
的話, 那麼這時候我會這樣做:




 




        #if 0




if ( TRUE == test_flag_1)




        {




                test_data
= FRUIT_BANANA;




        }




        else if ( FALSE == test_flag_2)




        {




                test_data
= FRUIT_ GRAPAS;




        }




        else




        #endif




        {




                test_data
= FRUIT_ APPLE;




        }




 




這樣的好處就:




(a)   
非常好加入巨集的維護,而且可以很方便的啟用(enable)與關閉(disable)




(b)  
如果有版本控制軟體的話(SVN/Mercurial/GIT),在比較程式不同時,只會發現多出來的巨集(#if 0/ #endif),這在專案維護上非常重要。




 




差別4 
判斷式的寫法:




 




        if (
TRUE == test_flag_1)
if (test_flag_1 == TRUE)




建議遇到常數時,盡可能的養成常數寫在判斷式的左側,以防止筆誤造成的除錯上的困難。




(a)                 
if (test_flag_1 0 = TRUE)
ç 筆者不小心寫錯,但這樣compiler會過,而且會永遠成立,因為判斷式非0即真。




(b)                 
( TRUE = test_flag_1)
ç 筆者不小心寫錯,但這樣compiler會出現錯誤。因為常數沒有辦法被設定成另一個數值。




 




這個是一個非常重要的小技巧,可以防止筆誤的機率。




 




以上分享給大家知道,並且歡迎大家討論。


 


 


 





感謝沒事才做木工大大的提醒,在寫這篇文章的時候,到是沒有認真思寫這裡的變數使用方式,假設變數都只有TRUE或是FALSE的話,那麼到是可以換個方式寫:





if ( test_flag_1)


        {


                test_data
= FRUIT_BANANA;


        }





        else if ( !test_flag_2)


        {


                test_data
= FRUIT_ GRAPAS;


        }


        else


        {


                test_data
= FRUIT_ APPLE;


        }




其實有時候在寫程式時,也是希望可以讓程式短一點,這樣可以少寫一點或是讓版面可以更精簡一點。








1 則留言:

  1. 沒事才做木工2013年5月8日 下午6:45

    個人覺得 true== 是多餘的句子, flase== 改成 ! 應該更容易維護.,
    [版主回覆05/09/2013 12:25:07]嗯, 我同意您的看法。 謝謝。

    回覆刪除