全国计算机等级考试二级C++上机指导

更新时间:2023-07-21 13:55:01 阅读量: 实用文档 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

1.二级

2.C++上机操作主要是要求考生能够阅读和分析C++程序,能够采用面向对象的方法编写程序,能熟练使用Visual C++ 6.0集成开发环境编写和调试程序。

3.上机90分钟,满分100分,共有3种类型的考题:基本操作题、简单应用题、综合应用题。

4.基本操作题主要以改作题的形式出现,其出题范围主要是C++中有关类与对象的操作,如考核对象的定义、对象成员的访问方式等;简单应用题主要是考察考生编写应用程序的能力,如题目要求的功能实现某个函数的定义,或考核某种算法的C++实现等;综合应用题的出题范围主要集中在类和对象以及类的继承与派生这些知识点上。出题形式通常是要求考生按照题目要求将程序补充完整,并调试程序使之输出正确的结果。

例1 使用VC6打开考生文件夹下的工程proj1,此工程包含一个源程序文件main.cpp,但该程序运行有问题,请改正main函数中的错误。

源程序文件main.cpp清单如下:

#include

class MyClass

{public:

MyClass(int m)

{

member=m;

}

~MyClass(){}

int GetMember()

{

return member;

}

private:

int member;

};

MyClass Makeobject(int m)

{

MyClass *pMyClass=new MyClass(m);

return *pMyClass;

}

int main()

