东陆风华BBS

 找回密码
 注册东陆风华通行证
东陆风华论坛18周年庆(2005.3.28-2023.3.28)东陆风华-云南大学各专业历年考研复试信息汇总帖送人玫瑰手留余香-云南大学历年考研复试信息汇总
东陆风华-云南大学各学院考研QQ群号码
申请东陆风华实名认证免费领取云大考研考博真题如何申请云南大学考研论坛VIP会员?VIP特权?
东陆风华-云南大学各省校友&云南省各地州校友QQ群云南大学呈贡校区图片 &宿舍图片&图片云大 东陆风华送人玫瑰手留余香-云南大学2021年考研复试信息分享
返回列表 发新帖
查看: 2822|回复: 0

PC-Lint与C\C++代码质量

[复制链接]

该用户从未签到

发表于 2006-10-8 13:34:01 | 显示全部楼层 |阅读模式

东陆风华帐号全站通用,包括论坛、商城、网络家园等站点,登陆查看更精彩内容

您需要 登录 才可以下载或查看,没有帐号?注册东陆风华通行证

x
软件质量对于一个软件设计者来说是相当重要的。

正确性、健壮性、可靠性、效率、易用性、可读性(可理解性)、可扩展性、可复
用性、兼容性、可移植性等质量属性就是软件整体质量的体现。
软件质量问题说到底应该是代码质量问题,写出优秀、稳定的代码是一个高水平的程序设计
者应该具备的。

在好的数据结构和算法的前提下,如何编写出优秀的代码是我们最应该关心的。

