C++练习题.docx

上传人:b****8 文档编号:9860127 上传时间:2023-02-07 格式:DOCX 页数:19 大小:22.98KB
下载 相关 举报
C++练习题.docx_第1页
第1页 / 共19页
C++练习题.docx_第2页
第2页 / 共19页
C++练习题.docx_第3页
第3页 / 共19页
C++练习题.docx_第4页
第4页 / 共19页
C++练习题.docx_第5页
第5页 / 共19页
点击查看更多>>
下载资源
资源描述

C++练习题.docx

《C++练习题.docx》由会员分享,可在线阅读,更多相关《C++练习题.docx(19页珍藏版)》请在冰豆网上搜索。

C++练习题.docx

C++练习题

1、创建一个单链表,写一个链表。

单向链表的反转是一个经常被问到的一个面试题,也是一个非常基础的问题。

比如一个链表是这样的:

1->2->3->4->5通过反转后成为5->4->3->2->1。

#include

#include

usingnamespacestd;

classFID

{

public:

intnum;

FID*next;

};

FID*head=NULL;

voidcreate(intnum)

{

while(num>0)

{

FID*p=newFID;

cout<<"数字:

";

cin>>p->num;

if(head==NULL)

{

head=p;

p->next=NULL;

}

else{

FID*temp=head;

while(temp->next!

=NULL)

{

temp=temp->next;

}

temp->next=p;

p->next=NULL;

}

num--;

}

}

voidreserve()

{

FID*pre,*cur,*next;

pre=head;

cur=pre->next;

while(cur!

=NULL)

{

next=cur->next;

cur->next=pre;

pre=cur;

cur=next;

}

head->next=NULL;

head=pre;

}

voidshow()

{

FID*ps=head;

while(ps!

=NULL)

{

cout<num;

ps=ps->next;

}

}

intmain()

{

create(5);

reserve();

show();

return0;

}

2、已知string类定义如下:

classString

{

public:

String(constchar*str=NULL);//通用构造函数

String(constString&another);//拷贝构造函数

~String();//析构函数

String&operater=(constString&rhs);//赋值函数

private:

char*m_data;//用于保存字符串

};

String:

:

String(constchar*str)

{

if(str==NULL)//strlen在参数为NULL时会抛

异常才会有这步判断

{

m_data=newchar[1];

m_data[0]='\0';

}

else

{

m_data=newchar[strlen(str)+1];

strcpy(m_data,str);

}

}

String:

:

String(constString&another)

{

m_data=newchar[strlen(another.m_data)+1];

strcpy(m_data,other.m_data);

}

String&String:

:

operator=(constString&rhs)

{

if(this==&rhs)

return*this;

delete[]m_data;//删除原来的数据,新开一块内

m_data=newchar[strlen(rhs.m_data)+1];

strcpy(m_data,rhs.m_data);

return*this;

}

String:

:

~String()

{

delete[]m_data;

}

3、已知strcpy的函数原型:

char*strcpy(char*strDest,constchar*strSrc)其中strDest是目的字符串,strSrc是源字符串。

不调用C++/C的字符串库函数,请编写函数strcpy。

char*strcpy(char*strDest,constchar*strSrc)

{

if((strDest==NULL)||(strSrc==NULL))//[1]

throw"Invalidargument(s)";//[2]

char*strDestCopy=strDest;//[3]

while((*strDest++=*strSrc++)!

='\0');//[4]

returnstrDestCopy;

}

3、求下面函数的返回值。

intfunc(x)

{

intcountx=0;

while(x)

{

countx++;

x=x&(x-1);

}

returncountx;

}

x=9999时,x-1=9998,用二进制表示

10011100001111

10011100001110

当他们执行&运算并赋值给x,结果x为

10011100001110

此时x-1为

10011100001101

当他们执行&运算并赋值给x,结果x为

10011100001100

如此类推到结果为00000000000000,应该发现x=x&(x-1)就是将x最右边的二进制位1变为0。

