雷电老师的上机实验答案(部分)。
以下文字中,红色为应填入的答案,绿色为代码的注释,蓝色为老师没有讲过的知识补充,紫色为我不确定的题目☆第二章从C到C++1. 以下说法正确的有A. 面向对象程序设计的基本特征是封装、继承、多态B. 名字空间的作用是提供逻辑分类和防止名字冲突2. 代码填空#include <iostream>using namespace std;//这是因为std涵盖了标准C++的定义和声明,可以把std 想象成一个很大的名字空间名,cin、cout都是其内部定义的函数namespace myLib //此处定义了名叫“myLib”的名字空间{int maxV(int& a,int& b){return a>b?a:b;}} //此空间里面的所有函数的全名为:myLib::maxV int main( ){int x,y;cin >>x>>y;//因为题目要求要输入两个函数,所以我们采取依次输入的方法cout <<myLib::maxV( x,y ); //输出maxV函数值,名字空间里面定义过的函数,全名为:“名字空间名::函数名”return 0;}输入 1 2 输出 2 //maxV函数的意思是取两个参数中较大的一个△这里说一下typedef的两条用法,下面的题目要用到:用途一:定义一种类型的别名,而不只是简单的宏替换。
可以用作同时声明指针型的多个对象。
比如:char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,// 和一个字符变量;以下则可行:typedef char* PCHAR; // 一般用大写PCHAR pa, pb; // 可行,同时声明了两个指向字符变量的指针虽然:char *pa, *pb;也可行,但相对来说没有用typedef的形式直观,尤其在需要大量指针的地方,typedef的方式更省事。
用途二:用在旧的C代码中(具体多旧没有查),帮助struct。
以前的代码中,声明struct新对象时,必须要带上struct,即形式为: struct 结构名对象名,如:struct tagPOINT1{int x;int y;};struct tagPOINT1 p1;而在C++中,则可以直接写:结构名对象名,即:tagPOINT1 p1;估计某人觉得经常多写一个struct太麻烦了,于是就发明了:typedef struct tagPOINT{int x;int y;}POINT;POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。
3. 有函数typedef char* LPTSTR; //此处规定了LPTSTR的类型是一个字符型的指针,这里为typedef的用途一int GetSystemDirectory( LPTSTR lpBuffer, int uSize);//函数中的两个参数类型,第一个为字符型的指针,第二个为整型正确的调用代码是(多选)A. char dir[200]; GetSystemDirectory( dir, 200 );//dir[200]表示一个数组,dir也可以理解为该数组第一个成员的地址(类似于指针)B. char *pdir=new char[200]; GetSystemDirectory( pdir, 200 );//前半句定义了一个字符型的指针pdir并且动态创建了一个长度为200的字符型数组,所以可以满足后半句中函数参数的要求C. char *dir; GetSystemDirectory( dir, 200 );//前半句定义了一个字符型的指针dir,但是为什么不选这项我也不清楚,我要问问老师D. string dir; GetSystemDirectory( dir, 200 );//dir的类型是一个字符串型的,不满足函数参数的要求E. LPTSTR lpBuffer; GetSystemDirectory( dir, 200 );//dir不知道从何而来,前半句定义lpBuffer为一个LPTSTR(字符类型的指针,为什么?看这道题的第一个注释)类型,并没有提到dir4. 有函数typedef struct _SYSTEMTIME {WORD wYear;WORD wMonth;WORD wDayOfWeek;WORD wDay;WORD wHour;WORD wMinute;WORD wSecond;WORD wMilliseconds;} SYSTEMTIME, *LPSYSTEMTIME; //此处用到了typedef的用途一:SYSTEMTIME和*LPSYSTEMTIME两者等价,类型都为结构体_SYSTEMTIME,只是SYSTEMTIME定义的变量为结构体_SYSTEMTIMELE类型,而LPSYSTEMTIME定义的变量的指针为结构体_SYSTEMTIME类型void GetSystemTime( LPSYSTEMTIME lpSystemTime );//此处要求lpSystemTime为结构体_SYSTEMTIME的指针正确的调用代码是(多选)A. LPSYSTEMTIME time; GetSystemTime( time );//用LPSYSTEMTIME定义变量的形式为LPSYSTEMTIME * time,所以题目中time不是一个指针类型B. SYSTEMTIME *ptime; GetSystemTime( ptime);C. SYSTEMTIME time; GetSystemTime( &time );D. SYSTEMTIME *ptime=new SYSTEMTIME; GetSystemTime( ptime);5.根据下面的调用char str[200]; bool ok = getstr( str,200); //①我们观察getstr 函数里面的两个参数:str是一个大小为200的数组的数组名,同时也是指向这个数组第一个元素的指针名(基地址);200为这个数组的元素个数,也同时是这个数组表示的存储空间里面基地址的偏移量②可以观察到ok的类型是bool型,所以函数getstr也应为bool型写出其函数原型(多选)A. void getstr( char str,int size );//不符合②B. bool getstr( char str[],int size );C. bool getstr( char *p,int len );D. ok=getstr( str,200 );//函数原型应包括函数得到类型6.下面哪条代码是错误的?A. string s; s="i love C++"; cout<<s<<'\n'; //p32 2.5.4 读写stringB. string s1="i love c++"; char s2[30]; s2=s1; cout<<s2<<'\n';//p33的2.5.5,明确说明了赋值时,左边必须是一个string类型得到字符串,右边可以是一个string类型的字符串,也可以是一个C风格的字符串或仅仅是一个char字符C. string s; s="i love "; s+="C++"; cout<<s<<'\n';//p34 2.5.6 字符串的连接D. string s="i love you",t; t=s+"!"; cout<<t<<'\n';//同上7.如下代码的输出是 p.x=4 p.y=-11 //注意cout输出内容的格式,不要忘记“p.x=”,“p.y=”#include <iostream>using namespace std;struct point{ int x,y;};void move (point& q){ q.x--;q.y++;}int main(){point p;p.x=5;p.y=-12;move(p);cout<<"p.x="<<p.x<<'\n';cout<<"p.y="<<p.y<<'\n';return 0;}8.如下代码的输出是 *p.x=4 *p.y=-11#include<iostream>using namespace std;struct point{int *x,*y;};void move (point& q){--*q.x; //此处是将q.x所指向的内容自减1++*q.y; //此处是将q.y所指向的内容自增1}int main(){point p;int a=5,b=-12;p.x=&a; //此处,令a的地址为p.xp.y=&b; //此处,令b的地址为p.ymove(p);cout<<"*p.x="<<*p.x<<'\n';cout<<"*p.y="<<*p.y<<'\n';return 0;}9.写一段代码double * db_ptr = new double;分配一个类型为double的存储空间,并将它的地址赋给变量db_ptr//此题代码也可为: double * db_ptr;db_ptr = new double;10.下面代码输出为 5 ,有一行错误修改为:int & ai(int i){int j=1;改为static int j=1;//因为代码定义了一个引用返回类型,j和b直接关联在一起,没改之前,当return j时,存储j的空间已经收回,所以要把j改为静态(全局)变量j += i;return j;}int main(){int& b=ai( 1 );b++;b = ai( 2 );cout<<b;}11.下面代码填空//此题主要是考枚举的概念,p28 2.4.4#include<iostream>using namespace std;enum {MinSize=0,MaxSize=1000};enum Color{red=0xff0000,green=0xff00,blue=0xff};void draw( Color color){if(color==red)cout<<"红"<<endl;else if(color==green)cout<<"绿"<<endl;else if(color==blue)cout<<"蓝"<<endl;}int main(int argc, char* argv[]){int a[MaxSize];for(int i=0;i<MaxSize;i++){a[i]=i;}Color color= red;draw(color);return 0;}12.下面代码的输出er:越界! 0 1 2 //此题考察例外处理,p53 2.8 const int MaxSize=3;int curr=0;int A[MaxSize];void append(int x){if( curr<MaxSize)A[curr++] = x;elsethrow "er:越界!";}int main(int argc, char* argv[]){int i;try{for(i=0;i<5;i++)append(i);}catch(char *e){cout<<e<<endl;}for(int j=0;j<i;j++)cout<<A[j]<<" ";cout<<endl;return 0;}☆第三章类类(1)设计并实现类(P127 3-7)1. 填空class Profession{string name;string title;double avgIncom;public:Profession(){} //构造函数Profession(string name){ this->name=name;} //构造函数~Profession(){} //析构函数int CompareIncome( Profession &profes){if( this->avgIncom < profes.getavgIncom()) return -1;else if(this->avgIncom == profes.getavgIncom() )return 0;//根据main函数最后输出结果的形式得出,特别注意C++的等于用“==”表示else return 1;}static int CompareIncome( Profession &profes1,Profession&profes2){if(profes1.getavgIncom()< profes2.getavgIncom() ) return -1;else if( profes1.getavgIncom()> profes2.getavgIncom()) return 1;else return 0;}string getname(){return name;}//name是字符串类型string gettitle(){return title;}double getavgIncom(){return avgIncom;}//avgIncom是double型void setname( string name ) { this->name=name;}//表示Profession类里面定义的name被setname的参数赋值void settitle( string title ) { this->title=title;}void setavgIncom( double avgIncom ) { this->avgIncom=avgIncom;}};int main( ){Profession prof[2];for(int i=0;i<2;i++){string name;string title;double avgIncom;cin>>name>>title>>avgIncom;prof[i].setname(name);//在循环中对两个prof都进行setname操作,但是要它们自己调用自己的成员函数setnameprof[i].settitle(title);prof[i].setavgIncom(avgIncom);}for(i=0;i<2;i++){cout<<prof[i].getname()<<"\t"<<prof[i].gettitle()<<"\t"<<prof[i].getavgIncom()<<"\t"<<endl;//两个prof分别调用各自的成员函数getname}int comp= Profession::CompareIncome( prof[0],prof[1] );//用到Profession类里面的函数,调用方法就为以上形式cout<<prof[0].getname()<<"avgIncom 比"<< prof[1].getname();if( comp < 0 )cout<<"少"<<endl;else if( comp > 0 )cout<<"多"<<endl;elsecout<<"相同"<<endl;return 0;}2. 改写settitle成员函数为外式实现void Profession::settitle( string title ) { this->title=title;}//因为是外联式实现(写在类外面),所以要用到“::”域解析操作符3. 改写析构函数为外联式实现Profession::~Profession(){}//同理4. 考察main()函数中的调用代码:prof[i].settitle(title);设对象prof[0]的地址0x11234567,对象prof[1]的地址0x21234567那么运行分别进入成员setname函数体中,this值分别是0x11234567、0x21234567//p119 最右边有■的一句话:this指向对象c1,即this的值为&c1类(2)以下是第3章类教材中的练习1. 78页 3.1.8-2 Airplane airplane; (注:对象名airplane) Airplane airplanes[5]; (注:5个对象的数组,名airplanes)2. 79页3.1.8-5 //与struct区别开来,struct成员都是公有的A.私有B.公有3. 79页 3.1.8-9 改为//此题牵涉到成员函数外联实现的表现形式A. private: unsigned getHeadCount() const;B. unsigned Circus::getHeadCount() const { ... }C. Circus:: unsigned getHeadCount() const { ... }D. unsigned Circus::getHeadCount() { ... }4. 82页 3.2.7-2 getTop其声明及内联式的实现(注:不考虑栈可能是空的情况)int getTop() {return arr[top];}//所写代码只要满足要求即可5. 85页 3.3.5-5 错的地方修改为A. void setAux(string& s){ dm=s;}B. void setAux(const string& s) const { dm=s;}C. void set(string& s)const{ setAux( s ); }D. void set(const string& s) { setAux( s ); } //修改之前set 函数使用const标记的,而setAux是非const类型,所以这种调用是错误的,具体陈述请见p84 最后一段6. 105页 3.5.12-2 错的地方修改为Z();//构造函数没有函数类型7. 106页 3.5.12-7 错的地方修改为public: //构造函数需要被调用,所以必须为公有成员函数8. 106页 3.5.12-9 错的地方修改为R(const R&arg); (注:参量要使用const 修饰) //拷贝构造函数的定义,p95 3.5.49. 106页 3.5.12-13 输出 1 -999 //这道题要说明什么我也不清楚10. 107页 3.5.12-19 错的地方修改为A. public: void C( int a ) { c = a; }B. const int c = 0;C. public: const int c;D. public: C( int a ) c(a) { }//此题表示的是,当要对const类型的对象赋值时,不能直接在函数内部赋值,需要用到构造函数的初始化段11. 108页 3.5.12-22 错的地方修改为~A(); //析构函数没有函数类型12. 117页 3.7.4-3 补上所缺的代码int C::x=0; (注:设初值为0)//因为x为static类型,属于全局变量,所以可以在类的外面对x赋值,但要用到“::”域解析操作符13. 117页 3.7.4-4 错误地方修改为A. ++this->xB. this->++xC. s函数内不能访问xD.public: int x;//static函数不能访问非static内容,具体陈述见p155 中间一段14. 117页 3.7.4-5 输出 1 2 3 //s为static类型,属于全局变量15. 120页 3.8.2-1 错的地方修改为A.void g( C& c1);B.g(c1);C.p->m();D.c1.g(&c1);//必须用这种形式,p118 例3-42以下是自编练习:16. 设有 class CC { public: CC( int x ){} };以下创建对象的方法正确的有(多选)A. CC c(1);B. CC *pc=new CC(1);C. CC cs[2]={C(1),C(2)};D. CC c;E. CC cs[2]={1,2};F. CC c1(1); CC c2(c1);//因为构造函数带有参数,所以创建对象时,必须要带参数创建,所以只有D没有带参数,故选ABCEF17. 设有 class CC{ public: void m(); static void sm(); int a; static int s;}以下正确的有(多选)A. CC c; c.m(); c.sm();B. CC c; CC::m(); c.sm();C. CC c; c.m(); CC::sm();D. CC c; CC::m(); CC::sm();E. int CC::s=0;F. void CC::sm(){ s=9;}G. void CC::m(){ this->s=9;}H. void CC::sm(){ this->a=9;}//见p115 例3-39 后面有一个表格,说明了当成员函数是static类型时,可以用C::sm()调用,也可以用c.sm()调用;当成员函数非static类型时,只能用c.m()调用。