关于如何提高自己编写的C\C++代码质量,林锐博士的《高质量C++_C编程指南》是很好的指导!
在那本书的最后提到了PC-Lint代码审查工具是很好的助手,这里我简单的介绍一下这个工具。
下面是从网络上找来的资料:
/********************************************************************************
LINT工具是一种软件质量保证工具,许多国外的大型专业软件公司,如微软公司,都  
把它作为程序检查工具,在程序合入正试版本或交付测试之前一定要保证通过了LINT检查  
,他们要求软件工程师在使用LINT时要打开所有的编译开关,如果一定要关闭某些开关,  
那么要给出关闭这些开关的正当理由。  

  可想而知,如果从我们编码后第一次编译程序时就使用LINT来检查程序,并且保证消  
除所有的LINT告警,我们就不会遇到象今天这么多的告警信息。即使在今天,我们如果能  
抽出一定的精力来消除程序中的LINT告警,以后再维持这种无告警状态就是很容易的了。  
我们程序质量的提高也是不言而喻的。  

  PC-LINT是GIMPEL SOFTWARE公司的产品,其中的内容是非常广泛的,光是选项就有30  
0多个,涉及到程序编译及语法使用中的方方面面。本篇培训材料旨在引导读者入门,学会  
PC-LINT的基本使用方法,起抛砖引玉的作用,能让读者从这里起步继续去研究如何娴熟地  
使用PC-LINT的各种选项,能让它充分为我们的开发工作服务。

1.概述  
  如果要给LINT工具下一个形象点的定义,那就是:一种更加严格的编译器。它不仅可  
以象普通编译器那样检查出一般的语法错误,还可以检查出那些虽然完全合乎语法要求,  
但很可能是潜在的、不易发现的错误。请看下面的例子:  
1:  
2:char *report( int m, int n, char *p )  
3:{  
4: int result;  
5: char *temp;  
6: long nm;  
7: int i, k, kk;  
8: char name[11] = "Joe Jakeson";  
9:  
10: nm = n * m;  
11: temp = p == "" ? "null" : p;  
12: for( i = 0; i 13: {  
14: k++;  
15: kk = i;  
16: }  
17:  
18: if( k== 1 ) result = nm;  
19: else if( kk > 0 ) result = 1;  
20: else if( kk < 0 ) result = -1;  
21:  
22: if( m == result ) return( temp );  
23: else return( name );  
24:}  
  上面的代码用一般的编译器编译是一段有效的代码,但是用PC-LINT编译就会有几个告  
警。首先第8行向name数组赋值时丢掉了nul字符,第10行的乘法精度会失准,第11行的比  
较有问题,第14行的变量k没有初始化,第15行的kk可能没有被初始化,第22行的result也  
有可能没有被初始化,第23行返回的是一个局部对象的地址。这段代码在大部分编译器下  
是可以顺利编译通过的,继续查找其中的错误就要靠人工调试程序,如果程序很大,这将  
是一项烦琐的工作,没有人可以保证能找出所有的这类问题,但PC-LINT只通过一次简单的  
编译就可做到,显然为我们节省了大量的开发时间。  

  下面就让我们看看如何安装使用PC-LINT。  
2.如何安装PC-LINT  
  PC-LINT的软件的安装过程比较复杂,选项较多,下面根据安装过程,逐条说明每一步  
的含义。  
0)如果是zip文件,将ZIP安装文件展开到目录C:\lint.ins下,进入COMMAND PROMPT,先  
进行目录映射 subst g: c:\lint.ins,然后转到G: , 执行install。其他步骤和下面的从  
软盘安装是一样的。  

1)在A:驱插入PC-LINT安装盘,输入A:\>install命令,进入开始安装栏,按任意键继续,  
进入PC-LINT介绍栏,再按任意键继续。  
2)进入环境选择栏,这一栏中有三个选项:  
Windows NT/Windows 95  
MS-DOS(DOS extended)  
OS/2(32bit)  
如果计算机安装了WIN95、WIN97、WIN98或WINNT要选择Windows NT/Windows 95,如果  
只有DOS则选择DOS。  
3)进入安装目录选择栏,它推荐的是C:\>LINT,如不想安装在这个目录下,可输入自己想  
要安装的目录,然后按回车确认,如果要安装的目录不存在,它会提示为你建立这个目录  
。我们这里选C:\>LINT  
4)选择安装盘所在的磁盘驱动器,我们这里选A:  
5)判断是否要选择多种编译器或编译库的配置,如果要对不同编译环境下的程序进行L  

INT,则选YES,否则选NO。然后回车确认。  
6)这时看到一个编译器列表,在这个表中选择自己使用的编译器,如果表中没有自己使用  
的编译器,可选择通用编译器:Generic Compilers。按回车确认。这个选项会体现在co-  
xxx.lnt文件中。  
7)接着安装程序会让你选择一个的内存模型,可以根据自己程序区和数据区的实际大小选  
择一个恰当的内存模型。如果CPU为32位68K系列,则要选择:32-bit Flat Module。  
内存模型的选项会体现在STD.LNT文件中。  
8)选完内存模型后,会看到一个库类型的列表,在这里选择一个或多个编译时使用的库。  
这个选项会体现在LIB-xxx.LNT文件中。  
9)接着是让你选择为使用C++编程提出过重要建议的作者,选择的某作者后,他提出的编  
程建议方面的选项将被打开。与作者选择有关的选项会体现在AU-xxx.LNT文件中。  
10)下一步是设置包含文件目录。有两种选项,第一种是使用环境变量INCLUDE,环境变量  
在批处理文件中设置,环境变量后每个目录用分号隔开,例如可设成“INCLUDE=C:\MRI\M  
CC68K;D:\LAP\SRC\INC”。第二种选项是使用-i选项,-i选项体现在STD.LNT文件中,每个  
目录前以-I引导,目录间以空格分隔,例如可设成“-IC:\MRI\MCC68K -ID:\LAP\SRC\INC  
”。如果选择使用-I选项,安装程序会接着让你输入包含文件所在的目录。  
11) 如果前面选择了使用多个编译环境,这里将会问你是否选择更多的编译环境,如果选  
YES,将会从第6步开使重复。如果选NO则会结束编译器选择。  
12)接下来将会准备产生一个 反映全局编译信息显示情况的选项文件OPTIONS.LNT,该文  
件的产生方式有两种,一种是安装程序对几个核心选项逐一解释并提问你是否取消该选项  
,如果你选择取消,则会体现在OPTIONS.LNT文件中,具体体现方式是在该类信息编码前加  
-e,后面第13~18步是逐一选择核心选项的过程。如果选择第二种选择方式,安装文件会先  
生成一个空的OPTIONS.LNT文件,等你以后在实际应用时加入必要的选项。  
13)是否关闭赋值时的布尔测试告警,如:if(a=f()){...  
14)是否关闭赋值时的有符号量和无符号量间的不匹配告警,通常情况下,这种赋值不会  
带来问题,选择关闭该告警信息的同时,其他类型的有符号量和无符号量间混合操作的告  
警仍然是打开的。  
15)当把一个整形量赋值给一个比它短的量时,后者会丢失精度,例如把一个INT量赋值给  
给一个CHAR量。本步是让你选择是否关闭该类告警。  
16)是否关闭左移带符号量的告警。通常PC-LINT会对所有带符号量的移动产生告警,但右  
移一般是由不同的CPU来确定是否将符号位移入,左移一般是不会产生什么问题的,所以可  
以选择关闭该告警。  
17)在一个C函数被定义或声明前调用它,并不总是会产生错误,在这里可以选择是否关闭  
该告警选项。该选项对C++程序不起作用。  
18)是否关闭“调用不存在的函数原型”告警。有些程序员不愿遵守严格的函数原形定义  
约定,但PC-LINT会在调用一个没有定义的函数原型时产生一个告警,在这里可以选择关闭  
该告警。  
19)通过上面的步骤确定OPTIONS.LNT文件的形式后,接着是选择编译环境。PC-LINT提供  
了集成在多种开发环境中工作的功能,例如可集成在VC、BC、Source Insight中。假如我  
们在这里选择Source Insight。选择后安装程序会继续问你是否还选择其它的环境,可根  
据自己应用的实际情况选择一种或多种开发环境。开发环境的选择情况记录在env-xxx.ln  
t文件中。  
20)安装程序会生成一个LIN.BAT文件,该文件是运行PC-LINT的批处理文件,为了使该文  
件能在任何路径下运行,安装程序提供了两种方法供你选择。第一种方法是让你选择把LI  
N.BAT拷贝到任何一个PATH目录下,在安装结束运行LCOPY.BAT文件时,会把LIN.BAT拷贝到  
你指定的目录。第二种方法是生成一个LSET.BAT文件,在每次使用PC-LINT前先运行它来设  
置路径,或者把LSET.BAT文件的内容拷贝到AUTOEXEC.BAT文件中。  
21)在安装程序执行完后第一件事是在你安装的目录下执行LCOPY.BAT文件。它会从安装盘  
拷贝将一些文件拷贝到安装目录下,并根据你在安装过程中的选择来设置文件中的参数。  

3.LINT 一个C文件  
3.1用命令行方式进行LINT  
如果使用LIN.BAT批处理文件进行LINT,在LINT前要先看一下该批处理文件中的内容,里面  
包含了LINT-NT命令和命令选项,可以根据自己的要求来修改、增减选项。我们看到,在这  
个批命令中嵌套了一个std.lnt文件,在std.lnt文件中还嵌套了co.lnt、options.lnt和l  
ib-stl.lnt文件,原则上*.lnt文件是可以无限制嵌套,该类文件中一般都是了LINT的选项  
,可通过修改这些文件来修改LINT选项,选项是按照从左到右的顺序执行的。可执行下面  
命令行:  
C:\abc\src>lin alpha.c beta.c gamma.c  
通常对于由多个C模块组成的程序,最好先分别对每个C模块单元进行LINT检查,做单元LI  
NT时可如下运行:  
C:\abs\src>lin -u alpha.c  
其中-u是单元选项,使用-u后可以关闭一些检查多模块时会产生的告警,例如“函数未被  
使用”或“函数没有定义”等。  
也可以不使用LIN.BAT批处理文件,而直接使用LINT命令。在DOS环境下LINT命令为LINT.E  
XE,在Windows95/NT环境下为LINT-NT.EXE,在OS2环境下为LINT-OS2.EXE。直接使用LINT  
命令要注意的一点是要在使用前预先设置LINT目录所在路径,最好的方法是把该路径加在  
AUTOEXEC.BAT文件中。其它的使用方法与使用批处理文件相同。例如:  
C:\abs\src>lint-nt -ic:\lint\ std.lnt -os(_lint.tmp) *.c  
3.2用开发环境进行LINT  
也可以使用开发环境来执行LINT操作,一般开发环境都支持运行可执行文件,但不一定支  
持运行批处理文件,下面用Source Insight , Ultra Edit, MSVC 6.0 来举例说明如何在  
开发环境下进行LINT。  
3.2.1 在Source Insight中集成  
如果你在安装过程中选定了使用某个开发环境,安装程序会在你安装的目录下生成一个en  
v-xxx.lnt的文件,例如选择了Source Insight就会有一个env-si.lnt文件。用编辑器打开  
该文件,在该文件开始的注释中说明了如何将PC-LINT功能集成在开发环境中,集成在Sou  
rce Insight中的过程如下:  
1)从Options菜单中选择“Custom Commands”命令项。  
2)在Name栏中输入“PC-lint ”,原则上这个名称可以随便起,只要你能搞清楚它的含义  
就可以了。  
3)在Run栏中输入“c:\lint\lint-nt -u -ic:\lint std env-si %f”其中c:\lint是你P  
C-LINT的安装目录。  
4)在Output栏中选择“Iconic Window”、“Capture Output”。  
5)在Control栏中选择“Save Files First”。  
6)在Source Links in Output栏中选择“Parse Links in Output”、“File,then Lin  
e”。  
7)在Pattern栏中输入“^\([^ ]*\) \([0-9]+\)”。  
8)点Add键加入该命令。如下图:  
9)使用时,在Source Insight下打开要LINT的文件,打开Options菜单中的“Custom Com  
mands”命令项,在“Command”栏中选择“PC-lint unit check”命令运行即可。  
注意到我的Run一栏的参数和上面的提示不一样,其实我的其他古怪参数都放到c:\lint\s  
td.lnt中了。请注意,不论你怎样配置参数一定不要忘记了将si-env.lnt包含在你的配置  
文件里,否则就无法进行错误信息和程序的自动对应了。  
为了使用方便,你还可以配置一下Menu按钮,将它加到系统菜0单里,这属于一般性的  
Source Insight应用,笔者就不在此赘述了。  
第二笔者在NT中使用Source Insight时,好象集成不了,原因暂时不明了。上面的例子在  
WIN 95下测试成功。  
如果要修改LINT选项,可直接在Run栏中修改,也可专门编辑一个*.lnt文件放在c:\lint目  
录下,并将该文件名加入Run栏中,和命令行方式是一样的。  
3.2.2在Ultra Editor中集成  
选取 Menu | Advanced | Tool Configuration ... , 显示如下图:  
1)点按“Insert",  
2)在command line:中填写:c:\lint\lint-nt c:\lint\std.lnt %f  
3)在Menu Item中填写:PC-LINT  
4)在Command Output中选择: (x) Output to List Box 和 (x) Capture Output  
5)点按"OK"  
如图所示的配置笔者在UE6.0 / NT 4.0 下测试成功。  
3.2.3 在MSVC 6.0中集成  

//这个好使过
基本原理是一样的:  
1)选取 menu | tools | customize.....  
2)选取 Tools Tab:  
3)点按主对话框上方的虚线小方框 New a tool item  
4)输入 name: PC-LINT  
5)输入 Command: c:\lint\lint-nt.exe  
6)输入 Arguments: c:\lint\std.lnt $(FilePath)  //注:替std.lnt为lnt\env-vc6.lnt
7) 选择 (x) Use Output Window  
8)Close  
完成后,在tools菜单下就会有一项PC-LINT选项。  
下面是笔者在VC6 / Win NT 4.0 的情况下的TOOL配置图:  
3.3LINT选项  
LINT选项可以放在注释中,例如:  
/*lint option1 option2 ... optional commentary */  
//lint option1 option2 ... optional commentary  
选项间要以空格分开,lint命令一定要小写,并且紧跟在/*或//后面,不能有空格。如果  
选项由类似于操作符和操作数的部分组成,例如-esym(534, printf, scanf, operat or  
new),其中最后一个选项是operator new,那么在operator和new中间只能有一个空  
格。  
选项还可以放在宏定义中,例如:  
#define DIVZERO(x) /*lint -save -e54 */ ((x) /o) /*lint -restore */  
LINT的选项很多共有300多种,大体可分为以下几类:  
1)错误信息禁止选项  
该类选项是用于禁止生成某类错误信息的选项,最常用的是-e和+e,-e是禁止生成某类错  
误信息,+e是恢复生成某类错误信息。运行lint目录下的msg.exe可以得到msg.txt文件,  
这个长达5000行的文件包含了所有的错误信息号和解释。  
-w 对于所有大于级别的告警信息都不显示。  
-wlib()对于所有大于级别的关于库函数数的告警信息都不显示。我们可以用-wlib(0)来屏  
蔽所有的库函数的告警信息,-wlib(1)只显示库函数中的句法错误。  
-esym(#,) 可以屏蔽对于特定符号的某告警信息。  
2)变量类型大小选项  
不同的目标机、编译系统变量类型的的大小(如短整形变量、整形变量等)会有所不同,  
该类选项用于为目标机设置变量类型的大小。由于默认的设置与大部分的编译器是匹配的  
,这些专门的设置通常情况下是不需要的,只在特别的目标机结构中才用。例如一个M680  
00目标机,它的int类型和指针类型通常是32bit的,这时你应该使用选项:-si4  
-sp4。这些尺寸参数的当前值可以通过help屏来获得,例如可以输入以下命令行:  
lin -si4 -sp4 ?  
3)冗长信息选项  
冗长信息指的是LINT过程中产生的一些与编译过程有关的信息,而不是真正的告警信息、  
错误信息等。是否生成这些信息可以通过-v和+v选项来决定。+v是生成这些信息,-v是关  
闭这些信息,这组选项中除+v外,其它所有选项都可以关闭+v选项。  
4)标记选项  
以+f、++f、-f和--f开头的选项是标记选项。他们的逻辑含义分别如下:  
+f...:通过把标志置为1而把它置为ON  
-f...:通过把标志置为0而把它置为OFF  
++f...:标志增1  
--f...:标志减1  
后面两个用于你想在局部把一个标志置为ON的情况,而不影响全局设置。例如你可以这样  
使用:  
/*lint ++flb */  
int printf( );  
/*lint --flb */  
标记选项的种类很多,基本含义是用于打开或关闭某类语法情况使用,例如允许使用缩写  
结构体名称,允许使用无名联合体,把所有模块当作C++编译等。  
5)消息显示选项  
消息显示选项用于定义消息输出格式。主要有消息高度选项、消息宽度选项、消息格式选  
项等。  
6)其它选项  
其它选项中的种类很多,各种类间差异很大,在这里就不一一介绍了,建议大家看一看《  
PC-LINT》一书,第五章有对每种选项的详细说明。lint本身也有一些说明信息, lint-n  
t 2> lint.txt 然后狂按几个回车就可以生成一个lint选项的说明文件。  
4.LINT一个工程下的多个C文件  
4.1为何要LINT多个C文件  
在程序编码初期,我们关心的可能只是单个C模块种中的语法问题,等到编程后期,对于由  
多个C模块组成的程序,我们希望了解当把多个模块连接在一起后是否还有存在于模块间的  
语法问题。这时编译器虽然能给出一些告警,但PC-LINT的连接能给出更多的告警。还有当  
我们能保证其中的几个模块相对稳定,而另外几个模块仍有问题时可以先将几个稳定的模  
块编译连接成一个目标文件,文件每次修改完成后先单独编译,然后连接入总的目标文件  
。  
4.2如何LINT一个工程下的多个C文件  
象我们平时使用的编译工具一样,PC-LINT在编译连接多个C文件时也会先把每个C文件编译  
生成中间的目标文件*.lob,然后再将所有的LOB文件连接在一起。LOB是Lint Object Mod  
ule的缩写。这个文件中包含了一个C或C++模块的所有外部信息。生成LOB文件时有三种选  
项要注意:第一种是-u,如果要LINT生成LOB文件,就一定要加-u选项;第二种是-zero或  
-zero(500)选项,为了保证LOB文件在模块存在错误的情况下也能生成,就一定要加这个选  
项;第三种是-oo[(filename)],filename是生成的LOB文件的名称,在-oo后面,可加,也  
可不加,如不加,则LOB文件名与原C模块的名称相同,例如:  
lint -u alpha.c -oo(a1)  
生成的LOB文件名为:a1.lob  
lint -u alpha.c -oo  
生成的LOB文件名为:alpha.lob  
LINT一个工程下的多个C模块,在用户的源程序目录下一般需要三个文件: 一个选项文件  
(*.lnt)、一个批处理文件(*.bat)和一个MAKEFILE文件(*.mak)。下面一一讲述如何  
制作这些文件。  
1)选项文件(*.lnt)  
选项文件在前面也提到过,你可以把你LINT每个C文件时时用到的所有公共选项罗列在该文  
件中,选项生效的顺序按照从左到右,从上到下的原则。该类文件可以层层嵌套,嵌套的  
层数没有限制。例如make.lnt文件:  
-iC:\lint  
std.lnt  
+os(temp)  
-e46  
+vm  
-zero  
2)批处理文件(*.bat)  
制作批处理文件时要注意要在该文件中调用TCMAKE.EXE文件和MAKEFILE文件,例如lintma  
ke.mak文件:  
@echo Lint Making 'makelap':  
tcmake -flintmake.mak  
@echo End of making  
3)MAKEFILE文件(*.mak)  
MAKEFILE使用的TCMAKE的语法,和我们平时开发编译时使用的MAKEFILE文件语法格式一样  
,例如下面的lintmake.mak文件:  
MCCPATH = c:\mcc68k  
OPTION = -u make.lnt -oo  
GLOBLE = os.h l2lap.h  
mail_depend = $(GLOBLE) q931.h mail.h  
lapmain_depend = $(GLOBLE) l1pubdef.h q931.h mail.h  
lapos_depend = $(GLOBLE)  
fhdlc1_depend = $(GLOBLE) cpuhdlc.h bd_prar.h q931.h  
OBJ = mail.lob lapmain.lob lapos.lob fhdlc1.lob  
project.lob : $(OBJ)  
lint-nt make.lnt -e768 -e769 *.lob  
mail.lob: mail.c $(mail_depend)  
lint-nt $(OPTION) mail.c  
lapmain.lob: lapmain.c $(lapmain_depend)  
lint-nt $(OPTION) lapmain.c  
lapos.lob: lapos.c $(lapos_depend)  
lint-nt $(OPTION) lapos.c  
fhdlc1.lob: fhdlc1.c $(fhdlc1_depend)  
lint-nt $(OPTION) fhdlc1.c  
4.3简单的LINT多个文件  
假设我们的工程不复杂,我们可以负担起每次都将所有的文件都lint一遍的开销,也可以  
不使用上面的正规用法。笔者在实践中发现,将所有的*.c文件放在一个lint命令中,同样  
能完成lint整个工程的目的。  
如:  
lint-nt c:\lint\std.lnt AllMySource.lnt  
在AllMySource.lnt中包括你的工程中的所有源文件:  
a1.c  
a2.c  
a3.c  
需要注意的是,在std.lnt文件中就不需要-u选项了。因为我们已经提供了所有的信息。
********************************************************************************/

