第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程序设计》中那些代码一样,当然会觉得枯燥,也许你昨天写的代码,今天就不知道它们是什么意思了。但如果你时刻牢记编程规则,写出“自己能够说话的代码”(即变量和函数的命名很恰当),那么你就不会觉得这份工作很枯燥,反而会觉得它很有趣。这可能就是所谓的“编程境界”吧。
“熟能生巧”,只有通过不断地练习,我们才能够懂得编写代码的诀窍,也才能够写得出好的、高质量的代码。
(欢迎访问南邮BBS:http://bbs.njupt.edu.cn/)
(欢迎访问重邮BBS:http://bbs.cqupt.edu.cn/nForum/index)
(本系列文章每周更新两篇,敬请期待!本人新浪微博:http://weibo.com/zhouzxi?topnav=1&wvr=5,微信号:245924426,欢迎关注!)