有史以来最全的C&C++语言笔试面试题

更新时间:2024-05-03 22:42:01 阅读量: 综合文库 文档下载

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

C++笔试题

注意:以下题目的答案仅供参考

1.多态类中的虚函数表是Compile-Time,还是Run-Time时建立的?

答案:虚拟函数表是在编译期就建立了,各个虚拟函数这时被组织成了一个虚拟函数的入口地址的数组.而对象的隐藏成员--虚拟函数表指针是在运行期--也就是构造函数被调用时进行初始化的,这是实现多态的关键.

3.main主函数执行完毕后,是否可能会再执行一段代码?(朗讯的一道笔试题) 答案:可以,可以用_onexit 注册一个函数,它会在main 之后执行;

如果你需要加入一段在main退出后执行的代码,可以使用atexit()函数,注册一个函数。 语法:

#include

int atexit(void (*function\ #include #include

void fn1( void ), fn2( void ), fn3( void ), fn4( void ); int main( void ) {

atexit(fn1); atexit( fn2 ); atexit( fn3 ); atexit( fn4 );

printf( \ }

void fn1() {

printf( \ }

void fn2() {

printf( \ }

void fn3() {

printf( \ }

void fn4() {

printf( \ } 结果:

This is executed first.

This is executed next.

4.一个父类写了一个virtual 函数,如果子类覆盖它的函数不加virtual ,也能实现多态? 在子类的空间里,有没有父类的这个函数,或者父类的私有变量? (华为笔试题)

答案:只要基类在定义成员函数时已经声明了virtue关键字,在派生类实现的时候覆盖该函数时,virtue关键字可加可不加,不影响多态的实现。子类的空间里有父类的所有变量(static除外)。

5.给一个字符串、例如 “ababc”要求返回“ab”. 因为“ab”连续重复出现且最长。 用C/C++语言写一函数完成该算法,给出复杂度

6.对序列1、1、2、3、5、8、13。。。。 是Fab..数列

2、3、5、13...是Fab..质数数列,因为他们与自己前面的Fab...数列都互质 给出k,返回第k小的Fab..质数

7.101个硬币100真、1假,真假区别在于重量。请用无砝码天平称两次给出真币重还是假币 重的结论。

8.完成字符串拷贝可以使用 sprintf、strcpy 及 memcpy 函数,请问这些函数有什么区别 ,你喜欢使用哪个,为什么?

答案:这些函数的区别在于 实现功能 以及 操作对象 不同。

1.strcpy 函数操作的对象是 字符串,完成 从 源字符串 到 目的字符串 的 拷贝 功能。

2.snprintf 函数操作的对象不限于字符串:虽然目的对象是字符串,但是源对象可以是字符串、也可以是任意基本类型的数据。这个函数主要用来实现(字符串或基本数据类型)向字符串的转换功能。如果源对象是字符串,并且指定 %s 格式符,也可实现字符串拷贝功能。

3.memcpy 函数顾名思义就是 内存拷贝,实现 将一个 内存块 的内容复制到另一个 内存块 这一功能。内存块由其首地址以及长度确定。程序中出现的实体对象,不论是什么类型,其最终表现就是在内存中占据一席之地(一个内存区间或块)。因此,memcpy 的操作对象不局限于某一类数据类型,或者说可 适用于任意数据类型,只要能给出对象的起始地址和内存长度信息、并且对象具有可操作性即可。鉴于 memcpy 函数等长拷贝的特点以及数据类型代表的物理意义,memcpy 函数通常限于同种类型数据或对象之间的拷贝,其中当然也包括字符串拷贝以及基本数据类型的拷贝。

对于字符串拷贝来说,用上述三个函数都可以实现,但是其实现的效率和使用的方便程度不同: strcpy 无疑是最合适的选择:效率高且调用方便。

snprintf 要额外指定格式符并且进行格式转化,麻烦且效率不高。

memcpy 虽然高效,但是需要额外提供拷贝的内存长度这一参数,易错且使用不便;并且如果长度指定过大的话(最优长度是源字符串长度 + 1),还会带来性能的下降。其实 strcpy 函数一般是在内部调用 memcpy 函数或者用汇编直接实现的,以达到高效的目的。因此,使用 memcpy 和 strcpy 拷贝字符串在性能上应该没有什么大的差别。

对于非字符串类型的数据的复制来说,strcpy 和 snprintf 一般就无能为力了,可是对 memcpy 却没有什么影响。但是,对于基本数据类型来说,尽管可以用 memcpy 进行拷贝,由于有赋值运算符可以方便且高效地进行同种或兼容类型的数据之间的拷贝,所以这种情况下 memcpy 几乎不被使用。memcpy 的长处是用来实现(通常是内部实现居多)对结构或者数组的拷贝,其目的是或者高效,或者使用方便,甚或两者兼有。 9.变量的声明和定义有什么区别?

10.请写出下面代码在 32 位平台上的运行结果,并说明 sizeof 的性质:

#include #include int main(void) {

char a[30];

char *b = (char *)malloc(20 * sizeof(char)); printf(\ printf(\ printf(\ printf(\ printf(\ return 0 ; }

12.请完成以下题目。注意,请勿直接调用 ANSI C 函数库中的函数实现。

a)请编写一个 C 函数,该函数给出一个字节中被置 1 的位的个数,并请给出该题的至少一个不同解法。

第一种unsigned int TestAsOne0(char log) {

int i;

unsigned int num=0, val; for(i=0; i<8; i++) {

val = log >> i; //移位 val &= 0x01; //与1相与 if(val)

num++; }

return num; }

第二种unsigned int TestAsOne1(char log) {

int i;

unsigned int num=0, val; for(i=0; i<8; i++) {

val = (~log) >> i; //反码? val &= 0x00; //与0相与 if(!val)

num++; }

return num; }

b)请编写一个 C 函数,该函数将给定的一个字符串转换成整数。 int Invert(char *str) {

int num=0; while(*str!='\\0') {

int digital=*str-48; num=num*10+digital; str=str+1; }

return num; }

c)请编写一个 C 函数,该函数将给定的一个整数转换成字符串。 void IntToCharChange(int num, char* pval) {

char strval[100]; int i, j;

int val0 = 0; int val1 = 0;

val0 = num; for(i=0; i<100; i++) {

val1 = val0 % 10; //取余 val0 = val0 / 10; //取整

strval[i] = val1 + 48; //数字—字符 if(val0 < 10) { i++;

strval[i] = val0 + 48; break; } }

for(j=0; j<=i; j++) //倒置 {

pval[j] = strval[i-j]; }

pval[j] = '\\0'; }

d)请编写一个 C 函数,该函数将一个字符串逆序。 void AntitoneValue(char* father, char* child) {

int i;

char source[100]; int j = 0;

while(father[j]) //放入source,[j]为长度 {

source[j] = father[j]; j++;

if(j > 99) {

return; } }

source[j] = '\\0';

for(i=0; i

child[i] = source[j-i-1]; //反序 }

child[i] = '\\0'; }

e)请编写一个 C 函数,该函数在给定的内存区域搜索给定的字符,并返回该字符所在位置索引值。 int search(char *cpSource, int n, char ch) //起始地址,搜索长度,目标字符 { int i;

for(i=0; i

f)请编写一个 C 函数,该函数在一个字符串中找到可能的最长的子字符串,该字符串是由同一字符组成的。

int ChildString(char*p) //自己写 {

Char *q=p;

int stringlen=0, i=0,j=1,len=0,maxlen=1;

while(*q!=‘\\0‘) //不能用strlen,求得长度stringlen {

Stringlen++; q++; }

while( i< Stringlen ) { if(*(p+i)==*(p+j)&&j< Stringlen) { len++; //统计子串长度 i++; j++; } else { if(len>maxlen) //统计最大子串长度

{ maxlen=len+1; len=0; } else { len=0; } i++; j++; } }

return maxlen; }

给出演示上述函数功能的一个简单程序,并请编写对应的 Makefile 文件

13.我们需要编写一个图形相关的应用程序,需要处理大量图形(Shape)信息,图形有矩形(Rectangle),正方形(Square),圆形 (Circle)等种类,应用需要计算这些图形的面积,并且可能需要在某个设备上进行显示(使用在标准输出上打印信息的方式做为示意)。

a)请用面向对象的方法对以上应用进行设计,编写可能需要的类 b)请给出实现以上应用功能的示例性代码,从某处获取图形信息, 并且进行计算和绘制