在大概看完了上述资料后,就可以把这个工具正式用于我们的程序了。
将该工具集成到VC++里是最常用到的,在网上也可以找到很多相关资料。
现在我简单的讲一下将它集成到Editpuls里,因为我比较喜欢用纯文本编辑器写代码,呵呵!

还是先看看网上的关于这方面的资料:-P
               http://xyzboard.com/?q=node/58

现在我写下我的经验:
在上述资料里有一些要修改的地方。

首先要注意Unix下xargs命令的使用。一定要给全路径!
比如我的是这样设参数项的:
$(FilePath) -name *.c -o -name *.cpp | D:\UnxUtils\usr\local\wbin\xargs
D:\Sources\PC-Lint\lint-nt -i"D:\UnxUtils\usr" -u D:\Sources\PC-Lint\std.lnt
D:\Sources\PC-Lint\env-vc6.lnt -w
也就是说xargs后的路径要给全。。。。

再有就是在编写std.lnt文件的时候要注意的,这个是我的std.lnt文件:
D:\Sources\PC-Lint\co-msc60.lnt

D:\Sources\PC-Lint\lib-w32.lnt

D:\Sources\PC-Lint\options.lnt -si4 -sp4

-i"D:\Microsoft Visual Studio 8;D:\Microsoft Visual Studio 8\VC\include"

