试卷代号:1008 中央广播电视大学2000—2001学年度第二学期“开放教育(本科)”期末考试(开) 计科技专业面向对象程序设计试题 2001年7月 一、???????????? 对错题。判断以下说法的正确性,在下面表格中对应的编号下面写上“对”或“错”。(20分,每个题目2分) 题号 1 2 3 4 5 6 7 8 9 10  对/错 ? ? ? ? ? ? ? ? ? ?  1.? 说明函数原型时不需要指明每个函数参数的名字,只需要说明每个参数的类型和返回值类型就可以了。 2.? 所有的表达式都有值。 3.? 程序的编译是以文件为单位的,因此将程序分到多个文件中可以减少每次对程序修改所带来的编译工作量。 4.? 类的静态数据成员需要在定义每个类的对象时进行初始化。 5.? 基类中被说明为protected和private的成员只能被其派生类的成员函数访问,不能被其它的函数访问。 6.? 当将一个类S定义为另一个类A的友元类时,类S的所有成员函数都可以直接访问类A的所有成员。 7.? 当函数的返回值是数组类型的,传递的是数组第一个元素的地址。 8.? 如果派生类的成员函数的原型与基类中被定义为虚函数的成员函数原型相同,那么,这个函数自动继承基类中虚函数的特性。 9.? 字符串’hello,world”在内存中存放时,占用11个字节的空间。 10.????????????? 用new动态申请的内存空间,必须用delete来释放 。 二、简单编程题。根据程序要求,写出函数的完整定义。(共25分) 1.(本小题15分)写一个函数,找出给定字符串中数字字符(即’0’—‘9’这10个数字)的个数(如字符串”olympic2000”中数字字符的个数为4个。函数的原型为: int CalcDigital(char *str); 函数参数:str为所要处理的字符串。 函数返回值:所给字符串中数字字符的个数。 int CalcDigital(char *str) { //在下面写出程序的实现 ? ? } 2.(本小题10分)用递归函数完成以下运算: sum(n)=12+22+…+n2 函数的原型如下: long sum(int n); 该函数完成12+22+…+n2的运算,并返回运算结果,其中n>0。 提示:你可以使用递归表达式:sum(n)=sum(n-1)+n2 long sum(int n) { ? ? } ? 三、???????????? (本小题30分) 下面的文件queue.h是一个队列类模板Queue的完整实现。在这个文件中首先定义了一个队列元素类模板QueueItem,然后在这个类的基础上定义了队列类模板Queue。在Queue中使用链表存放队列的各个元素,front指针指向链表的第一个节点元素,back指针指向链表的最后一个节点元素,成员函数add()将一个新节点元素加入到队列结尾,remove()从队列开头删除一个节点元素。为方便起见,程序中加上了行号。阅读程序,根据程序后面的问题作出相应解答。 1?????????? template<class Type> 2?????????? class Queue; 3?????????? /******************定义模板类QueueItem*******************************/ 4?????????? template <class Type> 5?????????? class QueueItem 6?????????? { 7?????????? public: 8?????????? QueueItem(const Type &elem):item(elem){} 9?????????? QueueItem(){} 10??????? private: 11??????? Type item; 12??????? QueueItem *nextItem; 13??????? friend class Queue<Type>; 14??????? }; 15??????? /***********************定义模板类Queue*****************************/ 16??????? template<class Type> 17??????? class Queue{ 18??????? public: 19??????? Queue():front(NULL),_______(A)_______{} 20??????? ~Queue(); 21??????? Type remove(); 22??????? void add(const Type &); 23??????? bool is_empty()const {return ____(B)____;} 24??????? private: 25??????? QueueItem<Type> *front; 26??????? QueueItem<Type> *back; 27??????? }; 28??????? //模板类Queue的函数成员remove()的实现 29??????? //从队列头取出一个节点,并返回该节点的值 30??????? template<class Type> 31??????? Type Queue<Type>::remove() 32??????? { 33??????? QueueItem<Type> *pFront; //指向头节点的临时指针 34??????? Type retVal; //返回值 35??????? ____(C)____; 36??????? retVal=front->item; 37??????? front=front->nextItem; 38??????? delete pFront; 39??????? return retVal; 40??????? } 41??????? //模板类Queue的函数成员add()的实现 42??????? template<class Type> 43??????? void Queue<Type>::add(const Type& newItem) 44??????? { 45??????? QueueItem<Type> *pNew=new QueueItem<Type>; 46??????? pNew->item=newItem; 47??????? ____(D)____; 48??????? if(front==NULL) 49??????? front=back=pNew; 50??????? else 51??????? { 52??????? back->nextItem=pNew; 53??????? ____(E)____; 54??????? } 55??????? } 56??????? 57??????? template <class Type> 58??????? Queue<Type>::~Queue() 59??????? { 60??????? QueueItem<Type> *p=front, *q; 61??????? while(p!=NULL) 62??????? { 63??????? q=p->nextItem; 64??????? delete p; 65??????? p=q; 66??????? } 67??????? } 问题1:(每个填空3分,共15分)程序中有几处填空,将它们完成。 (A)______________________________________________ (B)______________________________________________ (C)______________________________________________ (D)______________________________________________ (E)______________________________________________ ? 问题2:(本小题3分)题中程序第1、2行为什么要说明一下类模板Queue?如果没有这两行语句,程序还正确吗? 答: ? ? 问题3:(本小题4分)程序第22、23行各有一个const,它们各自表示什么含义? 答: ? ? 问题4:(本小题3分)程序中模板类Queue的析构函数主要做了什么事情?为什么要这么做? 答: ? 问题5:(本小题5分,每答对一个给1分)下面的程序使用了queue.h文件中定义的类模板,说明程序中哪些定义队列对象的语句是不正确的,哪些是正确的? #include “queue.h” ? void main() { Queue q1; //1 Queue<int> q2; //2 Queue<int> q3(100); //3 Queue<int> q4[100]; //4 Queue<int> q5=new Queue<int>; //5 //… delete q5; } 答: 语句号 1 2 3 4 5  对/错 ? ? ? ? ?  ? 四、???????????? (本小题16分)阅读下面的程序,写出程序运行的结果。 /*************************************************************/ #include <iostream.h> class A{ private: //…其它成员 public: virtual void func(int data){cout<<”class A:”<<data<<endl;} void func(char *str){ cout<<”class A:”<<str<<endl; } }; ? class B: public A{ //…其它成员 public: void func() {cout<<”function in B without parameter! \n”;} void func(int data) { cout<<”class B:”<<data<<endl; } void func(char *str){ cout<<”class B:”<<str<<endl;} }; int main(int argc,char *argv[]) { A *pA; B b; pA=&b; pA->func(1); pA->func(“haha”); return 0; } /*************************************************************************/ 问题1:(本小题4分)在下面写出程序的运行结果: ? 问题2:(本小题2分)如下句所示,在函数main()中通过pA调用类B中定义的参数表为空的函数func() : pA->func(); 是否正确? 答:(正确/不正确) ? ? 问题3:(本小题10分)如果要记录已尼创建的A类的实例(对象)的个数,我们可以借助于类的静态成员。修改上面类A的定义,使得它包含一个私有的静态成员object_count,记录属于该类的对象的个数,然后为类A增加必要的成员函数,使得下面的程序: void main() { A *pA=new A[3]; cout<<”There are ”<<pA->GetObjectCount()<<” objects”<<endl; delete []pA; cout<<”There are ”<<A::GetObjectCount()<<” objects”<<endl; } 得到的输出为: There are 3 objects There are 0 objects 在下面写出类A的定义(将所有的函数成员实现写在类定义体中): ? ? ? ? 在下面写出初始化类的静态成员object_count的语句: ? ? 五、(本题共9分) 下面的程序定义了一个简单的SmallInt类,用来表示从-128到127之间的整数。类的唯一的数据成员val存放一个-128到127(包含-128和127这两个数)之间的整数,为了方便,类SmallInt还重载了一些运算符。阅读SmallInt的定义,回答题目后面的问题。 class SmallInt{ public: SmallInt(int i=0); //重载插入和抽取运算符 friend ostream &operator<<(ostream&os,const SmallInt &si); friend istream &operator>>(istream &is, SmallInt &si); ? //重载算术运算符 SmallInt operator+(const SmallInt &si){return SmallInt(val+si.val);} SmallInt operator-(const SmallInt &si){return SmallInt(val-si.val);} SmallInt operator*(const SmallInt &si){return SmallInt(val*si.val);} SmallInt operator/(const SmallInt &si){return SmallInt(val/si.val);} //重载比较运算符 bool operator==(const SmallInt &si){return (val==si.val);} private: char val; }; SmallInt::SmallInt(int i) { while(i>127) i-=256; while(i<-128) i+=256; val=i; } ? ostream &operator<<(ostream &os,const SmallInt &si) { os<<(int)si.val; return os; } ? istream &operator>>(istream &is,SmallInt &si) { int tmp; is>>tmp; si=SmallInt(tmp); return is; } 问题1:(本小题4分)上面的类定义中,重载的插入运算符和抽取运算符被定义为类的友元函数,能不能将这两个运算符定义为类的成员函数?如果能,写出函数原型,如果不能,说明理由。 答: ? 问题2:(本小题5分)为类SmallInt增加一个重载的运算符’+=’,函数原型如下: class SmallInt{ public: SmallInt &operator +=(const SmallInt &si); //其它函数…… private: char val; }; 该函数将返回对当前对象的引用。如: SmallInt si1(20),si2(13); 则表达式: si1+=si2 将返回对象si1的引用,并且si1中的的值是si1.val和si2.val的值之和(但必须正规化为在-128至127之间)。 在下面写出重载的运算符+=的实现: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 试题答案 一、 题号 1 2 3 4 5 6 7 8 9 10  对/错 对 错 对 错 错 对 错 对 错 对  二、 1.? 程序为: int CalcDigital(char *str) { //判断字符指针是否为空 if(str==NULL) return 0; //记录数字字符个数的变量 int num_of_digital=0; //依次检查各个字符,如果是数字,则总数加1 for(int i=0;str[i]!=0x0;i++) if(str[i]<=’9’&&str[i]>=’0’) num_of_digital++; //返回数字字符个数 return num_of_digital; } ? 2.? 程序为: long sum(int n) { if(n==1) return 1; else return n*n+sum(n-1); } 三、 问题1:答案为: (A)????? back(NULL) (B)????? front==NULL或back==NULL (C)????? pFront=front (D)???? pNew->nextItem=NULL (E)????? back=pNew 问题2: 答:不正确。因为在类QueueItem模板类的定义中用到了模板类Queue,而此时Queue还没有定义,所以要先声明一下,告诉编译程序Queue是一个模板类,它将在程序的其它地方定义。如果没有这个说明,编译程序就不知道标识符Queue代表什么样的含义了。 问题3: 答:第22行的const修饰的是函数的参数,表示在这个函数体中不能改它所修饰的参数所对应的实际参数的值。 第23行的const修饰的是模板类Queue的成员函数is_empty(),它表示在函数is_empty()的函数体中不能改变任何数据成员的值。 问题4: 答:析构函数中主要是释放链表中存放的各个节点的空间。因为Queue对象在其生存期间可能加入了很多节点,从堆中申请了一些内存空间,这些空间应该随着对象的消亡而释放掉,所以需要在析构函数中来解放这些空间。 问题5: ? 语句号 1 2 3 4 5  对/错 错 对 错 对 对  ? 四、 问题1: 答:输出结果为: class B: 1 class A: haha 问题2: 答:不正确。 问题3:类A的定义如下: class A{ private: static object_count; //…其它成员 public: A(){ object_count++;} ~A(){ object_count—; } static int GetObjectCount(){ return object_count; } //其它函数 virtual void func(int data){cout<<”class A: “<<data<<endl; } void func(char *str){ cout<<”class A: “<<str<<endl; } }; object_count的初始化语句如下: int A::object_count=0; ? 五、 问题1: 答:不能将插入运算符和抽取运算符定义为类的成员函数。 因为这两个运算符对第一个运算数有特殊的要求,即必须分别是ostream和istream类的对象,而不能是用户自己定义的其它类,而类的成员函数默认的第一个参数为指向该类对象的指针类型,所以不符合插入和抽取运算符的要求。 问题2: 重载的运算符的实现如下: SmallInt &SmallInt::operator+=(const SmallInt &si) { SmallInt tmp(val+si.val); val=tmp.val; return *this; } 或 SmallInt &SmallInt::operator+=(const SmallInt &si) { val+=si.val; if(val>127) val-=256; if(val<-128 val=256; return *this; } 中央广播电视大学2000-2001学年度第一学期“开放教育(本科)”期末考试(开) 计科技专业面向对象程序设计试题 2001年1月 一、对错题。判断以下说法的正确性,在下面表格中对应的编号下面写上“对”或“错”。 (20分,每个题目2分) 题号 1 2 3 4 5 6 7 8 9 10  对/错                      1、变量必须先定义或说明,后说明。 2、常量不能作为左值使用。 3、头文件中一般存放着变量和常量的定义、函数的原型以及类的定义。 4、类的友元函数可以直接访问该类的所有成员。 5、派生类的成员函数可以直接访问基类的所有成员。 6、一个类可以作为另一个类的友元类。 7、函数的参数和返回值类型可以是简单数据类型,也可以是指什、引用、数组和类。 8、在基类中被说明为虚函数的类的成员函数必须在每个派生类中说明为虚函数,才能具有多态的特征。 9、下面两个语句是等价的: ??? char str[ ]="hello,world"; ? char str[11]="hello,world"; 10、用new动态申请的内存是在堆中分配的,而不是在栈中分配的。 二、简单编程题。根据程序要求,写出函数的完整定义。(共40分) 1、(本每小题15分)写一个函数,完成在链表末尾增加一个节点的操作。函数的原型为: Node * AddNode(Node * head,int newData); 其中,链表节点的定义如下: ????? struct Node{ ??????? int data:?????????? //存放数据 ??????? Node * next:??????? //指向链表中的下一个节点 ????? }; ?? 函数参数:函数的第一个参数head指向链表的第一个节点,如果链表为空,则head的值为NULL。第二个参数newData为要插入的新节点中存放的数据。 ?? 函数返回值:当成功地插入新的节点进,函数返回指向新节点的指针,否则,如果不能申请到内存空间,则返回NULL。 ???? Node * AddNode(Node * &head,int newData) ???? { ???? //在下面写出函数的实现               2、(本每小题15分)写一个函数,找出给定字符串中具有最大ASCII码的字符。如字符串"world"中字符'w'具有最大的ASCII码。函数的原型为: ??? char MaxCharacter(char * str); 函数参数:指向所要处理的字符串; 函数返回值:如果不空,则返回具有最大ASCII码的字符,否则返回空字符0x0或'\0'。 char MaxCharacter (char * str) {               3、(本每小题10分)用递归函数完成以下运算: sum(n)=1+2+3+…+n 函数的原型如下: int sum(int n); 该函数完成1+2+3+…n的运算,并返回运算结果,其中n>0 提示:你可以使用递归表达式:sun(n)=n+sum(n-1) int sum(int n) {             三、(本小题共30分) valarray是C++的标准模板库中的一个类模板,类模板的每个实例类实现了某个具体的数据类型的数组,如valarray<int>是一个整型的数组类。该类的使用和一般的数组非常类似,可以通过'[ ]运算符来访问数组中的和每个元素。 ? C++的标准模板库中还有一个模板函数abs(),其函数原型为: template<class T> valarray<T>abs(const valarray<T>& x); 该函数的作用是将作为参数的数组? 的每个元素的值取绝对值,并返回得到的新的数组。如原来的数组为: 4???? -1??? -3???? 0?????? -34 将这个数组作为参数传递给函数abs后,函数返回的数组就变成: 4???? 1???? 3????? 34 要求:阅读下列程序,回答后面的问题。 /*********************************************************************/ #include <iostream.h> #include <valarray.h>????? //该头文件中定义了模板类valarray和模板函数abs( ) #define ARRAY_SIZE 10 typedef valarray<int>INTVALARRAY; void main( ) { ? INTVALARRAY val_array(ARRAY_SIZE);?? //定义一长度为ARRAY_SIZE的数组对象 ??????????????????????? //赋初始值 for(int i =0;i<ARRAY_SIZE;i++) ?val_array[i]=-1; cout <<"Size of val_array="<<val_array,size()<<"\n"; cout<<"The values of val_array before calling abs():\n"; for(i=0;i<ARRAY_SIZE;i++) ?? cout<<val_array[i]<<"? "; cout<<"\n"; INTVALARRAY abs_array=abs(val_array); cout<<"The result of val_array after calling abs():\n"; for (i=0;i<ARRAY_SIZE;i++) ? cout<<abs_array[i]<<"? "; cout<<"\n"; } 问题1:(本小题5分)写出程序的输出结果 答:程序的输出为: _____________________________________________________________________________ _____________________________________________________________________________ _____________________________________________________________________________ ____________________________________________________________________________ ____________________________________________________________________________ _____________________________________________________________________________ 问题2:(每答对一个,得2分,共10分) 关于程序中的语句: ???? INTVALARRAY val_array(ARRAY_SIZE); 下列说法哪些是正确的,哪些是错误的?在下表相应的位置写上“对”或“错” 题号 A B C D E  对/错            (A)该语句定义了一个对象val_array,这个对象是类valarray<int>的实例 (B)该语句说明了一个函数原型,函数的名字为val_array,参数为ARRAY_SIZE,函数的返回值类型为INTVALARRAY (C)模板类valarray 一定有一个只带一个参数的构造函数 (D)模板类?valarray一定有一个只带两个参数的构造函数 (E)ARRAY_SIZE将作为参数传递给val_array 的构造函数,初始化val_array 对象 问题3:(本小题共12分)下面是模板函数abs()的实现。这个实现中有错误,指出错误并写出正确的实现。注意:函数头是正确的,不要改变,所有的错误出现在函数体中。 template<class T> valarray<T>abs(const valarray<T>& x) { ?for (int i=0;i<x,size();i++) if(x[i]<0)x[i] * =-1; return x; } 这个函数实现中有以下错误: (1)_____________________________ ________________________________ (2)_____________________________ ________________________________ (3)_____________________________ ________________________________ 正确的函数实现应为: template<class T> valarray<T>abs(const valarray<T>& x) {                                   } 问题4:(本小题3分)从上面的程序中,你可以推断出,valarray模板类中至少重载了哪个或哪些C++的运算符? 答:重载了___________运算符。 四、(本题共10分)下面的程序定义了三个类,Base是图形对象基类,Point表示屏幕上的一个点,ColorPoint表示带颜色的点,基类中利用posx和posy记录图形对象的位置。先阅读三个类的定义,然后回答后面的问题(假定程序中调用的SetPixel()和SetColor()是系统函数库中预定义的函数,可以直接使用)。 /**********************************************************************************/ class Base{ public: ??? Base():posz(0),posy(0){ }; ??? Base(int px,int py);posz(px),posy(py){ }; ??? virtual void draw()=0; protected: ???? int posx,posy;?? //图形对象的位置 }; class Point:public Base{ public: ???? Point(int px,int py):Base(px,py){ } ???? void draw(){? SetPixel(posx,posy); } }; class Colorpoint:public Point{ public; ???? ColorPoint(int px,int py):Point(px,py){color=0;} ???? ColorPoint(int px,int py,int c):Point(px,py),color(c){ } ???? void draw() ??? { ???? SetColor(color); ???? Point::draw(); ?? } protected: ?? int color; }; /**************************************************************************/ 问题1(共6分),每答对1个得1分)下面的主程序使用了上面定义的三个类,程序中定义对象语句哪些是正确的,哪些是错误的? void main() { ? Base b;??????????????????????? //1 ? Point p1;????????????????????? //2 ? Point p2(3,4);???????????????? //3 ? ColorPoint cp1;??????????????? //4 ? ColorPoint cp2(5,6);?????????? //5 ? ColorPoint cp3(7,8,1);???????? //6 答: 行号 1 2 3 4 5 6  对/错              问题2:(2分)将类ColorPoint的两个构造函数合并为一个构造函数,写出该函数的实现(提示:使用函数的默认参数)。 答:合并后的构造函数定义为: _________________________________________ _________________________________________ _________________________________________ _________________________________________ 问题3:(2分)下面的程序段 Base * p; p=new ColorPoint(5,6); p--->draw() 运行后将调用: (A)Base::draw() (B)Point::draw() (C)ColorPoint::draw() (D)::draw() 答:运行后将调用___________________________。 中央广播电视大学2000-2001学年度第一学期“开放教育(本科)期末考试(开) 计科技专业面向对象程序设计试题答案及评分标准(供参考) 2001年1月 总的评分标准: 1)每小题的得分都有语法分和语义分。 2)语法错误不影响语义分的取得,但语义的完全错误可能导致整个程序的不正确,因此当语义完全错误时,语法分也得不到。 3)语法错误指的是一些不影响程序结构和程序意义的小的错误,如: *标识符的误写,如将void写成viod,float写成flaot等 *括号的不匹配,如忘了写'}'或者')'等 *将::写成:,或者将:写成::等 4)语法错误一般每个错误扣0.5分,总共扣分的分数不超过整个题目所规定的语法分。 5)语义错误可能有很多种,要根据具体情况具体分析。可能是: *数据类型选择的错误,如变量或函数的参数或函数的返回值 *标识符不合乎要求,如题中要求是member,而学生写了num等 答案和评分标准: 一、对错题,共20分,每答对一个,给2分 题号 1 2 3 4 5 6 7 8 9 10  对/错 对 对 错 对 错 对 错 错 错 对  二、简单编程题(共40分) 1、答案为: Node * AddNode(Node * &head,int newData) { ?? //申请新的节点空间 Node * newNode=new Node; if (newNode==NULL) ? return NULL; //填充新节点的内容 newNode-->data = newData; newNode-->next = NULL; //插入到链表的结尾 if (head ==NULL) ??? head = newNode; else { //寻找链表的最后一个节点 ??? Node * tail=head; ??? while(tail-->next! =NULL) ???????? tail=tail-->next; ??? //将新节点插入到最后 ??? tail-->next=newNode; ? } ? return newNode; } 评分标准:本小题共15分,其中: (1)申请新的节点空间并填充内容共5分,如果没有申请空间,扣5分,申请空间但没有判断是否为NULL,扣2分,申请空间忘记填充内容扣2分,忘记其中一个内容的填充扣1分; (2)判断当前链是否为空的内容占3分,如果忘记,扣3分,如果判断了是否为空,但程序有错误,扣1分 (3)寻找链表的最后一个节点的程序占4分,如果有错误,视情节轻重扣1-3分 (4)将新节点插入到表尾的语句占2分 (5)返回语句占1分 2、程序可以有多种写法,下面是其中的四种 char MaxCharacter(char * str) { ??? if(str ==NULL) ?????? return 0x0; ????? char maxChar = 0x0; ????? for(int i=0;str[i]!=0x0;i++) ????? { ??????? if (str[i]>maxChar) ?????????? maxChar = str[i]; ?????? } ????? return maxChar; } char MaxCharacter (char * str) { ??? if(str==NULL) ?????? return 0x0; ??? char maxChar=0x0; ??? for(int i=0;i<strlen(str);i++) ??? { ????? if(str[i]>maxChar) ??????? maxChar=str[i]; ??? } ????? if(str[i]>maxChar) ???????? maxChar=str[i]; ??? } ??? return maxChar; } char MaxCharacter(char * str) {? ??? if(str==NULL||str[0]==0x0) ??? return 0x0; ??? char maxChar = str[0]; ??? for(int i=1;str[i]!=0x0;i++) ?? { ?? if(str[i]>maxChar) ??? maxChar = str[i]; ??? } ??? return maxChar; } char MaxCharacter (char * str) { ?? if(str==NULL||str[0]==0x0) ?????? return 0x0; ?? char maxChar = str[0]; ?? int=1; ?? while (str[i]!=0x0) ?? { ???? if(str[i]>maxChar) ??????? maxChar = str[i]; ??????? i++; ??? } ??? return maxChar; } 评分标准:本小题共15分。评分时,只要程序正确就可以,不需要严格和标准答案一样。 具体评分规则: (1)未判断str是否为NULL,扣3分 (2)未给maxChar赋初值,扣2分 (3)循环的起始条件可以有多种。如果maxChar(考生可以取其他的名字)的安初始值设的是str[0],那么循环的开始值为0或者1都可以,如果maxChar的初始值设的是0x0,那么循环的起始值为0。如果起始值不正确,扣2分 (4)循环的结束条件也可以有多种。可以通过取字符串的长度来决定循环次数,也可以通过判断字符是否为0xo来判断是否到了字符串的结尾。如果结束条件不正确,扣2分。 (5)循环变量必须每次循环增1,如果忘记,扣2分 (6)循环体中应比较所记录的maxChar与当前要判断的字符的大小,根据结果做相应的操作。如果循环体逻辑不正确,扣3分 (7)程序应返回所得到的maxChar,如果忘记,扣1分 3、递归函数的实现为: ??? int sum(int n) ??? { ??????? if(n==1) ?????????? return 1; ??????? else ?????????? return n + sum(n-1); ????? } 评分标准:本小题10分,具体评分方式为: (1)判断递归结束条件的语句占5分,如果没有写或者根本不正确,扣5分,如果写了,但有错误,则视情节轻重扣分:如果'n ==1'写成'n =0'或'n=2'等,扣2人,但写成'n<2'或'n<=1'是正确的。如果没有return语句或者返回值不是1,扣2分。 (2)递归调用语句占5分,如果没有return语句,扣2人,如果递归语句逻辑不正确,扣4分,如果有语法错误,则适当扣分 三、综合题(本小题共30分) ??? 问题1:程序的输出结果为: ??? Size of val_array=10 ??? The values of val_array before calling abs(); ??? 0???? -1??? -2???? -3????? -4?????? -5????? -6????? -7????? -8?????? -9 ??? The result of val_array after calling abs(); ??? 0??? 1??? 2?? 3?? 4?? 5?? 6??? 7???? 8??? 9 评分标准:本小题5分,每正确写出一行,给1分 问题2 题号 A B C D E  对/错 对 错 对 错 对  评分标准:本小题10分,每答对一个,给2分 问题3? 答案:该函数实现有以下错误: (1)函数的参数x为const参数,不能在函数体中被改变 (2)在函数中应该创建一个临时对象,这个对象的内容由参数x的内容运算而来 (3)函数返回的应是临时对象,而不是参数 评分标准:本部分4分 (1)答出参数x为const参数的,给2分 (2)答出应该创建临时对象的,给2分 正确的函数实现为: template<class T> valarray<T>abs(const valarray<T>& x) { ????? INTVALARRAY ret_array(x);??? //利用拷贝构造函数构造临时对象 ????? for(int i=0;i<x,size();i++) ???? { ??????????? if(ret_array[i]<0) ??????????????? ret_array[i]*=-1;?? //取绝对值 ???? } return ret_array;?????? //返回临时对象 } 或者 template<class T> valarray<T>abs1(const valarray<T>& x) { ? INTVALARRAY ret_array(x.size());???? //构造一个与X长度相同的对象 ? for(int i=0;i<x.size();i++) ? { ???? if(x[i]<0) ??????? ret_array[i]=x[i]*(-1)???? //取绝对值 ???? else ?????? ret_array[i]=x[i]; ?? } ?? return ret_array;??????????? //返回临时对象 } 评分标准:本部分共8分,具体评分方式为: (1)构造临时对象的语句占3分.没有写扣3分,有错误,视情节轻重扣1-3分. (2)循环语句占4分.有逻辑或语法错误,视情节轻重扣1-4分:如果改变的是参数X的值,扣2分,如果忘记求绝对值,扣2分.有小的语法错误,扣1-2分. (3)返回临时对象的语句占1分,没有写或有错误,扣1分. 问题4.答案:重载了取数组下标的运算符'[]'. 评分标准:本小题3分,多答了其他运算符,扣2分,未答运算符'[]',不给分 四、(本题共10分) 问题1:每答对一个给1分,共6分 行号 1 2 3 4 5 6  对/错 对 错 对 错 对 对  问题2:合并后的构造函数为: ? ColorPoint(int px,int py,int c=0); Point(px,py),color(c){ } 或: ColorPoint(int px,int py,int c=0):Point(px,py) { ?? color=c; } 评分标准:完全正确给2分,小的语法错误扣1人,没有写默认参数不给分 问题3:将调用(C),即ColorPoint::draw() 评分标准: 答对给2分,不对不给分 中央广播电视大学1999-2000学年度第二学期期末考试 面向对象程序设计试题 一.简单问答题(共25分) 1.下列程序是否是一个正确的C++程序?为什么?(5分) void main() {} 回答:________________________________________________________________ ______________________________________________________________________ 2.下面的程序共有17行,程序的每行前面加上了行号。程序中变量num、i 、temp、对象cout和函数func()的 作用域范围分别是什么?在程序的下面用行号来回答。(20分) 1. #include <iostream.h> 2. int num; 3. void func(); 4. void main() 5. { 6. char name[20]; 7. int i; 8. for(i=0; i<20; i++) 9. { 10. char temp; 11. temp=name[i]; 12. cout<<temp; 13. } 14. } 15. void func() 16.{ 17. cout<<”A function!”; 18. } 回答: num 的作用域为从第________行到第_________行。 i 的作用域为从第________行到第_________行。 temp的作用域为从第________行到第_________行。 cout 的作用域为从第________行到第_________行。 func 的作用域为从第________行到第_________行。 3.下面程序的功能为:从键盘读入若干整数,计算并输出所读入数中正整数的平均值,忽略输入数中的负数. 当输入的值为0时,结束输入。 比如从键盘输入以下数: 1 -4 -2 3 4 6 0 则输出内容为: The average of non-negative number is 3.5 仔细阅读程序,填充其中没有完成的部分。注意以下几点: (1) 输入数中的负数被忽略 (2) 输出的平均值不(3) 能省略小数部分 (每个填空4分,共20分) /************计算输入数中的正整数的和,直到读入一个0为止。***** *****************输出这些正整数的平均值************************/ _______A________ void main() { int iValue; //当前输入的整数值 int sum=0; //输入的正整数的和 ______B______; //统计输入的正整数的个数 while(1) { cin>>iValue; if(_________C________) continue; if(iValue==0) ______D______; sum+=iValue; //计算和 num++; } cout<<”\nThe average of non-negative number is”<<______E______; } 在下面写出答案: A________________________ B________________________ C________________________ D________________________ E________________________ 4.下面是一个类Circle的定义,它有一个整型成员变量radius,有一个无参构造函数,还包括存取radius的两 个函数GetRadius()和SetRadius(),程序中已经为Circle定义了大多数成员函数。仔细阅读类的定义,然后完 成后面的四个小题。(每小题5分,共15分) class Circle { public: Circle():radius(5){} void SetRadius(int r) { radius=r; } int GetRadius() { return radius; } private: int radius; //圆的半径 }; (1) 为下面的类增加一个构造函数,该函数有一个参数,并在构造时将该参数值赋给成员radius。将该函数实现为一个非内联函数。 在下面写出在类的定义体中增加构造函数定义的语句: 在下面写出构造函数的实现: (2)为类增加一个成员函数print(),使得可以输出有关圆的信息,比如下列程序 Circle c; c.SetRadius(5); c.Print(); 将输出: The circle has radius of 5! 在下面写出类的定义体中增加的成员函数定义的语句: 在下面写函数的实现: (3) 为类重载插入运算符,使得它完成的工作和上面Print函数类似。例如,下面的程序片段: Circle c; c.SetRadius(5); cout<<c; 将产生输出: The circle has radius of 5! 在下面写出在类的定义体中增加的成员函数定义的语句: 在下面写出函数的实现: 四、找错题。(共20分) 1.下列程序中包含三个错误,找出它们并说明错误原因。(程序的每一行前加上了行号,你可以通过说明行号 来指出错误位置。(12分) 1. class TV 2. { 3. public: 4. void SetStation(int Station) { itsStation=Station; } 5. int GetStation() const { return itsStation; } 6. private: 7. int itsStation; 8. }; 9. 10. void main() 11. { 12. TV myTV; 13. MyTV.itsStation=9; 14. TV.SetStation(10); 15. TV myOtherTV(2); 16. } 错误1为:______________________________________________________ ______________________________________________________ 错误2为:______________________________________________________ ______________________________________________________ 错误3为:______________________________________________________ ______________________________________________________ 2.传递给main函数的参数表argv是一个字符数组,数组的每一个元素是程序的名字。下面的代码从argv[0]中 取出程序的名字,并将它赋给一个字符指针。(4分) #include <iostream.h> #include <string.h> void main(int argc , char * argv[]) { char * program_name; strcpy(program_name,argv[0]); cout<<”Program name:”<<program_name; } 错误为:___________________________________________________________ 改正的方法为(写出一种改正方法): ___________________________________________________________________ ___________________________________________________________________ 3.下列的程序定义了一个交换两个浮点数的函数swap,并在主函数中调用这个函数进行两个浮点数的交换。 (4分) void swap(float &a,float &b); void main()( { float a=1,b=2; swap(&a,&b); } void swap(float &a,float &b) { float temp=a; a=b; b=temp; } 错误为:________________________________________________________ 改正方法为: ________________________________________________________________ ________________________________________________________________ 五、 下面的两个文件完成了类File的定义。文件file.h中定义了File类,文件file.cpp实现了类的一部分成员函数。还有一些成员函数需要由你去完成。仔细阅读所给的程序,按照后面的要求,一步步完善File的定义。(每个填空5分,共20分) /*********************************************************************/ //文件file.h class File{ private: char file_name[64]; //文件名 char * contents; //文件内容 public: File(char * filename); ~File(); //将文件source的内容复制到文件target中 friend bool copy(File & source , File & target); //设置文件内容为new_contents指向的内容 bool set_contents(char * new_contents); }; /**************************************************************/ /**************************************************************/ //文件file.cpp #include <string.h> #include “file.h” //功能:设置文件内容为new_contents指向的内容 //返回值:true:正常设置,返回false:内存空间不够 bool File::set_contents(char * new_contents) { delete[]contents; //释放现有空间 contents=new char[(strlen(new_contents)+1)]; if(contents==NULL) return false; strcpy(contents,new_contents); return true; } //还有一些函数没有实现 /***********************************************************************/ (1) 利用函数set_contents实现copy函数。 (2) 为了保证文件对象在开始生命期时保持正确的状态,应该正确地定义构造函数。在下面补足类File的构造函数的实现。 File::File(char * name) { } (3) 为了保证文件对象退出生命期前正确释放空间,应该正确地定义析构函数。写出类File的析构函数的定义。 (4) 如果想要为类File定义一个派生类Executable,表示可执行文件, 在Executable的成员函数中想直接访问File的成员contents和file_name,应该如何修改类File的定义?(不要写出修改后的类定义,只要说明如何修改) 试题答案 一、 (1) 是正确的C++程序。因为它具有必须的main函数,(2) 并且函数语法正确。 (3) 作用域范围分别为: num 的作用域为从第____2____行到第____18____行。 i 的作用域为从第____7____行到第____14____行。 temp的作用域为从第___10____行到第____13____行。 cout 的作用域为从第____1____行到第____18____行。 func 的作用域为从第____3____行到第____18____行。 二、 答案为: A #include <iostream.h> B int num=0 C iValue<0 D break E 1.0*sum/num 或者(float)sum/num 或者(double)sum/num 三、 (1)在类的定义体中增加构造函数定义的语句: Circle(int rad); 或者: Circle(int); 构造函数的实现: Circle::Circle(int rad):radius(rad) {} 或者: Circle::Circle(int rad) { radius=rad; } (2) 在类的定义体中增加成员函数定义的语句: void Print(); 函数的实现: void Circle::Print() { cout<<”The circle has radius of”<<radius<<”!\n”; } (3)在类的定义体中增加的语句为: friend ostream & operator<<(ostream & os, Circle & c); 函数的实现为: ostream & operator<<(ostream & os, Circle & c) { cout<<”The circle has radius of”<<c.radius<<”!\n”; return os; } 四、 (1) 答案: 1)第13行有错误。itsStation是myTV的私有成员,不能直接访问。 2) 第14行有错误。不能通过类名来访问SetStation函数,必须通过对象来访问。 3) 第15行有错误。类TV没有定义具有一个参数的构造函数,只有系统提供的默认构造函数,所以不能这样构造函数。 (2)答案 错误为:program_name是一个字符指针,还没有指向佥的空间,不能直接赋值。 改正的方法为:将program_name定义为字符数组 或者:先从堆中为program_name申请需要的字符空间,然后再使用。 (3)错误为:main函数中调用swap函数时,参数传递的方式不对 改正的方式为:将调用swap(&a,&b)改为swap(a,b) 五、 (1)copy函数的实现为: bool copy(File & source,File & target) { return target.set_contents(source.contents); } 或者: bool copy(File & source,File & target) { bool result=target.set_contents(source.contents); return result; } (2)在构造函数体中增加下面语句: strcpy(file_name,name); contents=NULL; (3)析构函数的定义为: File::~File() { delete[] contents; } 中央广播电视大学1999-2000学年度第一学期期末考试 面向对象程序设计试题 ? 1.(本题共20分) 下面列出了由三个文件main.cpp、MyClass.h和MyClass.cpp组成的一个程序。文件main.cpp中实现了主函数;文件MyClass.h中定义了类MyClass;文件MyClass.cpp中实现了类MyClass的成员函数。题中没有给出三个文件的完整实现。仔细阅读所给的程序,根据题意补充文件MyClass.h和文件MyClass.cpp的内容。要求: a.将成员变量定义为私有的; b.不要增加题中没有用到的类成员。 /***********************************************************************/ //文件main.cpp #include <iostream.h> #include "MyClass.h" void main() { MyClass obj(3.3); cout << obj.GetMember() << endl; obj.SetMember(5.6); cout << obj.GetMember() << endl; } /***********************************************************************/ /***********************************************************************/ //文件 MyClass.cpp #include "MyClass.h" float MyClass::GetMember() { return member; } void MyClass::SetMember(float member) { MyClass::member=member; } //在这里写出构造函数的实现函数 /***********************************************************************/ /***********************************************************************/ //文件 MyClass.h //类MyClass的定义 class MyClass { //在下面写出类的定义体 }; /***********************************************************************/ 2.写出能被编译、连接和运行的最小的C++程序。(5分) 三、根据下面的要求一步步写出正确的C++语句,注意:各个步骤之间是有先后顺序的。(每小题2分,共20分) 1.定义两个整型变量 value1,value2; 2.定义一个指向整型变量的指针pValue,将该指针初始化为指向value1; 3.将指针pValue改为指向变量value2; 4.通过pValue指针来间接地改变变量value2的值为20; 5.申请三个连续的整数空间,并将申请到空间的首地址赋值给pValue; 6.用cout输出所申请到的首地址值; 7.给第二个地址空间赋值10; 8.用cout输出第二个地址空间的地址; 9.释放所申请到的三个整数空间; 10.将指针pValue设置为不指向任何地址空间; 四、改错题。指出下面每段程序中有什么错误,并提出改正方法。(每小题5分,共15分) 1.下面的程序为一个指针所指空间赋值,并输出指针所指空间的值。 #include <iostream.h> int main() { int * pInt; *pInt = 9; cout << “The value at pInt:”<<*pInt ; return 0; } 错误为:______________________________________________________ 改正方法为:__________________________________________________ ______________________________________________________________ 2.下列程序判断两个数是否相等,如果相等,则输出”Equal”,否则输出”Not Equal”。 #include <iostream.h> void main() { int a=3,b=2; if(a=b) cout<<”Equal\n”; else cout<<”Not Equal\n”; } 错误为:______________________________________________________ 改正方法为:__________________________________________________ ______________________________________________________________ 3.下列程序片段对二维数组的每个元素赋值 unsigned short SomeArray[5][4]; for(int i=0;i<=5;i++) for(int j=0; j<=4; j++) SomeArray[i][j]=i+j; 错误为:_______________________________________________________ 改正方法为:_______________________________________________________ ___________________________________________________________ 五、 (每个填空5分,共25分) 下面一段程序从给定的数组a中找出值最大的元素,然后输出该元素的数组下标idx、内存地址maxaddr以及元素值本身。函数findmax负责在给定的数组中查找最大值,并返回最大值所在的内存地址,函数有三个参数:array是所要处理的数组;size是数组的大小;index负责从函数返回具有最大值的元素在数组中的数组下标。要求你填充A、B、C、D、E,使其成为一个合乎要求的完整程序,答案写在程序后面的指定处。 //程序开始 #include <iostream.h> int *findmax(int *array, int size, int &index); void main() { /****** 变量定义部分 ***********/ int a[10] = {34, 34, 23, 89, 1, 2, 13, 42, 5, 54}; A ; int idx; /*******寻找最大值 ************/ maxaddr = findmax(a, sizeof(a)/sizeof(int), idx); /*******输出最大值的有关信息 ************/ cout << "Max value index: " << idx << endl << "Max value address: " << maxaddr << endl << "Max value: " << B << endl; } /******* 函数findmax的定义部分 ************/ int *findmax(int *array, int size, int &index) { int max = 0; //max是当前具有最大值的数组元素下标值 for(int i = 1; C ; i++) { if (array[i] > D ) max = i; } E ; return array + max; //返回最大值所在内存地址 } 在下面写出答案: A ______________________ B ______________________ C ______________________ D ______________________ E ______________________ 六、阅读下列程序,回答后面提出的问题。(每小题5分,共15分) #include <iostream.h> class vehicle { int wheels; float weight; public: void message(void) {cout << “Vehicle message\n”; } }; class car : public vehicle { int passenger_load; public: void message(void) {cout << “Car message\n”;} }; class truck : public vehicle { int passenger_load; float payload; public: int passengers(void) {return passenger_load;} }; class boat : public vehicle { int passenger_load; public: int passengers(void) { return passenger_load; } void message(void) {cout << “Boat message\n”;} }; int main() { vehicle *unicycle; unicycle = new vehicle; unicycle ->message(); delete unicycle; unicycle = new car; unicycle ->message(); delete unicycle ; unicycle = new truck; unicycle ->message(); delete unicycle ; unicycle = new boat; unicycle ->message(); delete unicycle ; return 0; } (1) 写出程序的运行结果。 (2)如果将vehicle的成员函数message的定义改为: virtual void message(void) { cout << “Vehicle message \n”;} 写出修改后的程序的运行结果。 (3) 在上一题修改的基础上,(4) 修改类truck的定义,使它具有和car、boat等具有相似的特征。也就是说,(5) 下面的程序片段: unicycle = new truck; unicycle ->message(); delete unicycle ; 将会产生以下输出: Truck message 写出为truck增加的成员函数的定义并将其实现为一个内联函数。 试题答案 一、 (1)构造函数的实现: MyClass::MyClass(float iniVal) { member = iniVal; } 或: MyClass::MyClss(float iniVal): member(iniVal) { } (2)类的定义体: private: float member; public: MyClass(float iniVal); float GetMember(); void SetMember(foat member); 二、 答案为: void main() {} 三、 1) int value1,value2 或者: int value1; int value2; 2) int *pValue = &value1; 3) pValue = &value2; 4) *pValue = 20; 5) pValue = new int[3]; 6) cout << pvalue; 或者: cout << &pValue[0]; 7) pValue[1] = 10; 或者 *(pValue + 1) = 10 8) cout << pValue + 1; 或者 cout << &pValue [1]; 9) delete [] pValue; 10) pValue = NULL; 四、 (1) 错误为:指针pInt没有指向合法的空间,就被用来赋值 改正的方法为:用new为pInt申请合法的空间,并在程序结束之前释放该空间。 或者:定义一个整型变量,让pInt指向该合法变量。 (2) 错误为:循环变量i和j的范围超过了数组下标允许的范围。 改正的方法为:将for循环的循环条件分别改为:i<5和j<4。 (3) 错误为:判断a和b是否相等的条件表达式写成了赋值表达式。 改正的方法为:将if(a=b)改为if(a==b) 五、 A int *maxaddr B a[idx] C i < size D array[max] E index = max 六、 (1)程序的输出为: Vehicle message Vehicle message Vehicle message Vehicle message (2)程序的输出为: Vehicle message Car message Vehicle message Boat message (3)在类truck中增加以下语句: void message(void) {cout << "Truck message\n";}