您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 招聘面试 > IT公司笔试面试题系列
C++笔试题1.多态类中的虚函数表是Compile-Time,还是Run-Time时建立的?答案:虚拟函数表是在编译期就建立了,各个虚拟函数这时被组织成了一个虚拟函数的入口地址的数组.而对象的隐藏成员--虚拟函数表指针是在运行期--也就是构造函数被调用时进行初始化的,这是实现多态的关键.sizeof的常量性sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用,如:charary[sizeof(int)*10];//ok最新的C99标准规定sizeof也可以在运行时刻进行计算,如下面的程序在Dev-C++中可以正确执行:intn;n=10;//n动态赋值charary[n];//C99也支持数组的动态定义printf(%d\n,sizeof(ary));//ok.输出10但在没有完全实现C99标准的编译器中就行不通了,上面的代码在VC6中就通不过编译。所以我们最好还是认为sizeof是在编译期执行的,这样不会带来错误,让程序的可移植性强些。2.一个父类写了一个virtual函数,如果子类覆盖它的函数不加virtual,也能实现多态?在子类的空间里,有没有父类的这个函数,或者父类的私有变量?(华为笔试题)答案:只要基类在定义成员函数时已经声明了virtue关键字,在派生类实现的时候覆盖该函数时,virtue关键字可加可不加,不影响多态的实现。子类的空间里有父类的所有变量(static除外)。3.完成字符串拷贝可以使用sprintf、strcpy及memcpy函数,请问这些函数有什么区别,你喜欢使用哪个,为什么?答案:这些函数的区别在于实现功能以及操作对象不同。1.strcpy函数操作的对象是字符串,完成从源字符串到目的字符串的拷贝功能。2.snprintf函数操作的对象不限于字符串:虽然目的对象是字符串,但是源对象可以是字符串、也可以是任意基本类型的数据。这个函数主要用来实现(字符串或基本数据类型)向字符串的转换功能。如果源对象是字符串,并且指定%s格式符,也可实现字符串拷贝功能。3.memcpy函数顾名思义就是内存拷贝,实现将一个内存块的内容复制到另一个内存块这一功能。内存块由其首地址以及长度确定。程序中出现的实体对象,不论是什么类型,其最终表现就是在内存中占据一席之地(一个内存区间或块)。因此,memcpy的操作对象不局限于某一类数据类型,或者说可适用于任意数据类型,只要能给出对象的起始地址和内存长度信息、并且对象具有可操作性即可。鉴于memcpy函数等长拷贝的特点以及数据类型代表的物理意义,memcpy函数通常限于同种类型数据或对象之间的拷贝,其中当然也包括字符串拷贝以及基本数据类型的拷贝。对于字符串拷贝来说,用上述三个函数都可以实现,但是其实现的效率和使用的方便程度不同:1.strcpy无疑是最合适的选择:效率高且调用方便。2.snprintf要额外指定格式符并且进行格式转化,麻烦且效率不高。3.memcpy虽然高效,但是需要额外提供拷贝的内存长度这一参数,易错且使用不便;并且如果长度指定过大的话(最优长度是源字符串长度+1),还会带来性能的下降。其实strcpy函数一般是在内部调用memcpy函数或者用汇编直接实现的,以达到高效的目的。因此,使用memcpy和strcpy拷贝字符串在性能上应该没有什么大的差别。4.请编写一个C函数,该函数给出一个字节中被置1的位的个数,并请给出该题的至少一个不同解法。第一种unsignedintTestAsOne0(charlog){inti;unsignedintnum=0,val;for(i=0;i8;i++){val=logi;//移位val&=0x01;//与1相与if(val)num++;}returnnum;}第二种unsignedintTestAsOne1(charlog){inti;unsignedintnum=0,val;for(i=0;i8;i++){val=(~log)i;//反码?val&=0x00;//与0相与if(!val)num++;}returnnum;}还有一种方法是X&X-1,微软的《编程之美》里有,这里不再赘述。5.请编写一个C函数,该函数将给定的一个字符串转换成整数。intInvert(char*str){intnum=0;while(*str!=''){intdigital=*str-48;num=num*10+digital;str=str+1;}returnnum;}6.请编写一个C函数,该函数将给定的一个整数转换成字符串。voidIntToCharChange(intnum,char*pval){charstrval[100];inti,j;intval0=0;intval1=0;val0=num;for(i=0;i100;i++){val1=val0%10;//取余val0=val0/10;//取整strval[i]=val1+48;//数字—字符if(val010){i++;strval[i]=val0+48;break;}}for(j=0;j=i;j++)//倒置{pval[j]=strval[i-j];}pval[j]='';}7.请编写一个C函数,该函数在一个字符串中找到可能的最长的子字符串,该字符串是由同一字符组成的。intChildString(char*p)//自己写{Char*q=p;intstringlen=0,i=0,j=1,len=0,maxlen=1;while(*q!=’\0’)//不能用strlen,求得长度stringlen{Stringlen++;q++;}while(iStringlen){if(*(p+i)==*(p+j)&&jStringlen){len++;//统计子串长度i++;j++;}else{if(lenmaxlen)//统计最大子串长度{maxlen=len+1;len=0;}elselen=0;i++;j++;}}returnmaxlen;}1.假设现有一个单向的链表,但是只知道只有一个指向该节点的指针p,并且假设这个节点不是尾节点,试编程实现删除此节点参考:将下一个节点的内容复制到本节点上,然后删除下一个节点。2.字符指针、浮点数指针、以及函数指针这三种类型的变量哪个占用的内存最大?为什么?答案:指针变量也占用内存单元,而且所有指针变量占用内存单元的数量都是相同的。就是说,不管是指向何种对象的指针变量,它们占用内存的字节数都是一样的,并且要足够把程序中所能用到的最大地址表示出来(通常是一个机器字长)。3.类ClassB从ClassA派生,那么ClassA*a=newClassB(…);试问该表达是否合法?为什么?答案:派生类的指针指向基类的对象是错误的,不能通过编译的;基类的指针可以指向派生类的对象,调用派生类的函数。4.如果ClassA中定义并实现虚函数intfunc(void),ClassB中也实现该函数,那么上述变量a-func()将调用哪个类里面的函数?如果intfunc(void)不是虚函数,情况又如何?为什么?答案:第一问调用的是B的。第二问调用A的。虚函数的一个典型应用,虚函数只能借助于指针或者引用来达到多态的效果如果没有定义成虚函数:------classA{public:voidprint(){cout”ThisisA”endl;}};classB:publicA{public:voidprint(){cout”ThisisB”endl;}};intmain(){//为了在以后便于区分,我这段main()代码叫做main1Aa;Bb;A*p1=&a;A*p2=&b;p1-print();p2-print();}结果是两个ThisisA如果定义成虚函数:---------classA{public:virtualvoidprint(){cout”ThisisA”endl;}//现在成了虚函数了};classB:publicA{public:voidprint(){cout”ThisisB”endl;}//这里不需要在前面加上关键字virtual,只需在把基类的成员函数设为virtual,其派生类的相应的函数也会自动变为虚函数};再运行main输出的结果就是ThisisA和ThisisB。5.char**p,a[16][8];问:p=a是否会导致程序在以后出现问题?为什么?参考:这个不会导致出现问题,但是要注意p的使用,如a[1][2]等价的为*(*(p+1)+2)而不是*(p+11),会的,这样会出现编译错误正确的是:chara[5][5];char(*p)[5];p=a;6.应用程序在运行时的内存包括代码区和数据区,其中数据区又包括哪些部分?参考:对于一个进程的内存空间而言,可以在逻辑上分成3个部份:代码区,静态数据区和动态数据区。动态数据区一般就是“堆栈”。栈是一种线性结构,堆是一种链式结构。进程的每个线程都有私有的“栈”。全局变量和静态变量分配在静态数据区,本地变量分配在动态数据区,即堆栈中。程序通过堆栈的基地址和偏移量来访问本地变量。7.用,,|,&实现一个WORD(2个字节)的高低位交换intmain(){unsignedshorta=0xABCD;unsignedshortb;unsignedshortc,d;b=(a8)&0xff00;c=(a8)&0x00ff;d=b|c;printf(n%x,b);printf(n%x,c);printf(n%x,d);return0;}结果是CDAB2俩个字节是16位前八位为高位后八位为低位然后结合8.编写一个函数,函数接收一个字符串,是由十六进制数组成的一组字符串,函数的功能是把接到的这组字符串转换成十进制数字.并将十进制数字返回.答案:BOOLHexToDec(LPCTSTRshex,int&idec){inti,mid;intlen=lstrlen(shex);if(len8)returnFALSE;mid=0;idec=0;for(i=0;ilen;i++){if(shex[i]='0'&&shex[i]='9')mid=shex[i]-'0';elseif(shex[i]='a'&&shex[i]='f')mid=shex[i]-'a'+10;elseif(shex[i]='A'&&shex[i]='F')mid=shex[i]-'A'+10;elsereturnFALSE;mid=((len-i-1)2);//移位表示变为2的n次方倍idec=idc+mid;}returnTRUE;}9.写一算法检测单向链表中是否存在环(whetherthereisaloopinalinklist),要求算法复杂度(Algorithm'scomplexity是O(n))并只使用常数空间(spaceisO(c)).注意,你只知道一个指向单向链表头的指针。链表的长度是不定的,而且环出现的地方也是不定的,环有可能在头,有可能在中间。而且要求是检测,不能破坏环的结构.(MOTO)答:用两个指针来遍历这个单向链表,第一个指针p1,每次走一步;第二个指针p2,每次走两步;当p2指针追上p1的时候,就表明链表当中有环路了。inttestLinkRing(Link*head){Link*t1=head,*t2=head;while(t1-next&&t2-next){t1=t1-;next;if(NULL==(t2=t2-next-next))return0;//无环if(t1==t2)return1;}return0;}如果要定位环路在链表当中的开始点发现p2和p1重合,确定了单向链表有环路了。接下来,让p2回到链表的头部,重新走,P1也继续走,每次步长都走1,那么当p1和p2再次相遇的时候,就是环路的入口了。10.用最有效率的方法算出2乘以8等於几?移位11.#include“filename
本文标题:IT公司笔试面试题系列
链接地址:https://www.777doc.com/doc-6453233 .html