-wlib(0)

最后的-wlib(0)是取消对编译器库文件的审查,这个是相当重要的一个参数。如果
你只是想审查自己的代码的话,请加上这个参数。不然,就会对编译器的库函数也
进行审查。。。。想看看库文件的可以研究一下,呵呵!
好了,现在你就可以对自己的代码进行摸底咯~~~~

下面这个是我的一个数据结构的实验:Complex的代码
/**********************************************************************

  File name: Complex.h                                                       
  Function: The description of complex class                               
  Platform: Win Xp SP2                                                       
  Compiler & Linker: CL.exe 8.0 (in Visual Studio 2005 SDK)         
  Programmer: 88250                                                       
  Complete date: September 7, 2006    Version: 1.0                       
  Blog: http://DL88250.ynutx.net                                       
  E-mail: DL88250@gmail.com                                               
  QQ: 845765 or 316281008                                               
       
**********************************************************************/

#include <iostream>

using namespace std;

class complex
{
    public:        // public interface
                complex(double r, double i);        // constructor
                void assign(void);        // user input to define a complex
                // overload operators to friend functions
                friend complex operator + (complex &c1, complex &c2);       
                friend complex operator - (complex &c1, complex &c2);
                friend complex operator * (complex &c1, complex &c2);
                friend complex operator / (complex &c1, complex &c2);
                friend ostream& operator << (ostream &out, complex x);
        private:
                double real;
                double imag;
};

