程序员面试试题深刻剖析资料.docx
- 文档编号:25204498
- 上传时间:2023-06-06
- 格式:DOCX
- 页数:14
- 大小:20.41KB
程序员面试试题深刻剖析资料.docx
《程序员面试试题深刻剖析资料.docx》由会员分享,可在线阅读,更多相关《程序员面试试题深刻剖析资料.docx(14页珍藏版)》请在冰豆网上搜索。
程序员面试试题深刻剖析资料
面试例题1:
如果鸟是可以飞的,那么鸵鸟是鸟么?
鸵鸟如何继承鸟类?
[美国某著名分析软件公司2005年面试题]
解析:
如果所有鸟都能飞,那鸵鸟就不是鸟!
回答这种问题时,不要相信自己的直觉!
将直觉和合适的继承联系起来还需要一段时间。
根据题干可以得知:
鸟是可以飞的。
也就是说,当鸟飞行时,它的高度是大于0的。
鸵鸟是鸟类(生物学上)的一种。
但它的飞行高度为0(鸵鸟不能飞)。
不要把可替代性和子集相混淆。
即使鸵鸟集是鸟集的一个子集(每个驼鸟集都在鸟集内),但并不意味着鸵鸟的行为能够代替鸟的行为。
可替代性与行为有关,与子集没有关系。
当评价一个潜在的继承关系时,重要的因素是可替代的行为,而不是子集。
答案:
如果一定要让鸵鸟来继承鸟类,可以采取组合的办法,把鸟类中的可以被鸵鸟继承的函数挑选出来,这样鸵鸟就不是“akindof”鸟了,而是“hassomekindof”鸟的属性而已。
代码如下:
#include
#include
usingnamespacestd;
classbird
{
public:
voideat();
voidsleep();
voidfly();
};
classostrich
{
public:
birdeat(){cout<<"ostricheat";};
birdsleep(){cout<<"ostrichsleep";};
};
intmain()
{
ostrichxiaoq;
xiaoq.eat();
xiaoq.sleep();
return0;
}
面试例题2:
Findthedefectsineachofthefollowingprograms,andexplainwhyitisincorrect.(找出下面程序的错误,并解释它为什么是错的。
)[中国台湾某著名杀毒软件公司2005年面试题]
#include
usingnamespacestd;
classBase{
public:
intval;
Base(){val=1;};
};
classDerive:
Base{
public:
intval;
Derive(inti){val=Base:
:
val+i;};
};
intmain(int,char**,char**){
Derived(10);
cout<<d.Base:
:
val<<endl<<d.val<<endl;
return0;
}
答案:
把classDerive:
Base改成classDerive:
publicBase。
解析:
这是个类继承问题。
如果不指定public,C++默认的是私有继承。
私有继承是无法继承并使用父类函数中的公有变量的。
扩展知识(组合)
若在逻辑上A是B的“一部分”(apartof),则不允许B从A派生,而是要用A和其他东西组合出B。
例如眼(Eye)、鼻(Nose)、口(Mouth)、耳(Ear)是头(Head)的一部分,所以类Head应该由类Eye、Nose、Mouth、Ear组合而成,而不是派生而成。
程序如下:
classEye
{
public:
voidLook(void);
};
classNose
{
public:
voidSmell(void);
};
classMouth
{
public:
voidEat(void);
};
classEar
{
public:
voidListen(void);
};
classHead
{
public:
voidLook(void){m_eye.Look();}
voidSmell(void){m_nose.Smell();}
voidEat(void){m_mouth.Eat();}
voidListen(void){m_ear.Listen();}
private:
Eyem_eye;
Nosem_nose;
Mouthm_mouth;
Earm_ear;
};
Head由Eye、Nose、Mouth、Ear组合而成。
如果允许Head从Eye、Nose、Mouth、Ear派生而成,那么Head将自动具有Look、Smell、Eat、Listen这些功能。
程序十分简短并且运行正确,但是下面这种设计方法却是不对的。
classHead:
publicEye,publicNose,publicMouth,publicEar
{
};
面试例题3:
Findthedefectsineachofthefollowingprograms,andexplainwhyitisincorrect.(找出下面程序的错误,并解释它为什么是错的。
)[德国某著名软件咨询企业2005年面试题]
classbase{
private:
inti;
public:
base(intx){i=x;}
};
classderived:
publicbase{
private:
inti;
public:
derived(intx,inty){i=x;}
voidprintTotal(){inttotal=i+base:
:
i;}
};
解析:
要在子类中设定初始成员变量,把derived(intx,inty)改成derived(intx,inty):
base(x)。
答案:
代码如下:
classbase
{
protected:
//这里的访问属性需要改变
inti;
public:
base(intx){i=x;}
};
classderived:
publicbase
{
private:
inti;
public:
derived(intx,inty):
base(x)//以前没有初始化基类的成员变量
{
i=y;
}
voidprintTotal()
{
inttotal=i+base:
:
i;
}
};
32.请说出const与#define相比,有何优点?
答案:
1)const常量有数据类型,而宏常量没有数据类型。
编译器可以对前者进行类型安全检查。
而对后者只进行字符替换,没有类型安全检查,并且在字符替换可能会产生意料不到的错误。
2)有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试。
33.简述数组与指针的区别?
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。
指针可以随时指向任意类型的内存块。
(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< } 34.类成员函数的重载、覆盖和隐藏区别? 答案: a.成员函数被重载的特征: (1)相同的范围(在同一个类中); (2)函数名字相同; (3)参数不同; (4)virtual关键字可有可无。 b.覆盖是指派生类函数覆盖基类函数,特征是: (1)不同的范围(分别位于派生类与基类); (2)函数名字相同; (3)参数相同; (4)基类函数必须有virtual关键字。 c.“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,规则如下: (1)如果派生类的函数与基类的函数同名,但是参数不同。 此时,不论有无virtual关键字,基类的函数将被隐藏(注意别与重载混淆)。 (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。 此时,基类的函数被隐藏(注意别与覆盖混淆) 35.Therearetwointvariables: aandb,don’tuse“if”,“? : ”,“switch”orotherjudgementstatements,findoutthebiggestoneofthetwonumbers. 答案: ((a+b)+abs(a-b))/2 36.如何打印出当前源文件的文件名以及源文件的当前行号? 答案: cout<<__FILE__; cout<<__LINE__; __FILE__和__LINE__是系统预定义宏,这种宏并不是在某个文件中定义的,而是由编译器定义的。 37.main主函数执行完毕后,是否可能会再执行一段代码,给出说明? 答案: 可以,可以用_onexit注册一个函数,它会在main之后执行intfn1(void),fn2(void),fn3(void),fn4(void); voidmain(void) { Stringstr("zhanglin"); _onexit(fn1); _onexit(fn2); _onexit(fn3); _onexit(fn4); printf("Thisisexecutedfirst.\n"); } intfn1() { printf("next.\n"); return0; } intfn2() { printf("executed"); return0; } intfn3() { printf("is"); return0; } intfn4() { printf("This"); return0; } The_onexitfunctionispassedtheaddressofafunction(func)tobecalledwhentheprogramterminatesnormally.Successivecallsto_onexitcreatearegisteroffunctionsthatareexecutedinLIFO(last-in-first-out)order.Thefunctionspassedto_onexitcannottakeparameters. 38.如何判断一段程序是由C编译程序还是由C++编译程序编译的? 答案: #ifdef__cplusplus cout<<"c++"; #else cout<<"c"; #endif 39.文件中有一组整数,要求排序后输出到另一个文件中 答案: #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<40.链表题: 一个链表的结点结构 structNode { intdata; Node*next; }; typedefstructNodeNode; (1)已知链表的头结点head,写一个函数把这个链表逆序(Intel) Node*ReverseList(Node*head)//链表逆序 { if(head==NULL||head->next==NULL) returnhead; Node*p1=head; Node*p2=p1->next; Node*p3=p2->next; p1->next=NULL; while(p3! =NULL) { p2->next=p1; p1=p2; p2=p3; p3=p3->next; } p2->next=p1; head=p2; returnhead; } (2)已知两个链表head1和head2各自有序,请把它们合并成一个链表依然有序。 (保留所有结点,即便大小相同) Node*Merge(Node*head1,Node*head2) { if(head1==NULL) returnhead2; if(head2==NULL) returnhead1; Node*head=NULL; Node*p1=NULL; Node*p2=NULL; if(head1->data { head=head1; p1=head1->next; p2=head2; } else { head=head2; p2=head2->next; p1=head1; } Node*pcurrent=head; while(p1! =NULL&&p2! =NULL) { if(p1->data<=p2->data) { pcurrent->next=p1; pcurrent=p1; p1=p1->next; } else { pcurrent->next=p2; pcurrent=p2; p2=p2->next; } } if(p1! =NULL) pcurrent->next=p1; if(p2! =NULL) pcurrent->next=p2; returnhead; } (3)已知两个链表head1和head2各自有序,请把它们合并成一个链表依然有序,这次要求用递归方法进行。 (Autodesk) 答案: Node*MergeRecursive(Node*head1,Node*head2) { if(head1==NULL) returnhead2; if(head2==NULL) returnhead1; Node*head=NULL; if(head1->data { head=head1; head->next=MergeRecursive(head1->next,head2); } else { head=head2; head->next=MergeRecursive(head1,head2->next); } returnhead; } [C/C++]C/C++笔试、面试题目大汇总[41-45] bioeconomy发表于2006-3-2220: 28: 00 41.分析一下这段程序的输出(Autodesk) classB { public: B() { cout<<"defaultconstructor"<} ~B() { cout<<"destructed"<} B(inti): data(i)//B(int)worksasaconverter(int->instanceofB) { cout<<"constructedbyparameter"< private: intdata; }; BPlay(Bb) { returnb; } (1)results: intmain(intargc,char*argv[])constructedbyparameter5 {destructedB(5)形参析构 Bt1=Play(5);Bt2=Play(t1); destructedt1形参析构 return0; destructedt2 注意顺序! }destructedt1 (2)results: intmain(intargc,char*argv[])constructedbyparameter5 {destructedB(5)形参析构 Bt1=Play(5);Bt2=Play(10); constructedbyparameter10 return0; destructedB(10)形参析构 }destructedt2 注意顺序! destructedt1 42.写一个函数找出一个整数数组中,第二大的数(microsoft) 答案: constintMINNUMBER=-32767; intfind_sec_max(intdata[],intcount) { intmaxnumber=data[0]; intsec_max=MINNUMBER; for(inti=1;i { if(data[i]>maxnumber) { sec_max=maxnumber; maxnumber=data[i]; } else { if(data[i]>sec_max) sec_max=data[i]; } } returnsec_max; } 43.写一个在一个字符串(n)中寻找一个子串(m)第一个位置的函数。 KMP算法效率最好,时间复杂度是O(n+m),详见: 44.多重继承的内存分配问题: 比如有classA: publicclassB,publicclassC{} 那么A的内存结构大致是怎么样的? 这个是compiler-dependent的,不同的实现其细节可能不同。 如果不考虑有虚函数、虚继承的话就相当简单;否则的话,相当复杂。 可以参考《深入探索C++对象模型》,或者: 45.如何判断一个单链表是有环的? (注意不能用标志位,最多只能用两个额外指针) structnode{charval;node*next;} boolcheck(constnode*head){}//returnfalse: 无环;true: 有环 一种O(n)的办法就是(搞两个指针,一个每次递增一步,一个每次递增两步,如果有环的话两者必然重合,反之亦然): boolcheck(constnode*head) { if(head==NULL)returnfalse; node*low=head,*fast=head->next; while(fast! =NULL&&fast->next! =NULL) { low=low->next; fast=fast->next->next; if(low==fast)returntrue; } returnfalse; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 程序员 面试 试题 深刻 剖析 资料