高质量C编程(一)声明:1.本资料所涉及到的内容来自互联网和作者工作经验。2.本资料仅作为内部资料教学使用,禁止任何商业用途。作者:武汉工业学院数理科学系陈欣20087.1目录第一章程序的排版第二章变量的命名规则第三章常量、变量与结构第四章基本语句与表达式第五章函数的设计第一章程序的排版1.1空行空行起着分隔程序段落的作用。空行得体(不过多也不过少)将使程序的布局更加清晰。空行不会浪费内存,虽然打印含有空行的程序是会多消耗一些纸张,但是值得。所以不要舍不得用空行。建议:在一个函数体内,逻辑密切相关的语句之间不加空行,其它地方应加空行分隔。例如:while(condition){statement1;//空行if(condition){statement2;}else{statement3;}//空行statement4;}1.2代码行建议:一行代码只做一件事情,如只定义一个变量,或只写一条语句。这样的代码容易阅读,并且方便于写注释。建议:for、while、do等语句自占一行,执行语句不得紧跟其后。不论执行语句有多少都要加{}。这样可以防止书写失误。对比左右两段代码:intwidth;//宽度intheight;//高度intdepth;//深度if(widthheight){dosomething();}intwidth,height,depth;//宽度高度深度if(widthheight)dosomething();左边是良好的代码,右边是不好的代码。1.3代码行内的空格建议:关键字之后要留空格。象const、virtual、inline、case等关键字之后至少要留一个空格,否则无法辨析关键字。象if、for、while等关键字之后应留一个空格再跟左括号‘(’,以突出关键字。建议:函数名之后不要留空格,紧跟左括号‘(’,以与关键字区别。建议:(’向后紧跟,‘)’、‘,’、‘;’向前紧跟,紧跟处不留空格。建议:,’之后要留空格,如Function(x,y,z)。如果‘;’不是一行的结束符号,其后要留空格,如for(initialization;condition;update)。建议:赋值操作符、比较操作符、算术操作符、逻辑操作符、位域操作符,如“=”、“+=”“=”、“=”、“+”、“*”、“%”、“&&”、“||”、“”,“^”等二元操作符的前后应当加空格。建议:一元操作符如“!”、“~”、“++”、“--”、“&”等前后不加空格。建议:象“[]”、“.”、“-”这类操作符前后不加空格。建议:对于表达式比较长的for语句和if语句,为了紧凑起见可以适当地去掉一些空格,如for(i=0;i10;i++)和if((a=b)&&(c=d))voidFunc1(intx,inty,intz);//良好的风格voidFunc1(intx,inty,intz);//不良的风格if(year=2000)//良好的风格if(year=2000)//不良的风格if((a=b)&&(c=d))//良好的风格if(a=b&&c=d)//不良的风格for(i=0;i10;i++)//良好的风格for(i=0;i10;i++)//不良的风格1.4对齐建议:程序的分界符‘{’和‘}’应独占一行并且位于同一列,同时与引用它们的语句左对齐。下图:良好的代码不好的代码voidFunction(intx){⋯//programcode}if(condition){⋯//programcode}else{⋯//programcode}voidFunction(intx){⋯//programcode}if(condition){⋯//programcode}else{⋯//programcode}1.5长行拆分建议:代码行最大长度宜控制在70至80个字符以内。代码行不要过长,否则眼睛看不过来,也不便于打印。建议:长表达式要在低优先级操作符处拆分成新行,操作符放在新行之首(以便突出操作符)。拆分出的新行要进行适当的缩进,使排版整齐,语句可读。if((very_longer_variable1=very_longer_variable12)&&(very_longer_variable3=very_longer_variable14)&&(very_longer_variable5=very_longer_variable16)){dosomething();}for(very_longer_initialization;very_longer_condition;very_longer_update){dosomething();}2.6修饰符的位置修饰符*和&应该靠近数据类型还是该靠近变量名,是个有争议的活题。若将修饰符*靠近数据类型,例如:int*x;从语义上讲此写法比较直观,即x是int类型的指针。上述写法的弊端是容易引起误解,例如:int*x,y;此处y容易被误解为指针变量。虽然将x和y分行定义可以避免误解,但并不是人人都愿意这样做。建议:应当将修饰符*和&紧靠变量名例如:char*name;int*x,y;//此处y不会被误解为指针2.7注释C语言的注释符为“/*…*/”。C++语言中,程序块的注释常采用“/*…*/”,行注释一般采用“//…”。注释通常用于:(1)版本、版权声明;(2)函数接口说明;(3)重要的代码行或段落提示。虽然注释有助于理解代码,但注意不可过多地使用注释。建议:全局变量要有较详细的注释,包括对其功能、取值范围、哪些函数或过程存取它以及存取时注意事项等的说明。示例:/*TheErrorCodewhenSCCPtranslate*//*GlobalTitlefailure,asfollows*///变量作用、含义/*0-SUCCESS1-GTTableerror*//*2-GTerrorOthers-nouse*///变量取值范围/*onlyfunctionSCCPTranslate()in*//*thismodualcanmodifyit,andother*//*modulecanvisititthroughcall*//*thefunctionGetGTTransErrorCode()*///使用方法BYTEg_GTTranErrorCode;强烈建议:函数头部应进行注释,列出:函数的目的/功能、输入参数、输出参数、返回值、调用关系(函数、表)等。示例:下面这段函数的注释比较标准,当然,并不局限于此格式,但上述信息建议要包含在内。/*************************************************Function://函数名称Description://函数功能、性能等的描述Calls://被本函数调用的函数清单CalledBy://调用本函数的函数清单TableAccessed://被访问的表(此项仅对于牵扯到数据库操作的程序)TableUpdated://被修改的表(此项仅对于牵扯到数据库操作的程序)Input://输入参数说明,包括每个参数的作//用、取值说明及参数间关系。Output://对输出参数的说明。Return://函数返回值的说明Others://其它说明*************************************************/第二章变量的命名规则建议:标识符应当直观且可以拼读,可望文知意,不必进行“解码”。标识符最好采用英文单词或其组合,便于记忆和阅读。切忌使用汉语拼音来命名。程序中的英文单词一般不会太复杂,用词应当准确。例如不要把CurrentValue写成NowValue。建议:识符的长度应当符合“min-length&&max-information”原则。几十年前老ANSIC规定名字不准超过6个字符,现今的C++/C不再有此限制。一般来说,长名字能更好地表达含义,所以函数名、变量名、类名长达十几个字符不足为怪。那么名字是否越长越好?例如变量名maxval就比maxValueUntilOverflow好用。单字符的名字也是有用的,常见的如i,j,k,m,n,x,y,z等,它们通常可用作函数内的局部变量。建议:命名规则尽量与所采用的操作系统或开发工具的风格保持一致。例如Windows应用程序的标识符通常采用“大小写”混排的方式,如AddChild。而Unix应用程序的标识符通常采用“小写加下划线”的方式,如add_child。别把这两类风格混在一起用。建议:程序中不要出现仅靠大小写区分的相似的标识符。例如:intx,X;//变量x与X容易混淆voidfoo(intx);//函数foo与FOO容易混淆voidFOO(floatx);建议:程序中不要出现标识符完全相同的局部变量和全局变量,尽管两者的作用域不同而不会发生语法错误,但会使人误解。例如:#includestdio.hvoidInputFormat(char*strUserName){intlength=strlen(strUserName);//以下部分省略}voidmain(){intlength=0;//以下部分省略}建议:变量的名字应当使用“名词”或者“形容词+名词”。例如:floatvalue;floatoldValue;floatnewValue;建议:全局函数的名字应当使用“动词”或者“动词+名词”(动宾词组)。例如:DrawBox();//全局函数建议:用正确的反义词组命名具有互斥意义的变量或相反动作的函数等。例如:intminValue;intmaxValue;intSetValue(…);intGetValue(…);建议:尽量避免名字中出现数字编号,如Value1,Value2等,除非逻辑上的确需要编号。这是为了防止程序员偷懒,不肯为命名动脑筋而导致产生无意义的名字(因为用数字编号最省事)。例如:floatGetAverage(floatt1,floatt2){floatt3,t4;t3=t4=0.0;t3=t1+t2;t4=t3/2.0;returnt4;}简单的Windows应用程序命名规则作者对“匈牙利”命名规则做了合理的简化,下述的命名规则简单易用,比较适合于Windows应用软件的开发。建议:函数名用大写字母开头的单词组合而成例如:voidDraw(void);//函数名voidSetValue(intvalue);//函数名建议:变量和参数用小写字母开头的单词组合而成。例如:BOOLflag;intdrawMode建议:常量全用大写的字母,用下划线分割单词例如:constintMAX=100;constintMAX_LENGTH=100;建议:静态变量加前缀s_(表示static)例如:voidInit(…){staticints_initValue;//静态变量…}建议:如果不得已需要全局变量,则使全局变量加前缀g_(表示global)例如:intg_howManyPeople;//全局变量intg_howMuchMoney;//全局变量接下来我们来看一看,VC++6.0中提供的CString类中的部分成员函数的命名和注释情况。classCString{………………………….………………………….//以上省略部分代码//getdatalengthintGetLength()const;//TRUEifzerolengthBOOLIsEmpty()const;//clearcontentstoemptyvoidEmpty();//returnsinglecharacteratzero-basedindexTCHARGetAt(intnIndex)const;//returnsinglecharacteratzero-basedindexTCHARoperator[](intnIndex)const;//setasinglecharacteratzero-basedindexvoid