/**********************************************************************
  
  File name: Complex.h                                                       
  Function: A simple complex calculator demo                               
  Platform: Win Xp SP2                                                       
  Compiler & Linker: CL.exe 8.0 (in Visual Studio 2005 SDK)   
  Programmer: 88250                                                       
  Complete date: September 7, 2006    Version: 1.0                       
  Blog: http://DL88250.ynutx.net                                       
  E-mail: DL88250@gmail.com                                               
  QQ: 845765 or 316281008                                               
                                  
**********************************************************************/

#include "Complex.h"

complex::complex(double r = 0.0, double i = 0.0)
{
        real = r;
        imag = i;
        return;
}

void complex::assign(void)
{
        cout << "Please input the real part : " << endl;
        cin >> real;
        cout << "Please input the imaginary part: " << endl;
        cin >> imag;

        return;
}
ostream& operator << (ostream &out, complex x)
{
        if (x.imag < 0)
        {
                return (out << x.real << " + " << "(" << x.imag << ")" << "i" <<
endl);
        }
        else
        {
                return (out << x.real << " + " << x.imag << "i" << endl);   
        }
}       

complex operator + (complex &c1, complex &c2)
{
        return complex(c1.real + c2.real, c1.imag + c2.imag);       
}

complex operator - (complex &c1, complex &c2)
{
        return complex(c1.real - c2.real, c1.imag - c2.imag);       
}

