C++语言教学中编码标准化问题浅析

2008-07-14 10:05陈南京
电脑知识与技术 2008年18期
关键词:高等教育标准

陈南京 万 瑾

摘要:C++程序良好的可移植性使得C++语言成为程序设计人员的首选工具语言,而保证这一特性必需使用标准化的C++编码。国内高校尤其是高职院校的教材中,存在着大量非标准化的C++程序,不利于培养具有标准化C++编程风格的学生。本文从C++发展史、教育工作者和教材规范化等多个角度出发,分析了这一问题产生的原因,并提出了相应的解决办法。

关键词:C++标准;可移植性;高等教育

中图分类号:TP311文献标识码:A文章编号:1009-3044(2008)18-21ppp-0c

1 引言

1983年第一个C++程序投入使用,1994年8月,ANSI/ISO委员会草案登记,这便是业内所称的早期的C++标准,1998年11月,ISO/IEC:98-14882标准(以下简称98标准)被批准,标志着C++代码的标准化正式诞生[1]。C++语言诞生以来,延续了C语言的重要特征,即C++源程序良好的可移植性。正是这一特性,使得C/C++语言长期以来一直是程序开发人员的首选。

C++语言良好的可移植性是它具有较强生命力的关键所在。目前标准委员会正在修订C++标准,并拟于2009年发布修订后的09标准。可以预见,C++语言作为程序开发的主要工具仍将延续很长的一段时间。然而,国内高等教育尤其是高职教育,在C++语言的教学中却长期使用了非标准化的编码方式,这对于学生毕业后从事程序设计,写出具有良好可移植性的程序是相当不利的。

C++程序编码的标准化在互联网的一些论坛里有一些讨论,然而关于现行教材或专著里存在的问题,却鲜有文章进行报道。本文通过讨论现有高校教材尤其是高职教材中C++代码编写方式与现行C++标准的一些距离,试图引导高校教材尤其是高职教材中C++程序编码走向标准化。

2 标准化的目的和意义

标准化之争是信息时代商业竞争乃至国家之间竞争的必争之地。欧美的企业一直依赖都很热衷于标准化之争,UNIX从诞生到现在的各自为政就是一个很好的例子。而IT领域信息技术的高度集中和相对垄断也使得国际标准化组织制定的很多标准并没有被企业所采用,相反地,出现了很多像“Microsoft Windows”、“Internet Explorer”这种“事实上的工业标准”。C++语言从诞生到98标准诞生,花了整整15年的时间,对于发展迅猛的信息技术,这是一个相当漫长的过程。在此期间,国际上一些跨国公司如Microsoft、IBM、Borland(如今的Inprise)相继开发了自己的C++编译器,这些公司的编译器除了包含标准的C++编译器的内容之外,还加入了自己的一些特性,甚至修改了部分标准。一旦程序设计人员使用了这些非标准的特性,代码的可移植性将会成为一个大问题。因此,如何教导学生编写标准化的C++源程序,成为C++语言教学中一个非常重要的问题。

3 C++语言教学中存在的非标准化编码的主要问题

Microsoft公司曾经因为其在软件行业得天独厚的地位,而在MS Visual C++编译器中采使用了很多非标准化的内容。然而,在MS Visual Studio 2005发布之后,Microsoft公司相关人员特别指出该产品的一个重要变化就是完全符合98标准[2]。对于程序员来说,如果他原先在MS Visual C++中使用了非标准化的代码,在移植到MS Visual Studio2005这个平台上时将会花费相当大的精力去修改代码。即便是微软这样一个跨国企业,都不得不向国际标准靠拢,可想而知,标准化对于企业来讲是多么重要了。对于程序员,如何编写标准化的C++代码,保持C++代码的良好可移植性则是重中之重。然而,在我国的高校尤其是高职教材中却存在着甚至是大量存在着非标准化的C++程序,究其原因,笔者认为主要有如下几个方面:

3.1 C语言的影响