x为9999时二进制为1的位有8个,所以结果为8

4、什么是“引用”?

申明和使用“引用”要注意哪些问题?

1:

引用就是对某个变量其别名。

对引用的操作与对应变量的操作的效果完全一样。

2:

申明一个引用的时候,要对其进行初始化。

引用申明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,不能再把该引用名作为其他变量名的别名。

声明一个引用,不是新定义一个变量,他只表示该引用名是目标变量名的一个别名,他本身不是一中数据类型,因此引用本身不是储存单元,系统也不给引用分配储存单元。

3:

不能创建数组引用。

5、将“引用”作为函数参数有哪些特点?

1:

传递引用给函数与传递指针的效果一样。

2:

使用引用传递函数的参数,在内存中并没有产生实参的副本,他是直接对实参操作。

6、在什么时候需要使用“常引用”?

如果既要利用引用提高程序的效率,又要保护传递给函数的数据不在函数中被改变,就应使用常引用。

7、将“引用”作为函数返回值类型的格式、好处和需要遵守的规则?

1:

格式:

类型标识符&函数名

2:

好处:

在内存中不产生被返回值的副本

3:

需要遵守:

一、不能返回局部变量的引用;二、不能返回函数内部new分配的内存的引用;

三、可以返回类成员引用,但最好是const。

8、“引用”与多态的关系?

引用是除指针外另一个可以产生多态效果的手段。

这意味这,一个积累的引用可以指向他的派生类实例。

9、“引用”与指针的区别是什么?

指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。

程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。

此外,就是对函数传ref和pointer的区别。

10、什么时候需要“引用”?

复杂类型要用,避免拷贝构造函数被调用

12、.h头文件中的ifndef/define/endif的作用?

这个是预编译的命令,是用来防止头文件重复包含的。

13、#include与#include"file.h"的区别?

<>是标准库头文件:

查找时在系统定义的库中查询,””是用户自定义库头文件:

查找时在用户自己定义的文件中查找。

14、在C++程序中调用被C编译器编译后的函数,为什么要加extern“C”?

作为extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。

通常,在模块的头文件中对本模块提供给其它模块引用的函数和全局变量以关键字extern声明。

15、面向对象的四个基本特征,并简单叙述之?

抽象,继承,封装,多态

16、重载(overload)和重写(overried,有的书也叫做“覆盖”)的区别?

从定义上来说:

重载:

是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

重写:

是指子类重新定义父类虚函数的方法。

从实现原理上来说:

重载:

编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数。

重写:

和多态真正相关。

当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的。

17、多态的作用?

允许父类指针或名称来引用子类对象,或对象方法,而实际调用的方法为对象的类类型方法。

18、newdelete与mallocfree的联系与区别?

malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。

它们都可用于在堆区上申请动态内存和释放内存。

用malloc函数需要指定分配的字节数并且不能初始化对象,new会自动调用对象的构造函数,delete会调用对象的析构函数,而free不会调用对象的析构函数。

19、#defineDOUBLE(x)x+x,i=5*DOUBLE(5);i是多少?

i=30

20、有哪几种情况只能用intializationlist而不能用assignment?

无论是在构造函数初始化列表中初始化成员,还是在构造函数体中对它们赋值,最终结果都是相同的。

不同之处在于,使用构造函数初始化列表初始化数据成员,没有定义初始化列表的构造函数在构造函数体中对数据成员赋值。

对于const和reference类型成员变量,它们只能够被初始化而不能做赋值操作,因此只能用初始化列表。

还有一种情况就是,类的构造函数需要调用其基类的构造函数的时候。

20、C++是不是类型安全的?

不是。

两个不同类型的指针之间可以强制转换(用reinterpretcast)。

C#是类型安全的。

21、main函数执行以前,还会执行什么代码?

全局对象的构造函数会在Main前执行。

22、描述内存分配方式以及它们的区别?

1) 从静态存储区域分配。

内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。

例如全局变量,static 变量。

2) 在栈上创建。

