CC++程序员应聘常见面试题深入剖析
介绍
本文的目的不是为C/C++程序员提供求职面试指导,而是从技术上分析面试问题的内涵。文中的面试问题大部分来自各大论坛,部分回答也参考了网友的意见。
很多面试问题看似简单,却需要深厚的基本功才能给出完美的答案。让商务面试官写一个最简单的strcpy函数,可以显示面试官的技术水平。我们真的能写一个strcpy函数吗?我们都认为我们可以,但我们写的strcpy可能只得到10分中的2分。读者可以从这篇文章中看到2到10分的strcpy函数的例子,看看它们属于什么级别。除此之外,还有一些面试问题考察面试官的快速思维能力。
分析这些面试问题,本身就包含了浓厚的兴趣;作为一名R&D人员,通过对这些面试问题的深入分析,可以进一步提升自己的内功。
问错误的问题
1:
void test1()
{
char stringvoid test2()
{
char string[10],str 1[10];
int I;
for(I = 0;I {
str 1[I]= ' a ';
}
strcpy( string,str 1);
};
char * str 1 = " 0123456789 ";
strcpy( string,str 1);
}
测试问题2:
[10]
测试问题3:
void test3(char * str 1)
{
char string[10];
if(strlen(str 1){
strcpy(string,str 1);
}
}
回答:
1测试字符串str1需要存储11个字节(包括末尾的' [14] '),但字符串在空之间只有10个字节,strcpy会导致数组越界;
对于问题2,如果面试官指出字符数组str1不能以数组结尾,你可以给3分;如果面试官指出strcpy(string,str1)调用使得str1内存拷贝到string内存的字节数不确定,可以给7分。在此基础上,他指出库函数strcpy的工作原理是10分。
试题3的分析,if(strlen(str1):
考察基本功的掌握情况:
(1)字符串以“[18]”结尾;
(2)对数组越界抓取的敏感性;
(3)库函数strcpy是如何工作的。如果一个标准strcpy函数的总分是10,下面是一些得分不同的答案:
2分
void strcpy( char *strDest,char * strSrc)
{
while(* strdest++ = * strsrc++)!= '[22]' );
}
4分
Voidstrcpy (char * strtest,const char * str src)
/在源字符串中添加const表示它是输入参数,并添加2点
{
while((* strtest++ = * str src++)!= '[24]' );
}
7分
Voidstrcpy (char * strtest,const char * str src)
{
/用非0断言源地址和目的地址,加3点
断言((strtest!= NULL)& &(strrc!= NULL));
while(* str dest++ = * str src++)!= '[26]' );
}
10分
//为了实现连锁经营,返回目的地址加3分!
char * strcpy( char *strDest,const char * strSrc)
{
assert((strDest!= NULL)& &(strrc!= NULL));
char * address = strDest;
while(* str dest++ = * str src++)!= '[29]' );
寄信人地址;
}
从2到10的答案中,我们可以清楚地看到,小小的strcpy中隐藏着如此多的奥秘。真的不是盖的!写一篇完美的稿子需要多么扎实的基本功啊!
(4)掌握strlen,不包括字符串末尾的' [31] '。
在阅读了不同分数的strcpy版本后,读者应该能够编写一个10分的strlen函数。完美的版本是:int strlen( const char *str) //输入参数const
{
assert( strt!= NULL);//断言字符串地址不是0
int len;
while( (*str++)!= ' \ 0 ')
{
len++;
}
return len;
}
测试问题4:
void get memory(char * p)
{
p =(char *)malloc(100);
}
void Test(void)
{
char * str = NULL;
get memory(str);
strcpy( str," hello world ");
printf(str);
}
测试问题5:
char * get memory(void)
{
char p[]= " hello world ";
return p;
}
void Test(void)
{
char * str = NULL;
str = get memory();
printf(str);
}
测试问题6:
void GetMemory( char **p,int num)
{
* p =(char *)malloc(num);
}
void Test(void)
{
char * str = NULL;
GetMemory( &str,100);
strcpy( str," hello ");
printf(str);
}
测试问题7:
void Test(void)
{
char * str =(char *)malloc(100);
strcpy( str," hello ");
free(str);
...//其他省略的语句
}
回答:
4进来的试题中GetMemory( char *p)函数的参数是一个字符串指针。修改函数内部的参数并不能真正改变传入参数的值,就这样完了。
char * str = NULL
get memory(str);
以下字符串仍然为空;;
五个问题。
char p[]= " hello world ";
return p;
的p[]数组是函数中的局部自动变量。函数返回后,内存已被释放。这是很多程序员常犯的错误,其根源在于没有理解变量的生存期。
试题6的GetMemory避免了试题4的问题。传入GetMemory的参数是字符串指针的指针,但是应用内存和赋值语句是在GetMemory中执行的。
* p =(char *)malloc(num);
在判断内存申请是否成功后,应该加上:
If (*p == NULL )
{
...//处理内存应用程序失败
}
问题7和问题6有同样的问题,正在实施。
char * str =(char *)malloc(100);
之后不判断内存申请是否成功;另外,在free(str)之后,str没有设置为空,可能会变成“野”指针。你应该加上:
str = NULL
Malloc的内存在问题6的测试函数中没有释放。
分析:
试题4 ~ 7考察面试官对记忆操作的理解。基本功扎实的面试官一般能答对50~60的错误。但要答对并不容易。
记忆操作的检查主要集中在:
(1)指针的理解;
(2)变量的寿命和范围;
(3)良好的动态内存应用和释放习惯。
让我们看看下面的程序有什么问题:
swap( int* p1,int * p2)
{
int * p;
* p = * P1;
* P1 = * p2;
* p2 = * p;
}
在交换函数中,p是一个“野”指针,可能指向系统区域,导致程序崩溃。在VC++中调试时出现错误“访问冲突”。该程序应改为:
swap( int* p1,int * p2)
{
int p;
p = * P1;
* P1 = * p2;
* p2 = p;
}
0条评论