这也是最重要的一点。我国高校早期从事C++语言的教学和传播者主要是从C语言的使用者转移过来,C++语言的向下兼容性(即兼容C语言书写的源程序)使得这批教师能够较快的胜任C++语言的教学工作。不可否认,他们对中国高等教育的C++语言的教学和普及做出了不可磨灭的贡献。然而,C++语言所倡导的面向对象程序设计方法和C语言的面向过程程序设计方法还是存在着很大区别的,尤其是面向对象要求对数据进行封装保护的机制在C语言中是不存在的。而我们的第一批C++语言的传播者以及教材的编著者,却把C语言的风格和编程习惯带到了C++语言的教学中来,并且一直延续至今。例如:在C语言中主函数main是可以没有返回值的,即返回值类型可以是void,而在C++标准中,明确要求主函数main必须返回int类型。再例如,C语言中人们习惯使用字符数组或字符指针来保存字符串如char name[30], char *str等,而在C++中,提倡使用string对象来替代字符数组的变量。在我所使用的“十一五”国家级规范教材[3]中,从头到尾使用的都是字符数组和字符指针,而没有一处使用string对象,这明显违背了C++面向对象程序设计方法的精神。

有人问及C++语言的创始人也是C++标准的制定者之一Bjarne Stroustrup博士,有没有想过删除一些C++语言的特性。Bjarne Stroustrup博士说:从语言设计的角度讲,我最不喜欢的部分是与C兼容的那个子集[4]。然而,出于对现实世界里工作的程序员的考虑,保留与C兼容的子集是有必要的,但这并不意味着我们要写出C风格的C++程序。

3.2 大量非标准化编译器的影响

C语言和C++语言都是在UNIX平台下诞生的,在UNIX平台下使用的都是标准的编译器G++。而国内由于种种原因,UNIX平台一直未能进入主流的应用,大多数的企事业单位包括高校使用的都是MS Windows平台,高校教育又过分的偏爱了MS Visual C++这一典型的非标准C++编译器,即便是计算机等级考试这一全国性的考试,在C/C++的编程环境上也是选择了MS Visual C++。MS Visual C++编译器包含了很多与C++标准有出入的功能。这在某种程度上助长了C++的教学者编写出大量的非标准化代码。例如大家所熟悉的eof()函数,该函数根据当前指针是否指向文件结束部分而相应的返回true和false两个值,即当我们从一个文本文件读取数据时,如果指针指向文件的尾部则返回true,如果指针还未指向文件的尾部则返回false。MS Visual C++的编译器和基于标准C++的编译器如Dev-C++编译器对这个函数的处理却有很大的不同[5]。标准编译器在第一次读取文件的最后一个数据后仍然返回false,只有在试图继续读取数据时发现已经到了文件的结尾才返回true,而MS Visual C++编译器则在我们读取到文件的最后一个数据之后就返回true了。这样,针对不同的编译器,下面的这一段代码就有了不同的结果:

void totalFile(char *fName, float &total)

{

fstream rawData;

float itemPrice;

total = (float) 0.0;

rawData.open( fName, ios::in);

while(!rawData.eof())

{

rawData >> itemPrice;

total += itemPrice;

}

rawData.close();

}

假设我们的文本文件包含两个数据,如下:

6.00

1.25

如果我们使用MS Visual C++编译器,则最后得到的total值是7.25,而当我们用标准C++编译器如Dev-C++编译器,得到的结果则是8.5。对于MS Visual C++编译器而言,在读取1.25之后就认为文件已经结束,并且令eof()函数返回true值,while循环结束;而对于Dev-C++编译器,读取1.25后并没有认为文件已经到达尾部,因此,eof()返回的是false,循环继续执行,在试图继续读取数据时才知道文件已经结束,但此时的循环体多执行了一次,所以如果不作判断而直接使用上面的代码,则最后一个数据将会两次被加到total上。因此,要得到准确的结果7.25,标准C++的代码应该是这样的:

void totalFile(char *fName, float &total)

{

fstream rawData;

float itemPrice;

total = (float) 0.0;

rawData.open( fName, ios::in);

while(!rawData.eof())

{

rawData >> itemPrice;

if(!rawData.eof())/*这边增加一个判断,

以避免读取的最后一个数据被运算两次 */

total += itemPrice;

}

rawData.close();

}

从上面的例子我们可以看出,基于非标准C++的编译器和标准C++的编译器在一些地方会有很大的出入,这种情况下,如果毫不知情的将非标准的C++代码移植到标准C++的编译器中进行编译,无疑将会得到意想不到的结果。可见,只有编写出标准的C++代码,才能满足程序的可移植性这一重要特点。

3.3 国内部分教育者对国际标准的漠视