complex operator * (complex &c1, complex &c2)
{
        return complex((c1.real * c2.real - c1.imag * c2.imag)
                                   ,(c1.real * c2. imag + c2.real * c1.imag));       
}

complex operator / (complex &c1, complex &c2)
{
        double denominator = c2.real * c2.real + c2.imag * c2.imag;
        return complex((c1.real * c2.real + c1.imag * c2.imag) / denominator
                                   ,(c1.imag * c2.real - c1.real * c2.imag) /
denominator);       
}

int main(void)
{
        complex c1(5, 4), c2(2, 10);
       
        cout << "c1 = " << c1;
        cout << "c2 = " << c2;

        cout << "c1 + c2 = " << c1 + c2;
        cout << "c1 - c2 = " << c1 - c2;
        cout << "c1 * c2 = " << c1 * c2;
       
        c1.assign();
        cout << "Current c1 = " << c1;
        c2.assign();
        cout << "Current c2 = " << c2;
        cout <<"c1 / c2 = " << c1 / c2;

        return 0;
}

现在用PC-Lint审查一下:

PC-lint for C/C++ (NT) Ver. 8.00e, Copyright Gimpel Software 1985-2001

--- Module:   D:\Sources\C++\DataStructure\Exp1\Complex.cpp
};
D:\Sources\C++\DataStructure\Exp1\Complex.h(33): error 1712: (Info -- default co
nstructor not defined for class 'complex')
*/

