第1部分 重新認識C語言
變量及函數的命名
50塊錢,那個營業員問了一句“How much?”。路人甲心想現在社會真的與以往不同了,連一般的營業員都開始流行講英語了,于是便以不是很流利的口語說了一句“Fifty YUAN”。那個營業員一頭霧水地看着他,說道“電話号碼多少?”路人甲這才恍然大悟,原來是問我電話号碼多少,而非多少錢。
也許這個笑話本身并不好笑,但卻說明了一個道理:我們要盡量準确地表達自己的想法,不要讓别人感到疑惑。這個原理同樣适用于軟體開發過程,适用于編寫代碼的過程。
int i,j;”、“char c;”之類的變量定義到處都是,嚴重影響了工作的效率。
在本文中,我也不想說一些條條框框的東西,而是以一個實際的例子來為讀者展示如何命名變量和函數是恰當的。這裡用《學校C語言教材的缺陷》這篇文章中出現的程式代碼為例,将該代碼按照規範修改後,如下所示:
/***************************************************************
*版權所有 (C)2014,company name。
*
*檔案名稱:example.c
*内容摘要:用于示範如何給變量和函數做規範的命名
*其它說明:無
*目前版本:V1.0
*作 者:周兆熊
*完成日期:20140325
*
*修改記錄1: //修改曆史記錄,包括修改日期、版本号、修改人及修改内容等
* 修改日期:
* 版本号:
* 修改人:
* 修改内容:
***************************************************************/
#include <stdio.h>
typedef signed int INT32; //重定義資料類型
typedef float FLOAT; //重定義資料類型
FLOAT ProcessFactorial(INT32 iInputValue); //函數聲明
/**********************************************************************
*功能描述:主函數
*輸入參數:無
*輸出參數:無
*傳回值:無
*其它說明:無
*修改日期 版本号 修改人 修改内容
* ------------------------------------------------------------------------------------------------------
* 20140325 V1.0 周兆熊 建立
***********************************************************************/
INT32 main()
{
INT32 iInputValue = 0;
FLOAT fResult = 0.0;
printf("input an integer number: ");
scanf("%d", &iInputValue);
fResult = ProcessFactorial(iInputValue); //調用求階乘的函數
printf("%d!=%10.0f\n", iInputValue, fResult);
return 0;
}
/**********************************************************************
*功能描述:求一個數的階乘
*輸入參數: iInputValue-輸入值
*輸出參數:無
*傳回值:求階乘後的結果
*其它說明:無
*修改日期 版本号 修改人 修改内容
* -----------------------------------------------------------------------------------------------------
* 20140325 V1.0 周兆熊 建立
***********************************************************************/
FLOAT ProcessFactorial(INT32 iInputValue)
{
FLOAT fResult = 0.0;
//先判斷輸入值是否小于0
if (iInputValue < 0)
{
printf("iInputValue < 0, dataerror!");
return -1;
}
else
{
if (iInputValue == 0 || iInputValue == 1) // 0和1的階乘是1
{
fResult = 1;
}
else
{
fResult = ProcessFactorial(iInputValue-1)*iInputValue; //執行遞歸調用
}
return(fResult);
}
}
該代碼和之前的代碼相比,是不是有很大的不同?
有關類型重定義、注釋等相關内容,請參考我之前的文章,這裡重點說一下變量和函數的命名:
(1) 變量命名和函數命名應具備描述性,不要過度縮寫。變量的命名應該使用名詞,如fResult;函數的命名應該使用“指令性”動詞,如ProcessFactorial。
(2)不管是函數還是變量,它們的命名隻有一個原則:讓讀者一眼就能夠看出它們表達的意思。如ProcessFactorial函數,一看到它,就大概能夠明白這是在求階乘(如果你英語确實不好,那就另當别論了);iInputValue變量,表示輸入值;fResult變量,表示結果值。我們要讓代碼自己來說話,而不是要作者向别人解釋半天才行。
(3)為了讓讀者看到一個變量就知道其類型,在變量的最前面,通常會有一個辨別類型的字母。如iInputValue中的第一個字母“i”表示這是一個整型變量(“i”代表“int”),fResult中的第一個字母“f”表示這是一個浮點型變量(“f”代表“float”)。這樣做,也是為了更進一步讓讀者對代碼能夠了然于心,能夠很容易讀懂,這樣也省去了作者的很多向别人解釋的時間,可謂是“大家皆友善”。
(4) 函數的功能要單一,不要設計多用途的函數;函數體的規模要小,将函數内的代碼行數控制在項目中規定的範圍之内。此外,要盡量避免函數帶有“記憶”功能,相同的輸入應該産生相同的輸出。
(5)始終要明白,我們第一是為人編寫代碼,其次才是計算機。如果隻是計算機能夠讀懂的代碼,不是好代碼,也無法展現出一個程式設計人員的水準。
對于函數的調用,需要注意以下幾點:
(1)在調用的時候,傳入的實參的類型一定要與形參的類型完全一樣。如果不一緻,用代碼檢查工具(如Pclint)是很容易發現的。如果确實需要傳入該參數,可使用強制資料類型轉換。
(2)對于有傳回值的函數,盡量在被調用的時候對傳回值進行處理。在實際的軟體開發中,有很多人定義了一個有傳回值的函數,但直接調用該函數,而沒有對傳回值進行處理,這是不規範的。例如,定義一個傳回整型值的函數ExampleFun,如下所示:
int ExampleFun(…)
{
//執行代碼
return 0;
}
而調用代碼如下:
……
ExampleFun(…);
……
沒有考慮到傳回值。
規範的作法是:同樣定義一個整型變量,用于表示該函數的傳回值,如下代碼所示:
int iRetVal = 0;
……
iRetVal = ExampleFun(…);
……
很多人認為寫代碼很枯燥,其實不然。如果你每天寫出來的代碼像譚浩強老師寫的《C程式設計》中那些代碼一樣,當然會覺得枯燥,也許你昨天寫的代碼,今天就不知道它們是什麼意思了。但如果你時刻牢記程式設計規則,寫出“自己能夠說話的代碼”(即變量和函數的命名很恰當),那麼你就不會覺得這份工作很枯燥,反而會覺得它很有趣。這可能就是所謂的“程式設計境界”吧。
“熟能生巧”,隻有通過不斷地練習,我們才能夠懂得編寫代碼的訣竅,也才能夠寫得出好的、高品質的代碼。