{

int x=7;

/*********found**********/

MyClass *myobj=Makeobject(x);

/*********found**********/

cout< <″My object has member″< <&NBSP;

return 0;

分析: 本题考核对象指针的应用,属于改错题。

程序中出现了2个出错标识符,说明此程序有2处错误。

第1处错误:MyClass*myobj=Makeobject(x);,myobj是对象指针,而函数Makeobject的返回值是类MyClass的对象,所以应改为:MyClass*my0bj=&Make0bject(x);。

第2处错误是:cout< <″My object has member″< <&NBSP;成员名;和(*对象指针名).成员名;,显然上述语句的对象指针的使用方式是错误的。

答案: 应改为:cout< <″My object has member″< GetMember()< <&NBSP; < <(*myobj).GetMember()<

例2 请编写一个函数int find(char s[],char t[]),该函数在字符串s中查找字符串t,如果找到,则返回字符串t在字符串s中的位置(整数值):否则返回-1。注意:用数组方式及两重循环来实现该函数。

注意:部分源程序已存在文件PROC2.cpp中。

请勿修改主函数main和其他函数中的任何内容,仅在函数find的花括号中填写若干语句。 文件PROC2.cpp的内容如下:

#include

int find(char s[],char t[] );

const int MAXLINE=256;

int main()

{

char source[MAXLINE],target[MAXLINE];

cout< <″please input a string for searching:\n″;

cin.getline(source,[MAXLINE]);

cout< <″please input a string you want to find:\n″;

cin.getline(target,MAXLINE);

int intpos=find(source,target);

if(intpos>=0)

cout< <″Finding it,The target string is at index ″

< <&NBSP;

else

cout< <″Not finding it \n″;

return 0;

}

int find(char s[],char t[])

{

}

分析: 本题是一道简单应用题。

函数int find(char s[],char t[])的功能是在字符串s中查找字符串t,如果找到,则返回字符串t在字符串s中的位置(整数值);否则返回-1。而且用数组方式及两重循环来实现该函数。 答案:

int find(char s[],char t[])

{

int i=0,j=0;

for( i=0;s[i]!=′\0′;i+ +)

{

if(t[0]= =s[i])

{

while(t[j]!=′\0′&&s[i+j]!=′\0′)

{

j+ +;

if(t[j]!=s[i+j])

break;

}

}

if(t[j]= =′\0′)

return i;

}

return -1;

}

例3 请编写一个函数void fun(int aa[],int n,int x),其中n表示数组aa中元素的个数,函数的功能是:计算前x为的和并放在aa[x]中,aa数组中的元素值和x的值由主函数通过键盘读入。 部分源程序如下:

#include

#define MAX 100

void main()

{

void fun(int aa[],int n,int x);

int bb[MAX],i,x,n;

cout< <″please enter the counter of the number:\n″;

cin> >n;

cout< <″please enter the number:\n″;

for(i=0;i

cin> >bb[i];

cout< <″Input the x:\n″;

cin> >x;

fun(bb,n,x);

cout< <″The data after total:″< <&NBSP;

}

void fun(int aa[],int n,int x)

{

}

分析: 本题是一道简单应用题。

根据题意分析可得:本题要求考生统计一个数组中前x项的和。本题主要考查考生对数组作为形参的应用能力。

答案: 计算数组aa[]中前x项的和可以用循环语句for来实现。程序如下:

void fun(int aa[],int n,int x)

{

int i=0,sum=0;

for(i=0;i

sum=sum+aa[i];

aa[x]=sum;

}

例4 编写一个函数,用该函数可以统计一个长度为3的字符串在另一个字符串中出现的次数。例如,假定输入字符中“the abcthe they have theren”,子字符串为“the”,则应输出4。 注意:部分源程序在文件PRDE1.CPP中。

请勿改动主函数main和其他函数中的任何内容,仅在fun的花括号中填入编写的若干语句。 部分源程序如下:

#include

#define MAX 100

int fun(char *str,char *substr);

int main()

{

char str[MAX],substr[4];

int n;

cout< <″please Input the source string\n″;

cin> >str;

cout< <″please Input the substring\n″;

cin> >substr;

n=fun(str,substr);

cout< <″The counter is:″< <&NBSP;

return 0;

}

int fun(char *str,char *substr)

{

//

}

分析: 本题是一道简单应用题。

(1)本题主要考核考生对字符串指针或字符串数组的应用能力。函数fun的形参为两个字符串的首地址。

(2)函数fun的功能是统计一个长度为3的字符串在另一个字符串中出现的次数。

(3)此函数可用一个循环体和if语句来实现,依次判断字符串substr中的值,找到第一个字符时,设一个计数器k,将k+1赋给k,如果substr中下一个元素是str中的第2个元素则将k自增,如果有连续3个字符与str中相同则将计数器n自增。

答案: 实现此函数功能的方式有多种,下面给出其中一种答案。

int fun(char *str,char *substr)

{

int n,z;

n=0;

for(z=0;str[z]!=′\0′;z+ +)

{

if((str[z]= =substr[0]&&(str[z+1]= =substr[1])&&(str[z+2]= =substr[2])) nm+ +;

}

return (n);

}

例5 使用VC6打开考生文件夹下的工程proj1,此工程包含一个源程序文件main.cpp,但该程序运行有问题,请改正main函数中的错误,使程序的输出结果是:

member=0

member=5

member=10

源程序文件main.cpp清单如下:

#include

class MyClass

{

public:

MyClass(int i)

{

member=i;

}

void SetMember(int m)

{

member=m;

}

int GetMember()const

{

return member;

}

void print() const

{

cout< <″member=< <&NBSP;

}

private:

int member;

};

void main()

{

/*********found**********/

MyClass obj1;

obj1.print();

MyClass obj2(3);

/*********found**********/

obj1.member=5;

/*********found**********/

MyClass.SetMember(10);

obj1.print();

obj2.print();

}

分析: 本题主要考核类与对象的应用。

程序中出现了3个出错标识符,说明此程序有3处错误。

第1处错误:MyClass obj1;obj1.Print();,此时对象obj1没有给出初始化值,所以应该改为MyClass obj1(0);obj1.print();。

第2处错误:obj1.member=5;,由于类MyClass中,数据成员member是私有成员不能通过类的对象obj1访问。所以应该改为:obj1.SetMember(5);。

第3处错误:MyClass.SteMember(10);,此处MyClass是一个类名,这样的访问方式不合法,应该改为:obj2.SteMember(10);。

答案: 修改后的main()函数应该为:

void main()

{

MyClass obj1(0);

obj1.print();

MyClass obj2(3);

obj1.SetMember(5);

obj2.SetMember(10);

obj1.print();

obj2.print();

}

例6 使用VC6打开考生文件夹下的工程proj3。此工程包含一个源程序文件main.cpp,其中定义的类并不完整,按要求完成下列操作,将类的定义补充完整。

(1)定义类Planet的保护数据成员distance和revolve,它们分别表示行星距太阳的距离和行星

的公转周期。其中,distance为double型,revolve为int型。请在注释“//**1**”之后添加适当的语句。

(2)定义类Earth的构造函数Earth(double d,int r),并在其中计算地球绕态阳公转的轨道周长。假定:circumference=2*d*3.1416。请在注释“//**2**”之后添加适当的语句。

(3)定义类Earth的成员show(),用于显示所有信息。包含地球距太阳的距离,地球的公转周期,以及地球绕太阳公转的轨道周长。请在注释“//**3**”之后添加适当的语句。

源程序如下:

#include

class planet

{

protected:

//**1**

public:

planet(double d,int r)

{

distance=d;

revolve=r;

}

};

class Earth:public planet

{

double circumference;

public:

//**2**

//**3**

};

void main()

{

Earth obj(9300000,365);

obj.show;

}

答案: (1)第1处是完成类Planet的保护数据成员distance和revolve的定义,根据题意可填入:double distance;int revolve;。

(2)第2处是定义类Earth的构造函数Earth(double d,int r),并在其中计算地球绕太阳公转的轨道周长。由此可填入:

Earth(double d,int r):planet(d,r){ circumference=2*d*3.1416;}。

(3)第3处是定义类Earth的成员show(),用于显示所有信息。根据要求可填入:void show(){ cout< <&NBSP;<&NBSP; <&NBSP;<&NBSP; <&NBSP;

例7 使用VC6打开考生文件夹下的工程proj3。此工程包含一个源程序文件main.cpp,此程

序的运行结果为:

Derivel′s print() called.

Derive2′s print() called.

其中定义的类并不完整,按要求完成下列操作,将类的定义补充完整。

(1)定义函数print()为无值型纯虚函数。请在注释“//**1**”之后添加适当的语句。

(2)建立类Derive1的构造函数,请在注释“//**2**”之后添加适当的语句。

(3)完成类Derive2成员函数Print()的定义。请在注释“//**3**”之后添加适当的语句。

(4)定义类Derive1的对象指针d1,类Derive2的对象指针d2。其初始化值分别为1和2。 #include

class Base

{

public:

Base(int i){b=i;}

//**1**

protected:

int b;

};

class Derivel : public Base

{

public:

//**2**

void print()

{

cout< <″Derivel′s print() called.″<

}

};

class Derive2 : public Base

{

public:

Derive2(int i):Base(i){}

//**3**

};

void fun(Base *obj)

{

obj->print();

}

void main()

//**4**

fun(d1);

fun(d2);

}

答案: 本题是一道综合应用题,考核继承与派生,以及纯虚函数。

(1)在第1处定义函数print()为无值型纯虚函数。所以应填入:virtual void print()=0;。

(2)在第2处建立类Derive1的构造函数,所以应填入:Derivel(int i):Base(i){}。

(3)在第3处完成类Derive2成员函数print()的定义,根据程序的输出可知,此处应填入:void print(){cout< <″Derive2′s Print() called.″<

(4)在第4处定义类Derive1的对象指针d1,类Derive2的对象指针d2,其初始化值分别为1和2。所以应填入:Derive1 *d=new Derive1(1);Derive2 *d2=new Derive2(2)。

例8 使用VC6打开考生文件夹下的工程proj3。此工程包含一个源程序文件main.cpp,其中定义了用于表示日期的类Date,但类Date的定义并不完整。请按要求完成下列操作,将类Date的定义补充完成:

(1)定义私有数据成员year、month和day分别用于表示年、月、日,它们都是int型的数据。请在注释:“//**1**”之后添加适当的语句。

(2)完成默认构造函数Date的定义,使Date对象的默认值为:year=1,month=1,day=1,请在注释“//**2**”之后添加适当的语句。

(3)完成重载构造函数Date(int y,int m,int d)的定义,把数据成员year、month和day分别初始化为参数y、m和d的值,请在注释“//**3**”之后添加适当的语句。

(4)完成成员函数print的类外定义,使其以“年-月-日”的格式将Date对象的值输出到屏幕上。请在注释“//**4**”之后添加适当的语句。

注意:除在指定位置添加语句之外,请不要改动程序中的其他内容。

源程序文件main.cpp清单如下:

//main.cpp

#include

class Date

{

public:

//**2**

Date(int y,int m,int d)

{

//**3**

}

void print() const;

private:

//data member

//**1**

};

void Date::print() const

{

//**4**

}

{

Date national—day(1949,10,1);

national—day.print();

return 0;

}

答案: 本题是综合应用题。

(1)定义私有数据成员year、month和day分别用于表示年、月、日,它们都是int型的数据。所以在1处填入:int year,month,day;

(2)完成默认构造函数Date的定义,使Date对象的默认值为:year=1,month=1,day=1。根据以上要求可知类Date的默认构造函数(2处)为:Date(){year=1;month=1;day=1}。

(3)完成重载构造函数Date(int y,int m,int d)的定义,把数据成员year、month和day分别初始化为参数y、m和d的值。其实也就是给私有成员year、month和day赋值。所以在3处应填入:year=y;month=m;day=d;

(4)完成成员函数print的类外定义,使其以“年-月-日”的格式将Date对象的值输出到屏幕上。函数print的功能是输出Date对象的值,此处主要考核C+ +的格式化输出。所以在4处应该填入:cout< <&NBSP; <&NBSP; <&NBSP; <&NBSP; <&NBSP;

 分析程序中的错误,并改之。

#include

#include

class string{

private:

char*str;

public:

string(char*s)

{

str=new char[strlen(s)+1];

strcpy(str,s);

}

void pring(){cout< <&NBSP;

~string(){cout< <″DELETE″<

};

void main()

{

strint s1=″hello!!″;

strint s2=s1;

s1.print();

s2.print();

}

 分析下面程序中的错误,并改之。

int n;

public:

ares();

ares(int n1);

~ares(){cout< <″Destructing″<

};

ares::ares()

{

cout< <″Intializing default″<

n=0;

}

ares::ares(int n1)

{

cout< <″Intializing″<

n=n1;

}

void main()

{

ares x=1;

ares y=x;

}

 分析下面程序中的错误,并改之。

class ares{

const int a:

int& b;

public:

ares(int a1,int b1)

~ares(){cout< <″Destructing″<

};

ares::ares(int a1,intb1)

{

a=a1;

b=b1;

}

void main()

{

ares x(1,2);

}

 找出下面程序中的错误并说明理由。

#class base{

protected:

int p;

};

void fun()

{

base b;

int x=b.p;

}

 指出下列程序段中错误的语句,并说明原因。

class X{

private:

int a;

static int s;

public:

void fun(){s=10;}

static void sfun(X&);

void X::sfun(X& r)

{a=10;

r.a=10;

}

 找出下列程序中错误的语句,并说明错误的原因。

template

T max(T x,T y)

{return(x>y)?x:y;}

void fun(int i,char c)

{

max(i,i);

max(c,c);

max(i,c);

max(c,i);

}

 仔细阅读下面的程序,这个程序是想通过包含一个从filename到ifstream&的自动类型转换运算,使得在任何使用ifstream的地方都可以使用filename对象。如果是main()中cout< < #include #include

#include

clss filename{

ifstream File;

char buf[100];

ostrstream Name;

int nameset;

public:

filename(void):Name(ubf,100),nameset(0){}

filename(ocnst char*Filename):File(Filename),Name(ubf,100){

Name< <&NBSP;

nameset=1;

}

const char*name(void)const{return buf;}

void name(const char*newname){

if(nameset)return;

Name< <&NBSP;

nameset=1;

}

operator ifstream &(void){return File;}

};

void main(void){

filename file(″ygefilename.txt″);

cout< <&NBSP;

cout< <&NBSP;

}

 仔细阅读下面的程序,找出结构ttt中的错误,改正其中的错误并说明理由。

#include

struct ttt{

int x;

int y;

int z;

ttt(int,int,int)

viod display(void);

};

ttt::ttt(int a,int b,int c){x=a;y=b;z=c;}

void ttt::display(void){

cout< <″x=″< <&NBSP;<&NBSP;<&NBSP; <&NBSP;<&NBSP;<&NBSP; <&NBSP;

}

void main(void){

int aray[5];

for(int i=0;i<5;i+ +)

cout< <&NBSP;

cout<

int aray2[5]={0};

for(int j=0;j<5;j+ +)

ocut< <&NBSP;

cout<

int aray3[]={1,2,3,4,5};

for(int k=0;k

cout< <&NBSP;

cout<

ttt ttt4[5]={ttt(1,2,3),ttt(4,5,6),ttt(7,8,9),ttt(10,11,12)};

fot(int s=0;s<5;s+ +)

ttt4[s].display();

}

按照题目的意思,在下划线处填写正确的语句,要求至少写出4种方法。

#include

struct base{

int x;

int y;

int z;

}

void main(void){

base B={10,20,30};

base*pB;

pB=&B;

int sum;

sum= //用sum表示对象B中x、y、z的和

cout< <″sum=″< <&NBSP;

下列程序先接收若干用户的姓名和电话号码,按姓名的字典顺序排列后,再输出用户的姓名和电话号码。

#include

#inclued

#include

const int N=5; //设有5个用户

class person

{

char name[10];

char num[10];

public:

void getdata( (1) ){strcpy(name,na);strcpy(num,nu);}

friend void getsort(person pn[N]);

friend void outdata(person pn[N]);

};

void getsort(person pn[N]); //对对象数组进行选择法排序

{

int i,j,k;

person temp;

for(i=0;i

{

k=1;

for(j=i+1;j

if(strcmp( (2) )>0) k=j;

temp=pn[k];

pn[k]=pn[i];

pn[i]=temp;

}

}

void outdata(person pn[N]) //输出姓名和电话号码

{

int i;

cout< <″姓名 电话号码\n″;

cout< <″---------\n″;

cout.setf(ios::left);

for(i=0;i

{ cout.width(10);

cout<

cout.width(10);

cout< <&NBSP;

}

}

void main()

{

char*na[5]={″Li″,″Zhang″,″Ma″,″Chen″,″Gao″};

char*nu[5]={″8765781″,″5583901″,″8688080″,″8079500″,″9855321″};

person obj[5];

for(int i=0;i<5;i+ +)

(3) ;

person (4) ;

getsort(pt);

outdata(pt);

}

下列程序是一个含有比较运算符和赋值运算符重载的程序。请填空完成程序并上机运行验证。

#include

class point

{

private:

float x,y;

public:

point(float xx=0,float yy=0 {x=xx;y=yy;}

point(point &);

~point(){}

bool operator= =(point);

bool operator!=(point);

point operator+=(point);

point operator-=(point);

float get—x(){return x;}

float get—y(){return y;}

};

point:point(point &p)

{

(1) ;

}

bool point:perator= =(point p)

{

if( (2) )

return 1;

else

return 0;

}

bool point:perator!=(point p)

{

if(x!=p.get—x()&&y!=p.get—y())

return 1;

else

return 0;

}

point point:perator+=(point p)

{

this->x+=p.get—x();

this->y+=p.get—y();

return (3) ;

}

point point::operator-=(point p)

{

this->x-=p.get—x();

this->y-=p.get—y();

return*this;

}

void main()

{

point p1(1,2),p2(3,4),p3(5,6);

cout< <″p1= =p2? ″< <(p1= =p2)<

cout< <″p1!= =p2? ″< <(p1!= =p2)<

p3+=p1;

cout< <″p3+=p1,p3: ″< <&NBSP;<&NBSP;<&NBSP;

p3-=p1;

cout< <″p3+=p1,p3: ″< <&NBSP;<&NBSP;<&NBSP;

}

运行结果为:

p1= =p2? 0

p1!=p2? 1

p3+=p1,p3: 6,8

p3+=p1,p3: 5,6

下列程序中声明一个哺乳动物Mammal类,再由此派生出Dog类,二者都定义Spesk()成员函数,基类中定义Spesk()为虚函数。主程序中分别声明一个Mammal类和Dog类的对象,再分别用“对象名.函数名”和指针的形式调用Spesk()函数。请填空完成程序并上机运行验证。

#include

class Mammal

{

public:

(1) void Speak(){cout< <″This is a Mammal!″<

};

class Dog:public Mammal

{

public:

void Speak(){cout< <″This is a dog!″<

};

void main()

{

Mammal m, (2) ;

Dog d;

m.Speak();

d.Speak(0;

ptr=&m;

ptr->Speak();

(3) ;

ptr->Speak();

}

程序不能运行。

应在类的定义中加上下段。

string::string(string &a)

{

str=new char[strlen(a.str)+1];

strcpy(str,a.str);

}

程序才能得到正确结果。简单地说就是缺少拷贝初始化构造函数。

本题的错误在于没有定义类之间的赋值函数。

本题的错误在于初始化const和引用成员时,必须通过成员初始化列表进行。

 int x=b.p语句错误,x不能直接访问类体内的保护成员。

 a=10;错。静态成员函数只能通过对象名(或指向对象的指针)访问该对象的非静态成员。 max(i,c)和max(c,i)语句是错误的。出现错误的原因是由于没有隐含的类型转换的功能,实例化T的各模板之间必须保持完全一致的类型。如对语句max(i,c);编译器将先按变量i将T解释为int类型,此后出现的模板实参c不能解释为int类型时,便发生错误,在此没有隐含的类型转换的功能。

继承方法的实现如下:

#include

#include

#include

class filename:public ifstream{

char buf[100];

ostrstream Nane;

int nameset;

public:

filename(void):Name(buf,100),nameset(0){}

filename(const char*Filename):ifstream(Filename),Name(buf,100){

Name< <&NBSP;

nameset=1;

}

const char*name(void)const{

return buf;

}

void name(const char*newname){

if(nameset)return;

Name< <&NBSP;

nameset=1;

}

};

在没有构造函数时编译器会自动创建一个缺省构造函数,但如量有了构造函数就不会自动创建一个缺省构造函数了。语句ttt ttt4(5)调用4次构造函数(有参数)创建4个数组对象,但第5个

数组则要调用无参数构造函数,所以程序的错误是结构ttt中没有定义无参数构造函数,可以在ttt结构体内加上如下语句:

ttt(){}

正确语句的4种填法为:

B.x+B.y+B.z;

PB->x+pB->y+pB->z;

(&B)->x+(&B)->y+(&B)->z;

(*pB).x+(*pB).y+(*pB).z;

(1)char*na,char*nu或char na[],char nu[]

(2)pn[k].name,pn[j].name

(3)obj[i].getdata(na[i],nu[i])

(4)*pt=obj

分析: (1)空位于类成员函数getdata()的形参表中,根据其后的函数体内容和数据成员的类型,易知(1)处应填char*na,char*nu或char na[],char nu[]。(2)空位于进行排序的友元函数getsort(person pn[N]的比较语句中,根据函数的参数和意要求,可知此处是对对象数组pn[N]的name成员进行比较,故填pn[k].name,pn[j].name。在主函数中,注意到定义了对象数组obj[N],但没有被赋值,因此 (3)处要填obj[i].getdata(na[i],nu[i]),实现对各对象元素的赋值。空(4)处应注意到下两函数调用中的实参为pt,而pt又没有被定义且应为指向类对象数组的指针,故此处填*pt=obj。

(1)x=p,x;y=p.y

(2)x= =p.get—x()&&y= =p.get—y()

(3)*this

分析: 这是一个含有比较运算符和赋值运算重载的程序。从程序可以看出,这两种运算符的重载很容易实现,其中(1)处是point类的拷贝构造函数定义;(2)处是比较两个点是否相等,故可知(2)处应填x= =p.get—x()&&y= =p.get—y(),表示x值和y值都相等时,返回1,否则返回0;(3)处是返回this指针的内容。

(1)virtual

(2)*ptr

(3)ptr=&d

分析: 这是一个含有虚函数的程序。首先要注意的是虚函数必须在基类中定义,因此(1)处应填virtual;其次在用指针对基类和派生类对象操作时,指针应定义为基类的指针,如果定义为派生类的指针,则该指针只能指向派生类的对象,而不能指向基类对象,因此(2)处应填*ptr,定义一个基类指针;(3)处填入ptr=&d,是让指针指向派生类对象。

本文来源:https://www.bwwdw.com/article/woym.html

Top