2020年度C软件工程师笔试题_第1页
2020年度C软件工程师笔试题_第2页
2020年度C软件工程师笔试题_第3页
2020年度C软件工程师笔试题_第4页
2020年度C软件工程师笔试题_第5页
已阅读5页,还剩42页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C软件工程师笔试题

资料仅供参考

一、请填写BOOL,float,指针变量与“零值”

比较的if语句。(10分)

提示:这里“零值”能够是0,0.0,FALSE或

者“空指针”。例如int变量n与“零值”比

较的if语句为:if(n==0)if(n!=

0)

以此类推。请写出BOOLflag与“零值”比较

的if语句:

标准答案:if(flag)

if(!flag)

如下写法均属不良风格,不得分。

if(flag==TRUE)if(flag==1)if(flag

=FALSE)if(flag=0)

请写出floatx与“零值”比较的if语句:

标准答案示例:

constfloatEPSINON=0.00001;

if((x>=-EPSINON)&&(x<=EPSINON)不

可将浮点变量用〜'或“!二”与数字比较,应

该设法转化成“〉二"或“<二”此类形式。如下是

错误的写法,不得分。

资料仅供参考

if(x==0.0)if(x!=0.0)

请写出char*p与“零值”比较的if语句:

标准答案:

if(p=NULL)

if(p!=NULL)

如下写法均属不良风格,不得分。

if(p==0)if(p!=0)if(p)if(!)

二、以下为WindowsNT下的32位C++程序,请

计算sizeof的值(10分)

charstr[]="Hello”;char*p=str;

intn=10;

sizeof(str)=6sizeof(p)=4

sizeof(n)=4

voidFunc(charstr[100])

{请计算sizeof(str)=4}

void*p=malloc(100);

请计算sizeof(p)=4

三、简答题(25分)

1、头文件中的ifndef/define/endif干什么用?

防止该头文件被重复引用

2>ttinclude<filename.h>和^include

“filename,h”有什么区别?

资料仅供参考

答:对于#include<filename.h>,编译器

从标准库路径开始搜索filename.h

对于#include“filename,h”,

编译器从用户的工作路径开始搜索filename.h

3、const有什么用途?(请至少说明两种)

答:(1)能够定义const常量

(2)const能够修饰函数的参数、返回值,甚至

函数的定义体。被const修饰的东西都受到强制

保护,能够预防意外的变动,能提高程序的健壮

性。

4、在C++程序中调用被C编译器编译后的函

数,为什么要加extern"C”声明?

答:C++语言支持函数重载,C语言不支持函数重

载。函数被C++编译后在库中的名字与C语言的

不同。假设某个函数的原型为:voidfoo(int

x,inty);

该函数被C编译器编译后在库中的名字为_foo,

而C++编译器则会产生像_foo_int_int之类的

名字。

C++提供了C连接交换指定符号extern“C”来

解决名字匹配问题。

5、请简述以下两个for循环的优缺点

资料仅供参考

for(i=0;i<N;i++)

{if(condition)

DoSomething();

elseDoOtherthing();

)

//第二个

if(condition){

for(i=0;i<N;i++)

DoSomething();}

else{for(i=0;i<N;i++)

DoOtherthing();}优点:程序简洁

缺点:多执行了N-1次逻辑判断,而且打断了循

环“流水线”作业,使得编译器不能对循环进行

优化处理,降低了效率。优点:循环的效率高

缺点:程序不简洁

四、有关内存的思考题(20分)

voidGetMemory(char*p)

{p=(char*)malloc(100);

)

voidTest(void)

{char*str=NULL;

GetMemory(str);

资料仅供参考

strcpy(str,"helloworld");

printf(str);}

请问运行Test函数会有什么样的结果?

答:程序崩溃,getmemory中的malloc不能返

回动态内存,free()对str操作很危险博

主:getmemory中p是形参,是一个指针变量,

getmemory(str)调用后,传入的是指针变量保存

的对象地址,p=(char*)malloc(lOO)实际上是

把申请的动态内存空间的首地址付给P指向的

地址(即str指向的地址null),这个是错误的。

应该修改成指向指针的指针void

getmemory(char**p),这样malloc返回的地址

付给*p(即str变量本身)。

char*GetMemory(void)

{charp[]="helloworld”;

returnp;}

voidTest(void){char*str=NULL;

str=GetMemory();

printf(str);)

请问运行Test函数会有什么样的结果?

答:可能是乱码。

因为GetMemory返回的是指向“栈内存”的指针,

资料仅供参考

该指针的地址不是NULL,但其原现的内容已经

被清除,新内容不可知。

RetMenory执行完毕,p资源被回收,指向未知

地址。返回地址,str的内容应是不可预测的,

打印的应该是str的地址

VoidGetMemory2(char**p,intnum)

{p=(char*)malloc(num);

}voidTest(void)

{char*str=NULL;

GetMemory(&str,100);

strcpy(str,"hello");

printf(str);)

请问运行Test函数会有什么样的结果?

答:(1)能够输出hello

(2)内存泄漏

voidTest(void){char*str=(char*)

malloc(lOO);

strcpy(str,"hello");

free(str);

if(str!=NULL)

{strcpy(str,"world");

printf(str);}}

资料仅供参考

请问运行Test函数会有什么样的结果?

答:篡改动态内存区的内容,后果难以预料,非

常危险。

因为free(str);之后,str成为野指针,

if(str!=NULL)语句不起作用。

五、已知strcpy函数的原型是char

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

其中strDest是目的字符串,strSrc是源

字符串。

(1)不调用C++/C的字符串库函数,请编写函

数strcpy

答:char*my_strcpy(char*strdest,const

char*strsrc)

(

assert(strdest

!=NULL)&&(strsrc!=NULL))

char*address

=strdest;

while((*strdes

t++=*strsrc++)!=NULL)

return

address;

资料仅供参考

(2)strcpy能把strSrc的内容复制到strDest,

为什么还要char*类型的返回值?

答:为了实现链式表示式。〃2分

例如intlength=strlen(strcpy(strDest,

“helloworld"));

六、编写类String的构造函数、析构函数和赋

值函数(25分)

已知类String的原型为:

classString

{public:

String(constchar*str=NULL);//普

通构造函数

String(constString&other);//拷贝

构造函数

~String(void);//析构函数

String&operate=(constString

&other);//赋值函数

private:

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

);

请编写String的上述4个函数。

资料仅供参考

〃普通构造函数

String::String(constchar*str)

(

if(str==NULL)

(

m_data=new

char[l];//得分点:对空字符串自动申请存放

结束标志'\0'的空

〃加分点:对m_data加NULL判断

*m_data=

,\0,;

)

else

(

intlength=strlen(str);

m_data=newchar[length+1];

//若能加NULL判断则更好

strcpy(m_data,str);

资料仅供参考

//String的析构函数

String::^String(void)

(

delete[]m_data;//或

deletem_data;

)

〃拷贝构造函数

String::String(constString&other)

//得分点:输入参数为const型

(

intlength=

strlen(other.m_data);

m_data=newchar[length+1];

〃加分点:对m_data加NULL判断

strcpy(m_data,

other.m_data);

〃赋值函数

String&String::operate=(constString

&other)//得分点:输入参数为const型

资料仅供参考

if(this==

&other)

〃得分点:检查自赋值

return

*this;

delete[]

m_data;〃得

分点:释放原有的内存资源

intlength=

strlen(other.m_data);

m_data=newchar[length+1];

〃加分点:对m_data加NULL判断

strcpy(m_data,

other.m_data);

return

*this;〃得分点:返

回本对象的引用

)

编写一个函数,要求输入年月日时分秒,输出该

年月日时分秒的下一秒。如输入12月31日23

时59分59秒,则输出1月1日0时0分0秒。

voidResetTheTime(int*year,int

资料仅供参考

*month,int*date,int*hour,int

*minute,int*second)

(

int

dayOfMonth[12]={31,28,31,30,31,30,31,31,3

0,31,30,31);

if(*year<0||*month<1||

*month>12||

*date<1||*date>31

||*hour<0||*hour>23||

*minute<0||*minute>59||

"second<0||"second>60)

return;

if(*year%400==0||*year%100!=

0&&*year%4==0)

dayOfMonth[l]=29;

if("second>=60)

(

"second=0;

*minute+=1;

if(*minute>=60)

资料仅供参考

*minute=0;

*hour+=1;

if(*hour>=24)

(

*hour=0;

*date+=1;

if(*date>

dayOfMonth[*month-l])

(

*date

=1;

*month

+二1;

if(*mo

nth>12)

(

*month=l;

*year+=1;

资料仅供参考

return;

1.全局变量和局部变量在内存中是否有区别?

如果有,是什么区别?

全局变量储存在静态数据库,局部变量在堆栈

2.static有什么用途?(请至少说明两种)

1.限制变量的作用域2.设置变量的存储域

不能做switch。的参数类型是:

switch的参数不能为实型。

如何引用一个已经定义过的全局变量?

答:extern

能够用引用头文件的方式,也能够用extern关

键字,如果用引用头文件方式来引用某个在头文

件中声明的全局变理,假定你将那个变写错了,

那么在编译期间会报错,如果你用extern方式

引用时,假定你犯了同样的错误,那么在编译期

间不会报错,而在连接期间报错

资料仅供参考

全局变量可不能够定义在可被多个.c文件包含

的头文件中?为什么?

答:能够,在不同的C文件中以static形式来

声明同名全局变量。

能够在不同的C文件中声明同名的全局变量,前

提是其中只能有一个C文件中对此变量赋初值,

此时连接不会出错

char*ss="〃;

sizeof(ss)结果4===》ss是指向字符串

常量的字符指针,sizeof获得的是一个指针的

之所占的空间,应该是长整型的,因此是4

sizeof(*ss)结果1===》*ss是第一个字

符其实就是获得了字符串的第一位'0'所占的

内存空间,是char类型的,占了1位

请找出下面代码中的因此错误

说明:以下代码是把一个字符串倒序,如“abed”

倒序后变为“deba”

1、#include"string.h"

2、main()

3、{

4、char*src="hello,world";

5、char*dest=NULL;

资料仅供参考

6、intlen=strlen(src);

7、dest=(char*)malloc(len);

8、char*d=dest;

9、char*s=src[len];

10、while(len-!=0)

11、d++=s一;

12、printf("%s”,dest);

13、return0;

14、}

答:

方法L

intmain(){

char*src="hello,world";

intlen=strlen(src);

char*dest=(char*)manoc(len+1);〃要为

\0分配一个空间

char*d=dest;

char*s=&src[len-1];〃指向最后一个字符

while(len一!=0)

*d++=*s——;

*d='\0';〃尾部要加\0

printf("%s\n",dest);

资料仅供参考

free(dest);//使用完,应当释放空间,以免造

成内存汇泄露

return0;

)

方法2:

ttinclude<stdio.h>

ttinclude<string.h>

main()

(

charstr口="hello,world";

intlen=strlen(str);

chart;

for(inti=0;i<len/2;i++)

{

t=str[i];

str[i]=str[len-i-1];str[len-i-l]=t;

)

printfstr);

return0;

资料仅供参考

.用两个栈实现一个队列的功能?要求给出算法

和思路!

设2个栈为A,B,一开始均为空.

入队:

将新元素push入栈A;

出队:

⑴判断栈B是否为空;

(2)如果不为空,则将栈A中所有元素依次pop

出并push到栈B;

(3)将栈B的栈顶元素pop出;

char*constp;〃常量指针,p的值不能够修

charconst*p;〃指向常量的指针,指向的常

量值不能够改

constchar*p;〃和charconst*p

main()

{

inta[5]={l,2,3,4,5};

int*ptr=(int*)(&a+l);

printf("%d,%d”,*(a+1),*(ptr-l));

资料仅供参考

}输出:2,5

*(a+l)就是a[l],*(ptrT)就是a[4],执行结

果是2,5

&a+l不是首地址+L系统会认为加一个a数组

的偏移,是偏移了一个数组的大小(本例是5个

int)

int*ptr=(int*)(&a+l);则ptr实际是

&(a[5]),也就是a+5

原因如下:&a是数组指针,其类型为int(*)[5];

而指针加1要根据指针类型加上一定的值,

不同类型的指针+1之后增加的大小不同

a是长度为5的int数组指针,因此要加

5*sizeof(int)

因此ptr实际是a[5]

可是prt与(&a+l)类型是不一样的(这点很重要)

因此prtT只会减去sizeof(int*)

a,&a的地址是一样的,但意思不一样,a是数组

首地址,也就是a[0]的地址,&a是对象(数组)

首地址,a+1是数组下一元素的地址,即

a[l],&a+l是下一个对象的地址,即a[5].

char*s="AAA";

资料仅供参考

printfs);

s[0]=,B';

printf(级s”,s);

有什么错?

〃AAA〃是字符串常量。s是指针,指向这个字符串

常量,因此声明s的时候就有问题。

cosntchar*s="AAA";

然后又因为是常量,因此对是s[0]的赋值操作

是不合法的。

int(*s[10])(int)函数指针数组,每个指针指

向一个intfunc(intparam)的函数。

.交换两个变量的值,不使用第三个变量。即

a=3,b=5,交换之后a=5,b=3;

有两种解法,一种用算术算法,一种用X异或)

a=a+b;b=a-b;a=a-b;

ora=a'b;〃只能对int,char..

b=a"b;

a=a%;

3.c和c++中的struct有什么不同?

c和c++中struct的主要区别是c中的struct

不能够含有成员函数,而c++中的struct能够。

资料仅供参考

c++中struct和class的主要区别在于默认的

存取权限不同,struct默认为public,而class

默认为private

1:(void*)ptr和(*(void**))ptr的结果是

否相同?其中ptr为同一个指针

.(void*)ptr和(*(void**))ptr值是相同的

改错:

intmain(void){

int**p;

intarr[100];

p=&arr;

return0;}

解答:

搞错了,是指针类型不同,

int**p;〃二级指针

&arr;〃得到的是指向第一维为100的数组的

指针

^include<stdio.h>

intmain(void){

int**p,*q;

资料仅供参考

intarr[100];

q=arr;

P=&q;

return0;

)

下面这个程序执行后会有什么错误或者效果:

ftdefineMAX255

intmain()

{unsignedcharA[MAX],i;//i被定义为

unsignedchar

for(i=0;i<=MAX;i++)

A[i]=i;

}解答:死循环加数组越界访问(C/C++不进行数

组越界检查)

MAX=255数组A的下标范围为:0..MAX-1,这是其

一..其二.当i循环到255时,循环内执行:

A[255]=255;这句本身没有问题..可是返回for

(i=0;i<=MAX;i++)语句时,

由于unsignedchar的取值范围在(0..255),i++

以后i又为0了..无限循环下去.

资料仅供参考

设编号为L2,-n的n个人围坐一圈,约定

编号为k(l<=k<=n)的人从1开始报数,数到m

的那个人出列,它的下一位又从1开始报数,数

到m的那个人又出列,依次类推,直到所有人出

列为止,由此产生一个出队编号的序列。

数组实现:

#include<stdio.h>

#include<malloc.h>

intJosephu(intn,intm)

(

intflag,i,j=0;

int*arr=(int*)malloc(n*sizeof(int));

for(i=0;i<n;++i)

arr[i]=1;

for(i=1;i<n;++i)

{

flag=0;

while(flag<m)

if(j=n)

资料仅供参考

if(arr[j])

++flag;

++j;

)

arr[j-1]=0;

printf("第%4d个出局的人是:%4d号\n”,i,

j);

)

free(arr);

returnj;

)

intmain()

{

intn,m;

scanf("%d%d”,&n,&m);

printf("最后胜利的是%d号!\n",Josephu(n,

m));

system("pause");

return0;

}

链表实现:

ttinclude<stdio.h>

资料仅供参考

#include<malloc.h>

typedefstructNode

(

intindex;

structNode*next;

}JosephuNode;

intJosephu(intn,intm)

(

inti,j;

JosephuNode*head,*tail;

head=tail=(JosephuNode

*)malloc(sizeof(JosephuNode))

for(i=1;i<n;++i)

|

tail->index=i;

tail->next=(JosephuNode

*)malloc(sizeof(JosephuNode))

tail=tail->next;

)

tail->index=i;

tail->next=head;

资料仅供参考

for(i=1;tail!=head;++i)

(

for(j=1;j<m;++j)

(

tail=head;

head=head->next;

)

tail->next=head->next;

printf("第%4d个出局的人是:%4d号\n”,i,

head->index);

free(head);

head=tail->next;

)

i=head->index;

free(head);

returni;

)

intmain()

intn,m;

scanf("%d%d”,&n,&m);

printf("最后胜利的是%d号!\n",Josephu(n,

资料仅供参考

m));

system("pause");

return0;

斐波拉契数列递归实现的方法如下:

intFunct(intn)

(

if(n==0)return1;

if(n==l)return1;

retrurnFunct(n-l)+Funct(n-2);

)

请问,如何不使用递归,来实现上述函数?

请教各位高手!

解答:intFunct(intn)//n为非负整数

(

inta=0;

intb=l;

intc;

if(n==0)c=l;

elseif(n=l)c=l;

elsefor(inti=2;i<=n;i++)//应该n从2开

资料仅供参考

始算起

(

c=a+b;

a=b;

b=c;

)

returnc;

)

在对齐为4的情况下

structBBB

(

longnum;

char*name;

shortintdata;

charha;

shortba[5];

}*P;

p=0x1000000;

p+0x200=;

(Ulong)p+0x200=;

(char*)p+0x200=;

希望各位达人给出答案和原因,谢谢拉

资料仅供参考

解答:假设在32位CPU上,

sizeof(long)=4bytes

sizeof(char*)=4bytes

sizeof(shortint)=sizeof(short)=2

bytes

sizeof(char)=1bytes

由于是4字节对齐,

sizeof(structBBB)=sizeof(*p)

=4+4+2+l+1/*补齐*/+2*5+2/*补

齐*/=24bytes(经Dev-C++验证)

p=0xl000000;

p+0x200=;

=0x1000000+0x200*24

(Ulong)p+0x200=;

=0x1000000+0x200

(char*)p+0x200=;

=0x1000000+0x200*4

资料仅供参考

写一个函数,它的原形是intcontinumax(char

*outputstr,char*intputstr)

功能:

在字符串中找出连续最长的数字串,并把这个串

的长度返回,并把这个最长数字串付给其中一个

函数参数outputstr所指内存。例如:

“abcdl2345edl25ss”的首地址传给intputstr

后,函数将返回

9,outputstr所指的值为

intcontinumax(char*outputstr,char

*inputstr)

(

char*in=inputstr,*out=outputstr,

*temp,*final;

intcount=0,maxlen=0;

while(*in!='\0')

|

if(*in>47&&*in<58)

(

for(temp=in;*in>47&&*in<58;in++)

count++;

资料仅供参考

)

else

in++;

if(maxlen<count)

(

maxlen=count;

count=0;

final=temp;

)

)

for(inti=0;i<maxlen;i++)

{

*out=*final;

out++;

final++;

)

*out='\0';

returnmaxlen;

不用库函数,用C语言实现将一整型数字转化为

资料仅供参考

字符串

方法1:

intgetlen(char*s){

intn;

for(n=0;*s!='\0';s++)

n++;

returnn;

)

voidreverse(chars[])

(

intc,i,j;

for(i=0,j=getlen(s)-1;i<j;i++,j-

一){

c=s[i];

s[i]=s[j];

s[j]=c;

)

)

voiditoa(intn,chars[])

(

inti,sign;

if((sign=n)<0)

资料仅供参考

n=-n;

i=0;

do{/*以反序生成数字*/

s[i++]=n%10+'O';/*getnextnumber*/

}while((n/=10)>0);/"deletethe

number*/

if(sign<0)

s[i++]=,」;

s[i]=,\0,;

reverse(s);

)

方法2:

#include<iostream>

usingnamespacestd;

voiditochar(intnum);

voiditochar(intnum)

inti=0;

资料仅供参考

intj;

charstra[10];

charstrb[10];

while(num)

(

stra[i++]=num%10+48;

num=num/10;

)

stra[i]='\0';

for(j=0;j<i;j++)

(

strb[j]=stra[i-j-l];

)

strb[j]='\0';

cout«strb«endl;

)

intmain()

{

intnum;

cin»num;

itochar(num);

资料仅供参考

return0;

用指针的方法,将字符串“ABCD1234efgh”前后

对调显示

^include<stdio.h>

ttinclude<string.h>

#include<dos.h>

intmain()

(

charstr[]="ABCD1234efgh”;

intlength=strlen(str);

char*pl=str;

char*p2=str+length-1;

while(pl<p2)

(

charc=*pl;

*pl=*p2;

*p2=c;

++pl;

一p2;

资料仅供参考

printf(^strnowis%s\n”,str);

system("pause");

return0;

)

有一个数组a[1000]存放0—1000;要求每隔二

个数删掉一个数,到末尾时循环至开头继续进行,

求最后一个被删掉的数的原始下标位置。

方法2:链表

#include<iostream>

usingnamespacestd;

ttdefinenull0

structnode

|

intdata;

node*next;

};

intmain()

{

node*head=newnode;

head->data=0;

head->next=null;

资料仅供参考

node*p=head;

for(inti=l;i<1000;i++)

(

node*tmp=newnode;

tmp->data=i;

tmp->next=null;

head->next=tmp;

head=head->next;

)

head->next=p;

while(p!=p->next)

(

p->next->next=p->next->next->next;

p=p->next->next;

)

cout«p->data;

return0;

)

试题:

voidtest2()

资料仅供参考

charstring[10],strl[10];

inti;

for(i=0;i<10;i++)

(

strl[i]=9a;

)

strcpy(string,strl);

)

解答:对试题2,如果面试者指出字符数组strl

不能在数组内结束能够给3分;如果面试者指出

strcpy(string,strl)调用使得从strl内存起

复制到string内存起所复制的字节数具有不确

定性能够给7分,在此基础上指出库函数strcpy

工作方式的给10分;

strl不能在数组内结束:因为strl的存储为:

{a,a,a,a,a,a,a,a,a,a},没有'\0'(字符串结束

符),因此不能结束

strcpy(char*sl,char*s2)她的工作原理是,

扫描s2指向的内存,逐个字符付到si所指向的

内存,直到碰到到0',因为strl结尾没有'\0',

因此具有不确定性,不知道她后面还会付什么东

资料仅供参考

正确应如下

voidtest2()

(

charstring[10],strl[10];

inti;

for(i=0;i<9;i++)

(

strl[i]='a'+i;〃把abcdefghi赋值给字符

数组

)

str[i]='\0';〃加上结束符

strcpy(string,strl);

)

分析:

intarr[]={6,7,8,9,10};

int*ptr=arr;

*(ptr++)+=123;

printf(a%d%d",*ptr,*(++ptr));

输出:88

过程:对于*(ptr++)+=123;先做加法6+123,然

后++,指针指向7;对于printf("%d%d",

资料仅供参考

*ptr,*(++ptr));从后往前执行,指针先++,指

向8,然后输出8,紧接着再输出8

已知一个单向链表的头,请写出删除其某一个结

点的算法,要求,先找到此结点,然后删除。

slnodetype*Delete(slnodetype*Head,int

key){}中if(Head->number==key)

(

Head=

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论