国内程序设计语言如C++语言的传播者(以高校教师为主)甚少关注国际标准,很多老师甚至于不知道自己写出来的程序是否符合国际标准,通常情况下只是简单的将写出来的程序在某一特定编译器下编译测试通过就草草了事,导致C++语言教学的教材和各类专著充斥着大量的非标准代码。国际标准委员会为了让C++语言更好的实现面向对象程序设计的封装,在颁布的98标准中对原先提交的标准进行了一些修订,同时为了使得原有的程序不至于全部都要进行修改,保留了对原有标准的兼容性。而国内的高校教材中却很少对这些标准进行深入的研究。例如头文件包含

#include

这样的写法,在98标准中已经被废弃了,而改为使用不含.h的标准写法。

#include

原因之一是随着时间的推移,还能够继续支持.h的头文件包含的编译器将会越来越少,其次,标准写法在多个方面显示出了它的优越性,如对异常的捕获和处理、与其它C++标准类对象在接口方面的结合更紧密以及对本地化更好地支持,更为重要的一点是,iostream所定义的组件被声明为命名空间std的成员,而iostream.h定义的组件则被声明为全局的,不利于实现面向对象的封装性。然而,国内教材中却大量使用了前一种被废弃的写法。

3.4 国内教材出版业的规范化有待完善。

由于众所周知的原因,国内高校教师出版教材很多时候是迫于压力不得不做的事情,而出版业的过分商业化在一定程度上助长了这种风气,导致国内出版的教材良莠不齐。尽管近些年在引进国外的优秀图书方面出版界作了很大的努力,但是对于教材审查和出版的相对放松在广大学生中形成的不好的编程习惯是很难一下子扭转过来的,特别是高职院校的教材主要是以高职院校的教师自己编写的为主。Bjarne Stroustrup博士在谈到如何选择学习C++语言的书籍时说到:务必注意该书是不是从一开始就讲授标准C++,并且矢志不渝地使用标准库机制[4]。例如,从输入中读取一个字符串应该是这样的:

string s; /*标准C++程序的风格*/

cin>>s;

而不是这样的:

char s[MAX]; /*标准C程序的风格*/

scanf("%s",s);

可惜,在国内很多C++语言教材中都采用了后者,完全符合C++标准的高校教材是少之又少。

4 问题的解决

造成C++语言教材和专著中大量存在着非标准化代码的原因是多方面的,因此,要解决这个问题,我认为,应该从以下几个方面入手:

1) 选择标准化的C++编译器。标准化的C++编译器在编译非标准的C++代码时会给出警告信息,编译人员可以根据警告信息修改自己的代码,使之符合标准C++程序的编码风格;

2) 提高教材或专著出版者尤其是高校教师自身的素质。标准C++编译器不是万能的,例如上面所提到的eof()函数存在的问题,是编译器没有办法检查出来的。作为知识的传播者,高校教师应该努力学习本行业的相关标准,写出符合国际标准的代码,使之具有良好的可移植性;

3) 提倡教材编写与标准化相接轨,规范教材的编写和严格教材的出版。出版社应该组织权威的专家对准备出版的教材进行严格的审查,对不符合国际标准的写法予以纠正。这点在本科和研究生的教材出版中作的相对较好,而在刚起步而又发展迅猛的高职教材中问题较多。

参考文献:

[1] Juan Soulie. History of C++. [2008-1-18]. http://www.cplusplus.com/info/history.html.

[2] Bradley L. Jones. Breaking Changes in Visual C++ 2005. http://www.developer.com/net/cplus/article.php/3493706.

[3] 吴绍根,陈建潮,张婵 著. C++面向对象程序设计[M]. 清华大学出版社,2007.

[4] Bjarne Stroustrup. Bjarne Stroustrup's FAQ. http://www.research.att.com/~bs/bs_faq.html. [2008-2-5].

[5] Laurence Boxer. Porting Code between Language Implementations. http://purple.niagara.edu/boxer/essays/prog/porting.htm.

收稿日期:2008-04-18

作者简介:陈南京(1977-),硕士研究生,现就职于厦门华厦职业学院工科部,担任计算机教研室主任。

猜你喜欢
高等教育标准
2022 年3 月实施的工程建设标准
忠诚的标准
美还是丑?
你可能还在被不靠谱的对比度标准忽悠
大数据对高等教育发展的推动研究
基于Flash+XML技术的护理技能虚拟教学平台设计与实现
中国高等教育供给侧改革研究:起源、核心、内涵、路径
高等教育教学中的重与轻分析
一家之言:新标准将解决快递业“成长中的烦恼”
2015年9月新到标准清单