c)如果你的Square继承自Rectangle,请给出理由,如果不是, 请给出理由,并且请比较两种方式的优劣

d)请问你所编写的类,在如下代码中会有何表现,请解释 void test_rectangle_area(Rectangle& r) {

r.set_width(10); r.set_height(15);

assert(r.area() == 150); }

14.假设现有一个单向的链表,但是只知道只有一个指向该节点的指针p,并且假设这个节 点不是尾节点,试编程实现删除此节点

参考:将下一个节点的内容复制到本节点上,然后删除下一个节点;

15.写一个程序,把一个100以内的自然数分解因数。(自然数分解因数就是将一个自然数 分解为几个素数的乘积,提示,由于该数不是很大,所以可以将质数保存在数组中,以加快计 算速度)

16.编写一个Identify的分配、释放的函数,为1-10000之间的自然数。 17.分别实现itoa和atoi.

18.Consider the following code: #include

#include

int main(int argc, char *argv[]) { int i = 1; char buf[4];

strcpy(buf, \printf(\return 0; }

a) When compiled and executed on x86, why does this program usually not output what the programmer intended? 在x86上为什么不能得到预期结果

b) Name several ways in which the security problem that causes this program not to output what the programmer intended can be prevented WITHOUT changing the code.

参考:第一个问题: 32位情况:

x86下,栈方向向上生长.在main的栈中,先分配i空间(4byte),然后分配4个字节的buf(地址在i的上面,比i小).strcpy越界,用0把buf开始的第4(0开始)个字节覆盖掉了.而x86是LSB排列顺序,所以真好覆盖了i的内个数字1.所以显示出数字0. 16位情况同样分析即可. 第2问?

19.int w=1,x=2,y=3,z=4; m=(w

printf(\ 说出结果 答案:1

20.说出结果 ??? #include main() {

FILE *fp;

int i,a[4]={1,2,3,4},b;

fp=fopen(\这里帮忙解释一下 for(i=0;i<4;i++)

fwrite(&a[i],sizeof(int),1,fp);//这里也帮忙看一下 fclose(fp);

fp=fopen(\

fseek(fp,-2L*sizeof(int),SEEK_END);//还有这里 fread(&b,sizeof(int),1,fp);//这里还有也看一下 fclose(fp);

printf(\

}

21.有双向循环链表结点:(华为面试题) typedef struct node {

int date;

struct node *front,*next; }_Node;

有两个双向循环链表A,B,知道其头指针为:pHeadA,pHeadB,请写一函数将两上链表中date值相同的结点删除 参考算法:

1.取出A的一个元素d

2.收集B中有相同元素d的结点到垃圾箱,并从B里删除 3.收集A中有相同元素d的结点到垃圾箱,并从A里删除 4.删除垃圾箱中的所有元素 5.A链的指针指向下一个

6.重复1~5,直到A链循环到头了

注意的是第3步,在2步执行后垃圾箱不为空时才执行。 上述算法还可以做一点点优化:

1.加入两个变量cA, cB,分别记录当前A中和B中的元素个数 每次从较长者中取出一个元素来,先从较小者中找起 若没有,则不必在较长者中浪费时间了 #include ? struct NODE {

int date;

NODE *front,*next; };

void redel(NODE *&ahead,NODE *&bhead) {

int boy=0;

NODE *pa=ahead,*pb=bhead,*paa,*paaa,*paaaa,*pbb; while(pa->next!=ahead) {

int boys=pa->date; //取pa中一个值 paaaa=pa; paa=pa; pb=bhead;

while(pb->next!=bhead) {

if(boys==pb->date) //如果pa,pb中有值相同 {

cout<

cout<<\ B:\ \ if(pb==bhead) {

boy=1;

pb->front->next=pb->next; pb->next->front=pb->front; bhead=bhead->next; pbb=pb;

pb=pb->next; delete pbb; } else {

boy=1;

pb->front->next=pb->next; pb->next->front=pb->front; pbb=pb;

pb=pb->next; delete pbb; } } else

pb=pb->next; }

while(paa->next!=ahead && boy==1) {

if(paa->date==boys) {

cout<<\ A:\ if(paa==pa) {

pa=pa->next; ahead=pa;

paa->front->next=paa->next; paa->next->front=paa->front; paaa=paa;

paa=paa->next; delete paaa; } else {

paa->front->next=paa->next; paa->next->front=paa->front; paaa=paa;

paa=paa->next; delete paaa; } }

\

else {

paa=paa->next; } }

boy=0;

if(paaaa==pa)

pa=pa->next; }

cout<

int main() {

NODE *A,*pHeadA,*B,*pHeadB; A=new NODE; B=new NODE; pHeadA=A; pHeadB=B;

for(int i=1;i<21;++i) //生成链表A,并赋初值! {

A->date=i;

A->next=new NODE; A->next->front=A; A=A->next; }

A=A->front;

delete A->next; A->next=pHeadA; pHeadA->front=A;

for(int i=1;i<33;i+=2) //生成链表B,并赋初值! {

B->date=i;

B->next=new NODE; B->next->front=B; B=B->next; }

B=B->front;

delete B->next; B->next=pHeadB; pHeadB->front=B;

redel(pHeadA,pHeadB); //调用函数删除相同结点! }

{ extern int *a;

printf (\ return 0; }

1 #include “filename.h”和#include 的区别?

对于#include 编译器从标准库开始搜索filename.h;对于#include ―filename.h‖编译器从用户工作路径开始搜索filename.h

2 头文件的作用是什么?

一、通过头文件来调用库功能。在很多场合,源代码不便(或不准)向用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。编译器会从库中提取相应的代码。

二、头文件能加强类型安全检查。如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则能大大减轻程序员调试、改错的负担。

3 C++函数中值的传递方式有哪几种?

C++函数的三种传递方式为:值传递、指针传递和引用传递。

4 内存的分配方式的分配方式有几种?

答:一、从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量。

二、在栈上创建。在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

三、从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由我们决定,使用非常灵活,但问题也最多。

5 实现双向链表删除一个节点P,在节点P后插入一个节点,写出这两个函数; //删除操作

Status ListDelete_DuL(DuLinkList &L,int i,ElemType &e) {

if(!(p=GetElemP_DuL(L,i))) //此处得到i位置的节点指针,如果有需要也得写出具体函数实现 return ERROR; e=p->data;

p->prior->next=p->next; p->next->prior=p->pror; free(p); return OK; }

//插入操作

Status ListInsert_DuL(DuLinkList &L,int i,ElemType &e) {

if(!(p=GetElemP_DuL(L,i)))

return ERROR;

if(!(s=(DuLinkList)malloc(sizeof(DuLNode)))) //生成新节点 return ERROR;

s->data=e; s->prior=p;

p-> next -> prior =s; p->next=s;

s->next=p->next->next; return OK; }

6 写一个函数,将其中的\\t都转换成4个空格。

7 Windows程序的入口是哪里?写出Windows消息机制的流程.

8 如何定义和实现一个类的成员函数为回调函数?

9 C++里面是不是所有的动作都是main()引起的?如果不是,请举例. 比如全局变量的初始化,就不是由main函数引起的 举例: class A{};

A a; //a的构造函数限执行 int main() {}

10 C++里面如何声明const void f(void)函数为C程序中的库函数(华为)

11 下列哪两个是等同的 int b;

A const int* a = &b; B const* int a = &b;

C const int* const a = &b; D int const* const a = &b;

12 内联函数在编译时是否做参数类型检查

内联函数要做参数类型检查, 这是内联函数跟宏相比的优势

13 三个float:a,b,c

问值 (a+b)+c==(b+a)+c (a+b)+c==(a+c)+b

两者都不行。在比较float或double时,不能简单地比较。由于计算误差,相等的概率很低。应判断两数之差是否落在区间(-e,e)内。这个e应比浮点数的精度大一个数量级。

14 把一个链表反向 填空 (lucent) <<<

test* pe = head;

test* ps = head->next; while(ps) {

pe->next = ps->next; ps->next = head; head = ps; ps = pe->next; } }

从第一个元素开始,ps指向他,将他(ps)指向头节点(ps->next = head),将ps设为头节点(head = ps;)操作下一个元素(ps = pe->next;)等于是依次将每个元素翻到原头节点前面。

15 设计一个重采样系统,说明如何anti-alias

16 某个程序在一个嵌入式系统(200M的CPU,50M的SDRAM)中已经最化了,换到另一个系统( 300M的CPU,50M的SDRAM)中运行,还需要优化吗?

17. 下面哪种排序法对12354最快 a quick sort b.buble sort c.merge sort

18. 哪种结构,平均来讲,获取一个值最快 a. binary tree b. hash table c. stack

19 请问C++的类和C里面的struct有什么区别?

class中默认的成员访问权限是private的,而struct中则是public的

20 请讲一讲析构函数和虚函数的用法和作用?

析构函数是特殊的类成员函数,它没有返回类型,没有参数,不能随意调用,也没有重载,只有在类对象的生命期结束的时候,由系统自动调用。 有适放内存空间的做用。

虚函数是C++多态的一种表现, 使用虚函数,我们可以灵活的进行动态绑定,当然是以一定的开销为代价。

21 全局变量和局部变量有什么区别?实怎么实现的?操作系统和编译器是怎么知道的? 生命周期不同:全局变量随主程序创建和创建,随主程序销毁而销毁

局部变量在局部函数内部,甚至局部循环体等内部存在,退出就不存在; 内存中分配在全局数据区 使用方式不同:通过声明后全局变量程序的各个部分都可以用到 局部变量只能在局部使用;分配在栈区

操作系统和编译器通过内存分配的位置来知道的,全局变量分配在全局数据段并且在程序开始运行的时候被加载。局部变量则分配在堆栈里面 。

22 一些寄存器的题目,主要是寻址和内存管理等一些知识。

23 8086是多少位的系统?在数据总线上是怎么实现的?

24 多态。overload 和 override的区别。

overload是重载,重载是一种参数多态机制,即代码通过参数的类型或个数不同而实现的多态机制。 是一种静态的绑定机制(在编译时已经知道具体执行的是哪个代码段)。

override是覆盖。覆盖是一种动态绑定的多态机制。即在父类和子类中同名元素(如成员函数)有不同的实现代码。执行的是哪个代码是根据运行时实际情况而定的。

重载Overload特点

public bool withdraw(double amt, string name) public double withdraw(double amt)

1、方法名必须相同2、参数列表必须不相同3、返回值类型可以不相同 注意:override存在于继继承的关系类中。 覆写Override特点(三相同): public override bool withdraw(...)

1、方法名相同2、参数列表相同3、返回值类型相同

注意:存在于同一类中,但是只有虚方法和抽象方法才能被覆写.

<> 25.完成下列程序 * *.*. *..*..*.. *...*...*...*...

*....*....*....*....*....

*.....*.....*.....*.....*.....*.....

*......*......*......*......*......*......*......

*.......*.......*.......*.......*.......*.......*.......*....... #include #define N 8 int main() { int i; int j; int k;

---------------------------------------------------------

| |

| |

| |

---------------------------------------------------------

return 0; }

26 完成程序,实现对数组的降序排序 #include

void sort( ); int main() {

int array[]={45,56,76,234,1,34,23,2,3}; //数字任//意给出 sort( ); return 0; }

void sort( )

{ ____________________________________

| |

| |

|-----------------------------------------------------| }

27 费波那其数列,1,1,2,3,5……编写程序求第十项。可以用递归,也可以用其他方 法,但要说明你选择的理由。 #include int Pheponatch(int); int main()

{ printf(\ return 0; }

int Pheponatch(int N) {

-------------------------------- | |

| | -------------------------------- }

28 下列程序运行时会崩溃,请找出错误并改正,并且说明原因。 #include #include typedef struct{ TNode* left;

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

Top