在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。

栈内存分配运算内置于处理器的指令集。

3) 从堆上分配,亦称动态内存分配。

程序在运行的时候用malloc 或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。

动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。

24、struct和class的区别。

默认继承权限。

默认情况下,class的继承是以private来继承而struct则是按照public进行继承。

成员的默认访问权限。

class的成员默认是private权限,struct默认是public权限。

25、当一个类A中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。

当一个类A中没有生命任何成员变量与成员函数,这时sizeof(A)的值是多少,如果不是零,请解释一下编译器为什么没有让它为零。

(Autodesk)

26、比较C++中的4种类型转换方式?

1.static_cast

最常用的类型转换符,在正常状况下的类型转换,如把int转换为float;

2.const_cast

用于取出const属性,把const类型的指针变为非const类型的指针;

3.dynamic_cast

用于运算时检查该转换是否类型安全,但只在多态类型是合法;

4.reinterpret_cast

Interpret是解释的意思,reinterpret即为重新解释,此标识符的意思即为数据的二进制心事重新解释

27、分别写出BOOL,int,float,指针类型的变量a与“零”的比较语句。

BOOL:

   if(!

a)orif(a)

int:

    if(a==0)

float:

  constEXPRESSIONEXP=0.000001

         if(a-EXP)

pointer:

if(a!

=NULL)orif(a==NULL)

 

28、请说出const与#define相比,有何优点?

1)const常量有数据类型,而宏常量没有数据类型。

编译器可以对前者进行类型安全检查。

而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。

2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。

29、简述数组与指针的区别?

数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。

指针可以随时指向任意类型的内存块。

(1)修改内容上的差别

chara[]=“hello”;

a[0]=?

X?

;

char*p=“world”;//注意p指向常量字符串

p[0]=?

X?

;//编译器不能发现该错误,运行时错误

(2)用运算符sizeof可以计算出数组的容量(字节数)。

sizeof(p),p为指针得到的是一个指针变量的字节数,而不是p所指的内存容量。

C++/C语言没有办法知道指针所指的内存容量,除非在申请内存时记住它。

注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针。

chara[]="helloworld";

char*p=a;

cout<

cout<

计算数组和指针的内存容量

voidFunc(chara[100])

{

cout<

}

30、类成员函数的重载、覆盖和隐藏区别?

a.成员函数被重载的特征:

(1)相同的范围(在同一个类中);

(2)函数名字相同;

(3)参数不同;

(4)virtual关键字可有可无。

b.覆盖是指派生类函数覆盖基类函数,特征是:

(1)不同的范围(分别位于派生类与基类);

(2)函数名字相同;

(3)参数相同;

(4)基类函数必须有virtual关键字。

c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下:

(1)如果派生类的函数与基类的函数同名,但是参数不同。

此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。