D:\Sources\C++\DataStructure\Exp1\Complex.h(70): error 783: (Info -- Line does n
ot end with new-line)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(44): error 1746: (Info -- paramete
r 'x' in function 'operator<<(std::basic_ostream<char,std::char_traits<char>> &,
complex)' could be made const reference)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(49): error 1764: (Info -- Referenc
e parameter 'c1' (line 46) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(46): error 830: (Info -- Location
cited in prior message)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(49): error 1764: (Info -- Referenc
e parameter 'c2' (line 46) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(46): error 830: (Info -- Location
cited in prior message)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(54): error 1764: (Info -- Referenc
e parameter 'c1' (line 51) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(51): error 830: (Info -- Location
cited in prior message)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(54): error 1764: (Info -- Referenc
e parameter 'c2' (line 51) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(51): error 830: (Info -- Location
cited in prior message)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(60): error 1764: (Info -- Referenc
e parameter 'c1' (line 56) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(56): error 830: (Info -- Location
cited in prior message)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(60): error 1764: (Info -- Referenc
e parameter 'c2' (line 56) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(56): error 830: (Info -- Location
cited in prior message)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(68): error 1764: (Info -- Referenc
e parameter 'c1' (line 62) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(62): error 830: (Info -- Location
cited in prior message)
}
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(68): error 1764: (Info -- Referenc
e parameter 'c2' (line 62) could be declared const ref)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(62): error 830: (Info -- Location
cited in prior message)
    complex c1(5, 4), c2(2, 10);
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(72): error 747: (Info -- Significa
nt prototype coercion (arg. no. 1) int to double)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(72): error 747: (Info -- Significa
nt prototype coercion (arg. no. 2) int to double)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(72): error 747: (Info -- Significa
nt prototype coercion (arg. no. 1) int to double)
D:\Sources\C++\DataStructure\Exp1\Complex.cpp(72): error 747: (Info -- Significa
nt prototype coercion (arg. no. 2) int to double)
}

D:\Sources\C++\DataStructure\Exp1\Complex.cpp(88): error 783: (Info -- Line does
not end with new-line)

--- Global Wrap-up

error 1754: (Info -- Expected symbol 'operator*=' to be declared for class 'com
plex')
error 1754: (Info -- Expected symbol 'operator+=' to be declared for class 'com
plex')
error 1754: (Info -- Expected symbol 'operator-=' to be declared for class 'com
plex')
error 1754: (Info -- Expected symbol 'operator/=' to be declared for class 'com
plex')
error 900: (Note -- Successful completion, 28 messages produced)
请按任意键继续. . .

哎。。。。问题好多。。。。

改了下代码:
/**********************************************************************

  File name: Complex.h                                                       
  Function: The description of complex class                               
  Platform: Win Xp SP2                                                       
  Compiler & Linker: CL.exe 8.0 (in Visual Studio 2005 SDK)         
  Programmer: 88250                                                       
  Complete date: September 7, 2006    Version: 1.0                       
  Blog: http://DL88250.ynutx.net                                       
  E-mail: DL88250@gmail.com                                               
  QQ: 845765 or 316281008                                               
       
**********************************************************************/

#include <iostream>

using namespace std;

class complex
{
    public:        // public interface
                complex(double r, double i);        // constructor
                complex(void);        // void constructor
                void assign(void);        // user input to define a complex
                // overload operators to friend functions
                friend complex operator + (const complex &c1,
                                           const complex &c2);       
                friend complex operator - (const complex &c1,
                                           const complex &c2);
                friend complex operator * (const complex &c1,
                                           const complex &c2);
                friend complex operator / (const complex &c1,
                                           const complex &c2);
                friend ostream& operator << (ostream &out, const complex &x);
        private:
                double real;
                double imag;
};

/**********************************************************************
  
  File name: Complex.h                                                       
  Function: A simple complex calculator demo                               
  Platform: Win Xp SP2                                                       
  Compiler & Linker: CL.exe 8.0 (in Visual Studio 2005 SDK)   
  Programmer: 88250                                                       
  Complete date: September 7, 2006    Version: 1.0                       
  Blog: http://DL88250.ynutx.net                                       
  E-mail: DL88250@gmail.com                                               
  QQ: 845765 or 316281008                                               
                                  
**********************************************************************/

#include "Complex.h"

complex::complex(void)
{
        real = 0;
        imag = 0;

        return;
}

complex::complex(double r = 0.0, double i = 0.0)
{
        real = r;
        imag = i;
        return;
}

void complex::assign(void)
{
        cout << "Please input the real part : " << endl;
        cin >> real;
        cout << "Please input the imaginary part: " << endl;
        cin >> imag;

        return;
}
ostream& operator << (ostream &out, const complex &x)
{
        if (x.imag < 0)
        {
                return (out << x.real << " + " << "(" << x.imag << ")" << "i" <<
endl);
        }
        else
        {
                return (out << x.real << " + " << x.imag << "i" << endl);   
        }
}       

complex operator + (const complex &c1, const complex &c2)
{
        return complex(c1.real + c2.real, c1.imag + c2.imag);       
}

complex operator - (const complex &c1, const complex &c2)
{
        return complex(c1.real - c2.real, c1.imag - c2.imag);       
}

complex operator * (const complex &c1, const complex &c2)
{
        return complex((c1.real * c2.real - c1.imag * c2.imag)
                                   ,(c1.real * c2. imag + c2.real * c1.imag));       
}

complex operator / (const complex &c1, const complex &c2)
{
        double denominator = c2.real * c2.real + c2.imag * c2.imag;
        return complex((c1.real * c2.real + c1.imag * c2.imag) / denominator
                                   ,(c1.imag * c2.real - c1.real * c2.imag) /
                        denominator);       
}

int main(void)
{
        complex c1(5.0, 4.0), c2(2.0, 10.0);
       
        cout << "c1 = " << c1;
        cout << "c2 = " << c2;

        cout << "c1 + c2 = " << c1 + c2;
        cout << "c1 - c2 = " << c1 - c2;
        cout << "c1 * c2 = " << c1 * c2;
       
        c1.assign();
        cout << "Current c1 = " << c1;
        c2.assign();
        cout << "Current c2 = " << c2;
        cout <<"c1 / c2 = " << c1 / c2;

        return 0;
}


现在好多了:

PC-lint for C/C++ (NT) Ver. 8.00e, Copyright Gimpel Software 1985-2001

--- Module:   D:\Sources\C++\DataStructure\Exp1\Complex.cpp

--- Global Wrap-up

error 1754: (Info -- Expected symbol 'operator*=' to be declared for class 'com
plex')
error 1754: (Info -- Expected symbol 'operator+=' to be declared for class 'com
plex')
error 1754: (Info -- Expected symbol 'operator-=' to be declared for class 'com
plex')
error 1754: (Info -- Expected symbol 'operator/=' to be declared for class 'com
plex')
D:\Microsoft Visual Studio 8\VC\include\xutility(873): error 628: (Warning -- no
argument information provided for function 'std::__is_base_of()' (line 873, fil
e D:\Microsoft Visual Studio 8\VC\include\xutility))
error 900: (Note -- Successful completion, 5 messages produced)
请按任意键继续. . .

关于剩下的问题可以参看PC-Lint目录下的msg.txt文件,里面有详细的解释。。。。
哎。。。。闪人咯~~~~
:-P
东陆风华APP客户端 http://bbs.ynutx.net/appbyme_app-download.html

本版积分规则

关闭

站长推荐上一条 /2 下一条

QQ|小黑屋|手机版|Archiver|东陆风华,凝聚云大人的力量 ( 滇ICP备07500061号-1 )

GMT+8, 2024-5-4 03:40 , Processed in 0.109375 second(s), 19 queries , Gzip On, Redis On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表