(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。

此时,基类的函数被隐藏(注意别与覆盖混淆)

31、如何判断一段程序是由C编译程序还是由C++编译程序编译的?

#ifdef__cplusplus;

cout<<"c++&qu;

#else;

cout<<"c";

#endif;

32、文件中有一组整数,要求排序后输出到另一个文件中。

#include

#include

usingnamespacestd;

voidOrder(vector&data)//bubblesort

{

intcount=data.size();

inttag=false;//设置是否需要继续冒泡的标志位

for(inti=0;i

{

for(intj=0;j

{

if(data[j]>data[j+1])

{

tag=true;

inttemp=data[j];

data[j]=data[j+1];

data[j+1]=temp;

}

}

if(!

tag)

break;

}

}

voidmain(void)

{

vectordata;

ifstreamin("c:

\\data.txt");

if(!

in)

{

cout<<"fileerror!

";

exit

(1);

}

inttemp;

while(!

in.eof())

{

in>>temp;

data.push_back(temp);

}

in.close();//关闭输入文件流

Order(data);

ofstreamout("c:

\\result.txt");

if(!

out)

{

cout<<"fileerror!

";

exit

(1);

}

for(i=0;i

out<

out.close();//关闭输出文件流

}

33、输入一个字符串,将其逆序后输出。

#include

usingnamespacestd;

 

voidmain()

{

 chara[50];memset(a,0,sizeof(a));

 inti=0,j;

 chart;

 cin.getline(a,50,'\n');

  for(i=0,j=strlen(a)-1;i

 {

  t=a[i];

     a[i]=a[j];

  a[j]=t;

 }

 cout<

}

34、#include"stdafx.h"

#defineSQR(X)X*X

intmain(intargc,char*argv[])

{

inta=10;

intk=2;

intm=1;

a/=SQR(k+m)/SQR(k+m);

printf("%d\n",a);

return0;

}

这道题目的结果是什么啊?

2

35、const符号常量;

(1)constchar*p

(2)charconst*p

(3)char*constp

说明上面三种描述的区别;

如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;

如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。

(1)constchar*p

一个指向char类型的const对象指针,p不是常量,我们可以修改p的值,使其指向不同的char,但是不能改变它指向非char对象,如:

constchar*p;

charc1='a';

charc2='b';

p=&c1;//ok

p=&c2;//ok

*p=c1;//error

(2)char*constp

此时*p可以修改,而p不能修改。

(3)constchar*constp

这种是地址及指向对象都不能修改。

36、下面是C语言中两种if语句判断方式。

请问哪种写法更好?

为什么?

intn;

if(n==10)//第一种判断方式

if(10==n)//第二种判断方式

首先,看看效率上有没有区别

 if (i == 1)

004014CF   cmp         dword ptr [ebp-4],1

004014D3   jne         main+2Eh (004014de)

 if (2 == i)

004014DE   cmp         dword ptr [ebp-4],2

004014E2   jne         main+3Dh (004014ed)

可以看到效率上没有区别。

37、下面的代码有什么问题?

voidDoSomeThing(...)

{

char*p;

...

p=malloc(1024);//分配1K的空间p=(char*)malloc(1024);

if(NULL==p)

return;

...

p=realloc(p,2048);//空间不够,重新分配到2K

if(NULL==p)

return;

...

}

p=malloc(1024);    应该写成:

p=(char*)malloc(1024); 

       没有释放p的空间,造成内存泄漏。

38、下面代码有什么错误?

(1)Voidtest1()

{

charstring[10];

char*str1="0123456789";

strcpy(string,str1);

数组越界

(2)Voidtest2()

{

charstring[10],str1[10];

for(i=0;i<10;i++)//i未定义

{

str1[i]='a';

}

strcpy(string,str1);

}

数组越界

39、写出运行结果:

{//test1

charstr[]="world";cout<

";

char*p=str;cout<

";

chari=10;cout<

";

void*pp=malloc(10);cout<

}

6:

4:

1:

4

40.下面的代码有什么问题?

classA

{

public:

A(){p=this;}

~A(){if(p!

=NULL){deletep;p=NULL;}}

A*p;

};

会引起无限递归

41、101个硬币100真、1假,真假区别在于重量。

请用无砝码天平称两次给出真币重还是假币重的结论。

方法1:

 

把硬币分成50,50,1。

 

称50与50,如果平衡,则这两堆为真币,剩下的1为假币。

再用这个假币和真币称一下得结论。

 

若不平衡,则1为真币,接着判断假币在哪个堆里面。

 

取轻的1堆,分成25,25,称重。

若平衡则假币在另一堆里面,假币重。

 

若不平衡,则假币在这一堆中,假币轻。

 

方法2:

 

把硬币分成33,33,34。

 

称33与33,如果平衡,则这两堆为真币,假币在第三堆中。

从66中取出34与第三堆进行称,第三堆所在的天平的那一端的轻重就是假币的轻重情况。

 

若不平衡,则假币在这两堆中。

取下轻的一堆,从34里面取出33替换,称量。

如果平衡,代表取下的那一堆中有假币,假

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高等教育 > 文学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1