第一篇:C、C++程序员求职面
试题1:分别给出BOOL,int,float,指针变量 与“零值”比较的 if 语句(假设变量名为var)
解答:
BOOL型变量:if(!var)
int型变量: if(var==0)
float型变量:
const float EPSINON = 0.00001;
if((x >=steps;char tmp[MAX_LEN];
strcpy(tmp, pStr + n);
strcpy(tmp + steps, pStr);
*(tmp + strlen(pStr))= ' ';strcpy(pStr, tmp);}
正确解答2:
void LoopMove(char *pStr, int steps){ int n = strlen(pStr)-steps;char tmp[MAX_LEN];
memcpy(tmp, pStr + n, steps);
memcpy(pStr + steps, pStr, n);
memcpy(pStr, tmp, steps);}
剖析:
这个试题主要考查面试者对标准库函数的熟练程度,在需要的时候引用库函数可以很大程度上简化程序编写的工作量。
最频繁被使用的库函数包括:
(1)strcpy
(2)memcpy
(3)memset
试题6:已知WAV文件格式如下表,打开一个WAV文件,以适当的数据结构组织WAV文件头并解析WAV格式的各项信息。
WAVE文件格式说明表
偏移地址 字节数 数据类型 内 容
文件头
00H 4 Char “RIFF”标志
04H 4 int32 文件长度
08H 4 Char “WAVE”标志
0CH 4 Char “fmt”标志
10H 4
过渡字节(不定)
14H 2 int16 格式类别
16H 2 int16 通道数
18H 2 int16 采样率(每秒样本数),表示每个通道的播放速度
1CH 4 int32 波形音频数据传送速率
20H 2 int16 数据块的调整数(按字节算的)
22H 2
每样本的数据位数
24H 4 Char 数据标记符"data"
28H 4 int32 语音数据的长度
解答:
将WAV文件格式定义为结构体WAVEFORMAT:
typedef struct tagWaveFormat {
char cRiffFlag[4];
UIN32 nFileLen;
char cWaveFlag[4];
char cFmtFlag[4];
char cTransition[4];
UIN16 nFormatTag;
UIN16 nChannels;
UIN16 nSamplesPerSec;
UIN32 nAvgBytesperSec;
UIN16 nBlockAlign;
UIN16 nBitNumPerSample;
char cDataFlag[4];
UIN16 nAudioLength;
} WAVEFORMAT;
假设WAV文件内容读出后存放在指针buffer开始的内存单元内,则分析文件格式的代码很简单,为:
WAVEFORMAT waveFormat;memcpy(&waveFormat, buffer,sizeof(WAVEFORMAT));
直接通过访问waveFormat的成员,就可以获得特定WAV文件的各项格式信息。
剖析:
试题6考查面试者组织数据结构的能力,有经验的程序设计者将属于一个整体的数据成员组织为一个结构体,利用指针类型转换,可以将memcpy、memset等函数直接用于结构体地址,进行结构体的整体操作。透过这个题可以看出面试者的程序设计经验是否丰富。
试题7:编写类String的构造函数、析构函数和赋值函数,已知类String的原型为:
class String {
public:
String(const char *str = NULL);// 普通构造函数
String(const String &other);// 拷贝构造函数
~ String(void);// 析构函数
String & operate =(const String &other);// 赋值函数
private:
char *m_data;// 用于保存字符串
};
解答:
//普通构造函数
String::String(const char *str){ if(str==NULL)
{
m_data = new char[1];// 得分点:对空字符串自动申请存放结束标志' '的空
//加分点:对m_data加NULL 判断
*m_data = ' ';
}
else {
int length = strlen(str);
m_data = new char[length+1];// 若能加 NULL 判断则更好
strcpy(m_data, str);
} }
// String的析构函数 String::~String(void){ delete [] m_data;// 或delete m_data;}
//拷贝构造函数
String::String(const String &other)
// 得分点:输入参数为const型 {
int length = strlen(other.m_data);
m_data = new char[length+1];
//加分点:对m_data加NULL 判断
strcpy(m_data, other.m_data);}
//赋值函数
String & String::operate =(const String &other)// 得分点:输入参数为const型 {
if(this == &other)
//得分点:检查自赋值
return *this;
delete [] m_data;
//得分点:释放原有的内存资源
int length = strlen(other.m_data);
m_data = new char[length+1];//加分点:对m_data加NULL 判断
strcpy(m_data, other.m_data);
return *this;
//得分点:返回本对象的引用 }
剖析:
能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!
在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,也是《Effective C++》中特别强调的条款。
仔细学习这个类,特别注意加注释的得分点和加分点的意义,这样就具备了60%以上的C++基本功!
试题8:请说出static和const关键字尽可能多的作用
解答:
static关键字至少有下列n个作用:
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。
const关键字至少有下列n个作用:
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;
(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:
const classA operator*(const classA& a1,const classA& a2);
operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错:
classA a, b, c;(a * b)= c;// 对a*b的结果赋值
操作(a * b)= c显然不符合编程者的初衷,也没有任何意义。
剖析:
惊讶吗?小小的static和const居然有这么多功能,我们能回答几个?如果只能回答1~2个,那还真得闭关再好好修炼修炼。
这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入,没有一定的知识广度和深度,不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。
4.技巧题
试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1
解答:
int checkCPU(){ {
union w
{
int a;
char b;
} c;
c.a = 1;
return(c.b == 1);} }
剖析:
嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容
0x4000 0x34 0x4001 0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址 存放内容
0x4000 0x12 0x4001 0x34
32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容
0x4000 0x78 0x4001 0x56 0x4002 0x34 0x4003 0x12
而在Big-endian模式CPU内存中的存放方式则为:
内存地址 存放内容 0x4000 0x12 0x4001 0x34 0x4002 0x56 0x4003 0x78
联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-endian模式读写。如果谁能当场给出这个解答,那简直就是一个天才的程序员。
试题2:写一个函数返回1+2+3+„+n的值(假定结果不会超过长整型变量的范围)
解答:
int Sum(int n){
return((long)1 + n)* n / 2;
//或return(1l + n)* n / 2;}
剖析:
对于这个题,只能说,也许最简单的答案就是最好的答案。下面的解答,或者基于下面的解答思路去优化,不管怎么“折腾”,其效率也不可能与直接return(1 l + n)* n / 2相比!
int Sum(int n){ long sum = 0;for(int i=1;i<=n;i++){
sum += i;} return sum;}
所以程序员们需要敏感地将数学等知识用在程序设计中。
本篇文章来源于:开发学院 http://edu.codepub.com
原文链接:http://edu.codepub.com/2008/1216/166_3.php
第二篇:C语言C++程序员编程必备
Java,NET,PHP,Ruby,Perl 和 Python 等,但今天我们要讨论的是两个最古老和流行的语言的C和C++。它们都有其特殊的地方,更有效的功能和支持的工具,这两种语言仍然很活跃。
今天我们整理了一些令人印象深刻的IDE(集成开发环境)和编译器推荐给 C 和 C++ 程序员。集成开发环境,主要用于提供软件应用的各种组件而开发的,其中最流行的功能是它们都有吸引力的用户界面。1)Best IDE for C/C++ – kDevelop KDevelop 是基于 KDevPlatform 的可使用开源插件扩展的 IDE。KDevPlatform 是一种可以用来作为 IDE 的基础库的开源集。
2)Best IDE for C/C++-Anjuta Anjuta Devstudio 具有先进的编程工具,包括项目管理,应用程序向导,交互式调试器,源代码编辑器,版本控制,GUI设计器,分析器和许多工具,另一个伟大的开发工作室。此工具提供的 C/C++ 程序员有很大强大的用户界面开发接口。
3)Best IDE for C/C++Eclipse CDT Eclipse CD 是最强大和最流行的IDE之一,提供了更高效的功能,如:项目的创建和管理,构建支持不同的工具链,标准make编译,源代码导航,各种来源的知识工具,代码编辑器,语法高亮,折叠和超链接导航,源代码重构和代码生成,可视化调试工具,包括内存,寄存器等等。
7)Best IDE for C/C++ – Compilr Compilr 是在线集成开发工具,让您与令人印象深刻的功能和简单的用户界面编写代码。该工具支持的编程语言中广泛的C,C + + JAVA,HTML等等。
8)Best IDE for C/C++Netbeans C++ Netbeans 的工具包括许多适合 C 和 C++ 项目类型模板,可以 使用动态库和静态创建 C/C++ 应用程序库。它拥有迷人的功能:代码协助,编译器配置,单元测试,源检查,远程开发和文件导航等等。
10)Best IDE/Compiler for C/C++Ultimate++ Ultimate++是对于 C++ 程序员来说是很好框架。这个 IDE 引入了模块化概念,可以结合 GCC,MinGW 和 Visual C++。
12)Best Compiler for C/C++-Digital Mars DigitalMars 是一款高性能的 C/C++ 编译器。包括的功能,如速度最快的编译/链接时,强
HTML文档,反汇编,图书管理员,资源编译器,make等,命令行和GUI版本,教程,代码示例,在线更新,标准模板库等等。
13)Best IDE for C-C-Free
14)Best Compiler for C/C++ – MinGW MinGW 编译器提供访问微软的C运行库和一些特定语言运行库的功能。
15)Best Compiler for C – Tiny C Compiler iny C Compiler 是最好的编译器之一,让开发人员可以在任何地方编译代码,可以使用任何 C 动态库,编译并直接执行C++源程序,也包含完整的 C 预处理器和 GNU 汇编器。
@扣丁学堂 智悦分享
第三篇:C、C++程序员常见面试题深入剖析
1.引言 本文的写作目的并不在于提供C/C++程序员求职面试指导,而旨在从技术上分析面试题的内涵。文中的大多数面试题来自各大论坛,部分试题解答也参考了网友的意见-。
许多面试题看似简单,却需要深厚的基本功才能给出完美的解答。企业要求面试者写一个最简单的strcpy函数都可看出面试者在技术上究竟达到了怎样的程
度,我们能真正写好一个strcpy函数吗?我们都觉得自己能,可是我们写出的strcpy很可能只能拿到10分中的2分。读者可从本文看到strcpy 函数从2分到10分解答的例子,看看自己属于什么样的层次。此外,还有一些面试题考查面试者敏捷的思维能力。
分析这些面试题,本身包含很强的趣味性;而作为一名研发人员,通过对这些面试题的深入剖析则可进一步增强自身的内功。2.找错题
试题1: void test1(){ char string[10];char* str1 = “0123456789”;strcpy(string, str1);} 试题2: void test2(){ char string[10], str1[10];int i;for(i=0;i<10;i++){ str1 = 'a'; } strcpy(string, str1); } 试题3:
void test3(char* str1){ char string[10];if(strlen(str1)<= 10){ strcpy(string, str1);} } 解答:
试题1字符串str1需要11个字节才能存放下(包括末尾的' '),而string只有10个字节的空间,strcpy会导致数组越界; 对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10 分;
对试题3,if(strlen(str1)<= 10)应改为if(strlen(str1)< 10),因为strlen的结果未统计' '所占用的1个字节。
剖析:
考查对基本功的掌握:(1)字符串以' '结尾;(2)对数组越界把握的敏感度;
(3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案: 2分
void strcpy(char *strDest, char *strSrc){ while((*strDest++ = * strSrc++)!= ' ');} 4分 void strcpy(char *strDest, const char *strSrc)//将源字符串加const,表明其为输入参数,加2分 { while((*strDest++ = * strSrc++)!= ' ');} 7分 void strcpy(char *strDest, const char *strSrc){ //对源地址和目的地址加非0断言,加3分
assert((strDest!= NULL)&&(strSrc!= NULL));while((*strDest++ = * strSrc++)!= ' ');} 10分 //为了实现链式操作,将目的地址返回,加3分!char * strcpy(char *strDest, const char *strSrc){ assert((strDest!= NULL)&&(strSrc!= NULL));char *address = strDest;while((*strDest++ = * strSrc++)!= ' ');return address;} 从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊!(4)对strlen的掌握,它没有包括字符串末尾的' '。
读者看了不同分值的strcpy版本,应该也可以写出一个10分的strlen函数了,完美的版本为:
int strlen(const char *str)//输入参数const { assert(strt!= NULL);//断言字符串地址非0 int len;while((*str++)!= ' '){ len++;} return len;}
试题4: void GetMemory(char *p){ p =(char *)malloc(100);} void Test(void){ char *str = NULL;GetMemory(str);strcpy(str, “hello world”);printf(str);} 试题5: char *GetMemory(void){ char p[] = “hello world”;return p;} void Test(void){ char *str = NULL;str = GetMemory();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;GetMemory(str);后的str仍然为NULL;
试题5中
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;试题6的Test函数中也未对malloc的内存进行释放。
剖析: 试题4~7考查面试者对内存操作的理解程度,基本功扎实的面试者一般都能正确的回答其中50~60的错误。但是要完全解答正确,却也绝非易事。
对内存操作的考查主要集中在:
(1)指针的理解;
(2)变量的生存期及作用范围;
(3)良好的动态内存申请和释放习惯。
再看看下面的一段程序有什么错误: swap(int* p1,int* p2){ int *p;*p = *p1;*p1 = *p2;*p2 = *p;} 在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的崩溃。在VC++中DEBUG运行时提示错误“Access Violation”。该程序应该改为: swap(int* p1,int* p2){ int p;p = *p1;*p1 = *p2;*p2 = p;} 3.内功题 试题1:分别给出BOOL,int,float,指针变量 与“零值”比较的 if 语句(假设变量名为var)
解答: BOOL型变量:if(!var)int型变量: if(var==0)float型变量:
const float EPSINON = 0.00001;if((x >=steps;char tmp[MAX_LEN];strcpy(tmp, pStr + n);strcpy(tmp + steps, pStr);*(tmp + strlen(pStr))= ' ';strcpy(pStr, tmp);} 正确解答2: void LoopMove(char *pStr, int steps){ int n = strlen(pStr)-steps;char tmp[MAX_LEN];memcpy(tmp, pStr + n, steps);memcpy(pStr + steps, pStr, n);memcpy(pStr, tmp, steps);} 剖析: 这个试题主要考查面试者对标准库函数的熟练程度,在需要的时候引用库函数可以很大程度上简化程序编写的工作量。
最频繁被使用的库函数包括:
(1)strcpy(2)memcpy(3)memset 试题6:已知WAV文件格式如下表,打开一个WAV文件,以适当的数据结构组织WAV文件头并解析WAV格式的各项信息。WAVE文件格式说明表
偏移地址 字节数 数据类型 内 容 文件头
00H 4 Char “RIFF”标志 04H 4 int32 文件长度 08H 4 Char “WAVE”标志 0CH 4 Char “fmt”标志 10H 4 过渡字节(不定)14H 2 int16 格式类别 16H 2 int16 通道数 18H 2 int16 采样率(每秒样本数),表示每个通道的播放速度 1CH 4 int32 波形音频数据传送速率
20H 2 int16 数据块的调整数(按字节算的)22H 2 每样本的数据位数 24H 4 Char 数据标记符"data" 28H 4 int32 语音数据的长度
解答:
将WAV文件格式定义为结构体WAVEFORMAT: typedef struct tagWaveFormat { char cRiffFlag[4];UIN32 nFileLen;char cWaveFlag[4];char cFmtFlag[4];char cTransition[4];UIN16 nFormatTag;UIN16 nChannels;UIN16 nSamplesPerSec;UIN32 nAvgBytesperSec;UIN16 nBlockAlign;UIN16 nBitNumPerSample;char cDataFlag[4];UIN16 nAudioLength;} WAVEFORMAT;假设WAV文件内容读出后存放在指针buffer开始的内存单元内,则分析文件格式的代码很简单,为: WAVEFORMAT waveFormat;memcpy(&waveFormat, buffer,sizeof(WAVEFORMAT));直接通过访问waveFormat的成员,就可以获得特定WAV文件的各项格式信息。
剖析:
试题6考查面试者组织数据结构的能力,有经验的程序设计者将属于一个整体的数据成员组织为一个结构体,利用指针类型转换,可以将memcpy、memset等函-数直接用于结构体地址,进行结构体的整体操作。透过这个题可以看出面试者的程序设计经验是否丰富。
试题7:编写类String的构造函数、析构函数和赋值函数,已知类String的原型为: class String { public: String(const char *str = NULL);// 普通构造函数 String(const String &other);// 拷贝构造函数 ~ String(void);// 析构函数
String & operate =(const String &other);// 赋值函数 private: char *m_data;// 用于保存字符串 };解答: //普通构造函数
String::String(const char *str){ if(str==NULL){ m_data = new char[1];// 得分点:对空字符串自动申请存放结束标志' '的空 //加分点:对m_data加NULL 判断 *m_data = ' ';} else { int length = strlen(str);m_data = new char[length+1];// 若能加 NULL 判断则更好 strcpy(m_data, str);} } // String的析构函数 String::~String(void){ delete [] m_data;// 或delete m_data;} //拷贝构造函数 String::String(const String &other)// 得分点:输入参数为const型 { int length = strlen(other.m_data);m_data = new char[length+1];//加分点:对m_data加NULL 判断 strcpy(m_data, other.m_data);} //赋值函数 String & String::operate =(const String &other)// 得分点:输入参数为const型 { if(this == &other)//得分点:检查自赋值 return *this;delete [] m_data;//得分点:释放原有的内存资源 int length = strlen(other.m_data);m_data = new char[length+1];//加分点:对m_data加NULL 判断
strcpy(m_data, other.m_data);return *this;//得分点:返回本对象的引用 } 剖析: 能够准确无误地编写出String类的构造函数、拷贝构造函数、赋值函数和析构函数的面试者至少已经具备了C++基本功的60%以上!在这个类中包括了指针类成员变量m_data,当类中包括指针类成员变量时,一定要重载其拷贝构造函数、赋值函数和析构函数,这既是对C++程序员的基本要求,-也是《Effective C++》中特别强调的条款。
仔细学习这个类,特别注意加注释的得分点和加分点的意义,这样就具备了60%以上的C++基本功!
试题8:请说出static和const关键字尽可能多的作用
解答:
static关键字至少有下列n个作用:
(1)函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;
(2)在模块内的static全局变量可以被模块内所用函数访问,但不能被模块外其它函数访问;
(3)在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;
(4)在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;
(5)在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。const关键字至少有下列n个作用:
(1)欲阻止一个变量被改变,可以使用const关键字。在定义该const变量时,通常需要对它进行初始化,因为以后就没有机会再去改变它了;
(2)对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const;
(3)在一个函数声明中,const可以修饰形参,表明它是一个输入参数,在函数内部不能改变其值;(4)对于类的成员函数,若指定其为const类型,则表明其是一个常函数,不能修改类的成员变量;
(5)对于类的成员函数,有时候必须指定其返回值为const类型,以使得其返回值不为“左值”。例如:
const classA operator*(const classA& a1,const classA& a2);operator*的返回结果必须是一个const对象。如果不是,这样的变态代码也不会编译出错: classA a, b, c;(a * b)= c;// 对a*b的结果赋值
操作(a * b)= c显然不符合编程者的初衷,也没有任何意义。
剖析:
惊讶吗?小小的static和const居然有这么多功能,我们能回答几个?如果只能回答1~2个,那还真得闭关再好好修炼修炼。
这个题可以考查面试者对程序设计知识的掌握程度是初级、中级还是比较深入,没有一定的知识广度和深度,不可能对这个问题给出全面的解答。大多数人只能回答出static和const关键字的部分功能。4.技巧题
试题1:请写一个C函数,若处理器是Big_endian的,则返回0;若是Little_endian的,则返回1 解答: int checkCPU(){ { union w { int a;char b;} c;c.a = 1;return(c.b == 1);} } 剖析: 嵌入式系统开发者应该对Little-endian和Big-endian模式非常了解。采用Little-endian模式的CPU对操作数的存放方
式是从低字节到高字节,而Big-endian模式对操作数的存放方式是从高字节到低字节。例如,16bit宽的数0x1234在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容 0x4000 0x34 0x4001 0x12 而在Big-endian模式CPU内存中的存放方式则为: 内存地址 存放内容 0x4000 0x12 0x4001 0x34 32bit宽的数0x12345678在Little-endian模式CPU内存中的存放方式(假设从地址0x4000开始存放)为: 内存地址 存放内容 0x4000 0x78 0x4001 0x56 0x4002 0x34 0x4003 0x12 而在Big-endian模式CPU内存中的存放方式则为: 内存地址 存放内容 0x4000 0x12 0x4001 0x34 0x4002 0x56 0x4003 0x78 联合体union的存放顺序是所有成员都从低地址开始存放,面试者的解答利用该特性,轻松地获得了CPU对内存采用Little-endian还是Big-en-dian模式读写。如果谁能当场给出这个解答,那简直就是一个天才的程序员。
试题2:写一个函数返回1+2+3+...+n的值(假定结果不会超过长整型变量的范围)
解答:
int Sum(int n){ return((long)1 + n)* n / 2;//或return(1l + n)* n / 2;} 剖析: 对于这个题,只能说,也许最简单的答案就是最好的答案。下面的解答,或者基于下面的解答思路去优化,不管怎么“折腾”,其效率也不可能与直接return(1 l + n)* n / 2相比!int Sum(int n){ long sum = 0;for(int i=1;i<=n;i++){ sum += i;} return sum;}
迅雷笔试题:
一、实现一个高性能的文件缓存系统,先写好思路,再编码实现。
二、实现一个高效率的程序(包括所需程序代码),以尽量短的时间,将用户信息表中150张按照时间hash的表(每张表的数据量为100万,数据字段包含《最近修改时间戳/username/nickname/出生地/所在地/年龄/性别/自我介绍》),转换成按照username hash的100张表。转换过程方法和过程需要考虑: a)尽可能短的时间中断用户服务; b)尽可能少的使用机器内存。
三、迅雷进行一个活动,这个活动需要客户端访问我们服务器。但活动为了限制访问量,做了如下规定,那就是每一个帐户在3600秒内只能参加不多于5次。请实现类c_user_enabled,完成此限制功能。类接口定义:
Class c_user_enabled { Public: Bool init();Bool is_user_enabled(string user_name);// user_name表示用户帐户标识 Bool destroy();};
附:
需要考虑线程安全 可以使用stl.可以使用如下的一个hash函数: Unsigned str_hash(string str);可以使用如下锁: Class c_lock { Public: Void lock();Void unlock();Private: …;};高手们,想多少就说多少吧。
第四篇:2012年最新C和C++程序员笔试题
以下是整理自8月下旬至10月份内的各大公司的笔试面试三十题(注:所有题目基本上全部为软件开发方向,题目来源:网络收集),相信一定能给正在参加各种校招的诸多朋友多少帮助,学习参考或借鉴
九月十月百度人搜,阿里巴巴,腾讯华为小米搜狗笔/面试五十题
9月11日,京东:
谈谈你对面向对象编程的认识
8月20日,金山面试,题目如下:
数据库1中存放着a类数据,数据库2中存放着以天为单位划分的表30张(比如table_20110909,table_20110910,table_20110911),总共是一个月的数据。表1中的a类数据中有一个字段userid来唯一判别用户身份,表2中的30张表(每张表结构相同)也有一个字段userid来唯一识别用户身份。如何判定a类数据库的多少用户在数据库2中出现过? 百度实习笔试题(2012.5.6)
简答题1
一个单词单词字母交换,可得另一个单词,如army->mary,成为兄弟单词。提供一个单词,在字典中找到它的兄弟。描述数据结构和查询过程。评点:同去年9月份的一道题,见此文第3题:简答题2 线程和进程区别和联系。什么是“线程安全”
简答题3
C和C++怎样分配和释放内存,区别是什么
算法题1
一个url指向的页面里面有另一个url,最终有一个url指向之前出现过的url或空,这两种情形都定义为null。这样构成一个单链表。给两条这样单链表,判断里面是否存在同样的url。url以亿级计,资源不足以hash。
算法题2
数组al[0,mid-1] 和 al[mid,num-1],都分别有序。将其merge成有序数组al[0,num-1],要求空间复杂度O(1)系统设计题
百度搜索框的suggestion,比如输入北京,搜索框下面会以北京为前缀,展示“北京爱情故事”、“北京公交”、“北京医院”等等搜索词。
如何设计使得空间和时间复杂度尽量低。评点:老题,直接上Trie树+Hash,Trie树的介绍见:从Trie树(字典树)谈到后缀树。
人搜笔试
1.快排每次以第一个作为主元,问时间复杂度是多少?(O(N*logN))
2.T(N)= N + T(N/2)+T(2N), 问T(N)的时间复杂度是多少? 点评:O(N*logN)or O(N)? 3.从(0,1)中平均随机出几次才能使得和超过1?(e)4.编程题:
一棵树的节点定义格式如下: struct Node{ Node* parent;Node* firstChild;// 孩子节点 Node* sibling;// 兄弟节点 } 要求非递归遍历该树。
思路:采用队列存储,来遍历节点。5.算法题:
有N个节点,每两个节点相邻,每个节点只与2个节点相邻,因此,N个顶点有N-1条边。每一条边上都有权值wi,定义节点i到节点i+1的边为wi。求:不相邻的权值和最大的边的集合。 人搜面试,所投职位:搜索研发工程师:面试题回忆
1、删除字符串开始及末尾的空白符,并且把数组中间的多个空格(如果有)符转化为1个。
2、求数组(元素可为正数、负数、0)的最大子序列和。
3、链表相邻元素翻转,如a->b->c->d->e->f-g,翻转后变为:b->a->d->c->f->e->g
4、链表克隆。链表的结构为: typedef struct list { int data;//数据字段
list *middle;//指向链表中某任意位置元素(可指向自己)的指针 list *next;//指向链表下一元素 } list;5、100万条数据的数据库查询速度优化问题,解决关键点是:根据主表元素特点,把主表拆分并新建副表,并且利用存储过程保证主副表的数据一致性。(不用写代码)
6、求正整数n所有可能的和式的组合(如;4=1+1+1+1、1+1+2、1+3、2+1+1、2+2)。
7、求旋转数组的最小元素(把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个排好序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3, 4, 5, 1, 2}为{1, 2, 3, 4, 5}的一个旋转,该数组的最小值为1)
8、找出两个单链表里交叉的第一个元素
9、字符串移动(字符串为*号和26个字母的任意组合,把*号都移动到最左侧,把字母移到最右侧并保持相对顺序不变),要求时间和空间复杂度最小
10、时间复杂度为O(1),怎么找出一个栈里的最大元素
11、线程、进程区别
12、static在C和C++里各代表什么含义
13、const在C/C++里什么意思
14、常用linux命令
15、解释Select/Poll模型 网易有道二面:
判断一个数字序列是BST后序遍历的结果,现场写代码。
8月30日,网易有道面试题
var tt = 'aa';function test(){ alert(tt);var tt = 'dd';alert(tt);} test(); 8月31日,百度面试题:不使用随机数的洗牌算法,9月6日,阿里笔试题:平面上有很多点,点与点之间有可能有连线,求这个图里环的数目。
9月7日,一道华为上机题:
题目描述: 选秀节目打分,分为专家评委和大众评委,score[] 数组里面存储每个评委打的分数,judge_type[] 里存储与 score[] 数组对应的评委类别,judge_type == 1,表示专家评委,judge_type == 2,表示大众评委,n表示评委总数。打分规则如下:专家评委和大众评委的分数先分别取一个平均分(平均分取整),然后,总分 = 专家评委平均分 * 0.6 + 大众评委 * 0.4,总分取整。如果没有大众评委,则 总分 = 专家评委平均分,总分取整。函数最终返回选手得分。
函数接口 int cal_score(int score[], int judge_type[], int n)
上机题目需要将函数验证,但是题目中默认专家评委的个数不能为零,但是如何将这种专家数目为0的情形排除出去。
9月8日,腾讯面试题:
假设两个字符串中所含有的字符和个数都相同我们就叫这两个字符串匹配,比如:abcda和adabc,由于出现的字符个数都是相同,只是顺序不同,所以这两个字符串是匹配的。要求高效!
又是跟上述第3题中简单题一的兄弟节点类似的一道题,我想,你们能想到的, 阿里云,搜索引擎中5亿个url怎么高效存储;
一道C++笔试题,求矩形交集的面积:
在一个平面坐标系上,有两个矩形,它们的边分别平行于X和Y轴。
其中,矩形A已知,ax1(左边), ax2(右边), ay1(top的纵坐标), ay2(bottom纵坐标).矩形B,类似,就是 bx1, bx2, by1, by2。这些值都是整数就OK了。要求是,如果矩形没有交集,返回-1,有交集,返回交集的面积。int area(rect const& a, rect const& b){...} 点评: healer_kx:
补齐代码,最好是简洁的,别用库。你可以写你的辅助函数,宏定义,代码风格也很重要。ri_aje:struct rect {
// axis alignment assumed // bottom left is(x[0],y[0]), top right is(x[1],y[1])double x [2];double y [2];};
template
// return type changed to handle non-integer rects double area(rect const& a, rect const& b){
// perfectly adjacent rects are considered having an intersection of 0 area double const dx = min(a.x[1],b.x[1])max(a.y[0],b.y[0]);return dx>=0&&dy>=0 ? dx*dy :-1; } 下面是一个简短的证明。
对于平行于坐标轴的矩形 r,假设其左下角点坐标为(rx0,ry0),右上角点坐标为(rx1,ry1),那么由 r 定义的无限有界点集为:{(x,y)|x in [rx0,rx1] && y in [ry0,ry1]}。
根据交集的定义,则任意二维点(x,y)在矩形 a,b 的交集内等价于 {(x,y)|(x,y)in a 并且(x,y)in b} <==>
{(x,y)|x in [ax0,ax1] && x in [bx0,bx1] 并且 y in [ay0,ay1] && y in [by0,by1]} <==> {(x,y)|x in [max(ax0,bx0),min(ax1,bx1)] 并且 y in [max(ay0,by0),min(ay1,by1)]}
因此,交集矩形的边长分别为 min(ax1,bx1)-max(ax0,bx0)和 min(ay1,by1)-max(ay0,by0)。注意当交集为空时(a,b 不相交),则经此法计算出来的交集边长为负值,此事实可用于验证 a,b 的相交性。
鉴于笛卡尔积各个维度上的不相关性,此方法可扩展到任意有限维线性空间,比如,三维空间中平行于坐标轴的长方体的交集体积可以用类似的方法计算。
2012年创新工场校园招聘最后一道笔试题:工场很忙
创新工场每年会组织同学与项目的双选会,假设现在有M个项目,编号从1到M,另有N名同学,编号从1到N,每名同学能选择最多三个、最少一个感兴趣的项目。选定之后,HR会安排项目负责人和相应感兴趣的同学一对一面谈,每次面谈持续半小时。由于大家平时都很忙,所以咱们要尽量节约时间,请你按照以下的条件设计算法,帮助HR安排面试。
1)同学很忙。项目负责人一次只能与一名同学面谈,而同学会在自己第一个面试开始时达到工场,最后一个面试结束后离开工场,如果参加一个项目组的面试后不能立即参加下一个项目组的面试,就必须在工场等待。所以请尽可能让同学的面试集中在某一时间段,减少同学在工场等待的时间。
2)项目负责人很忙。众所周知,创业团队的负责人会有很多事情要做,所以他们希望能够将自己参与的面试集中在某一段时间内,请在保证1)的情况下,使得项目负责人等待的时间最少。
3)HR很忙。从第一轮面试开始以后,所有HR都必须等到最后一轮面试结束,所以需要在保证1)和2)的同时,也能尽快解放掉所有的HR,即让第一轮面试到最后一轮面试之间持续的时间最短。
输入(以文件方式输入,文件名为iw,例如iw.in):
第1行...第n行:同学的编号 项目的编号
样例(数据间用空格隔开,两个0表示输入结束):
112
0 0
表示M=3,N=3,编号为1的同学选择了项目1,2和3,编号为2的同学选择了项目1,编号为3的同学选了项目1和2
输出(以文件方式输出,文件名为iw,例如iw.out):
第1行:编号为1的项目依次面试新同学的编号序列
第2行:编号为2的项目依次面试新同学的编号序列...第n行:编号为n的项目依次面试新同学的编号序列
样例(数据间用空格隔开,0表示没有面试):3 21 0 0 0 1
表示编号为1的项目在第一轮面试编号为1的同学,第二轮面试编号为3的同学,第三轮面试编号为2的同学
编号为2的项目在第一轮面试编号为3的同学,第二轮面试编号为1的同学,第二轮不用面试
编号为3的项目在第一轮和第二轮都不用面试,第三轮面试编号为1的同学
4**9 的笔试题,比较简单: 1.求链表的倒数第二个节点
2.有一个整数数组,求数组中第二大的数 阿里巴巴二道题 第一道:
对于给定的整数集合S,求出最大的d,使得a+b+c=d。a,b,c,d互不相同,且都属于S。集合的元素个数小于等于2000个,元素的取值范围在[-2^28,2^281)^2)。最后我给出了一个巧妙的证明。然后发现如果是m*n的矩阵也是类似的答案,不局限于方阵。此外,题目具体描述可以看看这里:
9月27日,小米两面:
一面:
除了聊研究,就一道题
数组里找到和最接近于0的两个值。二面:
行列有序的矩阵查找一个数
直方图最大矩形。点评:这里有此题的具体表述及一份答案: 3 next_permutation 字符串匹配 含有* ?(写代码)
实现strcpy memmove(必须写代码)//void * memmove(void * destination, const void * source, size_t num);) //是
//最简单的方法是直接复制,但是由于它们可能存在内存的重叠区,因此可能覆盖了原有数据。//比如当source+count>=dest&&source //解决办法是从后往前拷贝。//对于其它情况,则从前往后拷贝。 void* memmove(void* dest, void* source, size_t count){ void* ret = dest; if(dest <= source || dest >=(source + count)){ //正向拷贝 //copy from lower addresses to higher addresses while(count--)*dest++ = *source++;} else { //反向拷贝 //copy from higher addresses to lower addresses dest += count1; while(count--)*dest--= *source--;} return ret;} 6 读数(千万亿,百万亿„„)变为数字(说思路即可,字符串查找,填写各个权值的字段,然后判断是否合法,读前面那些×权值,累加)。 9月27日,Hulu 2013北京地区校招笔试题 填空题: 1、中序遍历二叉树,结果为ABCDEFGH,后序遍历结果为ABEDCHGF,那么前序遍历结果为? 2、对字符串HELL0_HULU中的字符进行二进制编码,使得字符串的编码长度尽可能短,最短长度为? 3、对长度12的有序数组进行二分查找,目标等概率出现在数组的每个位置上,则平均比较次数为? 4、一副扑克(去王),每个人随机的摸两张,则至少需要多少人摸牌,才能保证有两个人抽到同样的花色。 5、x个小球中有唯一一个球较轻,用天平秤最少称量y次能找出这个较轻的球,写出y和x的函数表达式y=f(x)6、3的方幂及不相等的3的方幂的和排列成递增序列1,3,4,9,10,12,13„„,写出数列第300项 7、无向图G有20条边,有4个度为4的顶点,6个度为3的顶点,其余顶点度小于3,则G有多少个顶点 8、桶中有M个白球,小明每分钟从桶中随机取出一个球,涂成红色(无论白或红都涂红)再放回,问小明将桶中球全部涂红的期望时间是? 9、煤矿有3000吨煤要拿到市场上卖,有一辆火车可以用来运煤,火车最多能装1000吨煤,且火车本身需要烧煤做动力,每走1公里消耗1吨煤,如何运煤才能使得运到市场的煤最多,最多是多少? 10、1,2,3,4„..n,n个数进栈,有多少种出栈顺序,写出递推公式(写出通项公式不得分) 11、宇宙飞船有100,000位的存储空间,其中有一位有故障,现有一种Agent可以用来检测故障,每个Agent可以同时测试任意个位数,若都没有故障,则返回OK,若有一位有故障,则失去响应。如果有无限多个Agent可供使用,每个Agent进行一次检测需要耗费1小时,现在有2个小时时间去找出故障位,问最少使用多少个Agent就能找出故障。 (总共12道填空题,还有一道太复杂,题目很长,还有示意图,这里没有记录下来)大题: 1、n个数,找出其中最小的k个数,写出代码,要求最坏情况下的时间复杂度不能高于O(n logk) 2、写程序输出8皇后问题的所有排列,要求使用非递归的深度优先遍历 3、有n个作业,a1,a2„..an,作业aj的处理时间为tj,产生的效益为pj,最后完成期限为dj,作业一旦被调度则不能中断,如果作业aj在dj前完成,则获得效益pj,否则无效益。给出最大化效益的作业调度算法。 有道的一个笔试题,1-9,9个数组成三个三位数,且都是完全平方数(三个三位数 占据 9个数)求解法。 点评@林晚枫&归云见鸿:(a*10+b)(a*10+b)100a^2+20ab+b^2 a 属于 [1,2,3] a=3,b=1 31 961, a=2,b=3 23 529 400+40b+b^2 25 625 27 729 28 784 29 841 a=1,b=3 13 169 100+20b+b^2 14 196 16 256 17 289 18 324 19 361 =>最终唯一解 529 784 361 具体代码如下(3个for循环,然后hash): 9月28日,大众点评北京笔试题目: 1.一个是跳台阶问题,可以1次一级,1次两级,1次三级,求N级的跳法一共多少种? 点评:老题, 2.一个文件有N个单词,每行一个,其中一个单词出现的次数大于N/2,怎么样才能快速找出这个单词? 点评:还是老题, 大众点评前面还有30道逻辑题,15道文字推理,15道数学推理,一共只给20min。 9月28日,网易笔试题: 1、英雄升级,从0级升到1级,概率100%。 从1级升到2级,有1/3的可能成功;1/3的可能停留原级;1/3的可能下降到0级; 从2级升到3级,有1/9的可能成功;4/9的可能停留原级;4/9的可能下降到1级。每次升级要花费一个宝石,不管成功还是停留还是降级。求英雄从0级升到3级平均花费的宝石数目。 点评:题目的意思是,从第n级升级到第n+1级成功的概率是(1/3)^n(指数),停留原级和降级的概率一样,都为[1-(1/3)^n]/2)。 2、将一个很长的字符串,分割成一段一段的子字符串,子字符串都是回文字符串。有回文字符串就输出最长的,没有回文就输出一个一个的字符。例如: habbafgh 输出h,abba,f,g,h。 点评:一般的人会想到用后缀数组来解决这个问题, 10月9日,腾讯一面试题: 有一个log文件,里面记录的格式为: QQ号: 时间: flag: 如123456 14:00:00 0 123457 14:00:01 1 其中flag=0表示登录 flag=1表示退出 问:统计一天平均在线的QQ数。 点评:第8题后的腾讯面试题,读者可以参看之。 10月9日,腾讯面试题: 1.有一亿个数,输入一个数,找出与它编辑距离在3以内的书,比如输入6(0110),找出0010等数,数是32位的。2.每个城市的IP段是固定的,新来一个IP,找出它是哪个城市的,设计一个后台系统。 10月9日,YY笔试题: 输出一个字符串中没有重复的字符。如“baaca”输出“bac”。对于一个多叉树,设计TreeNode节点和函数,返回先序遍历情况下的下一个节点。函数定义为TreeNode* NextNode(TreeNode* node)3 分割字符串。 对于一个字符串,根据分隔符seperator,把字符串分割,如果存在多个分隔符连在一起,则当做一个分隔符。如果分隔符出现在“ ”符号之间,则不需要分割“ ”之间的字符。比如a++abc,分隔符为+,输出a abc a+“hu+” 输出a hu+ a++“HU+JI 输出a ”HU JI。 请根据上述需求完成函数:void spiltString(string aString,char aSeperator)。 10月9日,赶集网笔试 10月9日,阿里巴巴2013校园招聘全套笔试题(注:下图中所标答案不代表标准答案,有问题,欢迎留言评论) 上述第15题,填空:lower+(upper-lower)/2 lower mid upper 0 6 12 7 9 12 7 7 8 8 8 8 比较4次 上述第16题,解答如下图所示: 上述第17题,解答如下图所示: 18、甲包8个红球 2个蓝球,乙包2个红球 8个蓝球。抛硬币决定从哪个包取球,取了11次,7红4蓝。注,每次取后还放进去,只抛一次硬币。问选的是甲包的概率? 点评: 贝叶斯公式 + 全概率公式作答(参看链接:http://)。具体解答如下图所示: 注:上述第15~18的解答全部来自读者Lei Lei来信给出的解答,特此感谢。有任何问题,欢迎随时讨论&指正,同时,更欢迎其他朋友也一起来做这些题目(你的答案一经选用,我可以根据你的要求,贴出你的个人主页或微博地址或博客地址)。 19、已知一个n个元素的数组,第i个元素在排序后的位置在[i-k,i+k]区间,k< 10月10日,暴风影音笔试: 都是非常基础的题目,这是其中一道:一个整数转换成二进制后,问里面有多少个1。10月10日人人网面试题 第一面: 1、(1)++i 和 i++,那个效率高? (2)++++i,i++++,哪个是合法的? (3)实现int型的++i 和 i++操作。 2、一段程序,求输出。(考察静态变量和模版类) int g = 0;template int main(){ cout << B 3、(1)实现二进制转十进制。 (2)如果有下面这种能直接求二进制转十进制的代码,是怎么实现的? binary<1>::value;// 结果为1 binary<11>::value;// 结果为3 4、volatile、explicit、mutable表示的含义。 5、求整形数组的一个子数组,使得该子数组所有元素的和的绝对值最大。 6、(1)写求单链表是否有环的算法。(2)如果有环,如何找出环的第一个结点。 7、实现单例模式。二面: 1、一个文本,一万行,每行一个词,统计出现频率最高的前10个词(词的平均长度为Len)。并分析时间复杂度。 2、求数组中最长递增子序列。 10月10日,网易2013校园招聘全套笔试题: 10月10日,网易,数据挖掘工程师: 1,简述你对数据与处理的认识; 2,简述你对中文分词的理解,说明主要难点和常用算法; 3,常见的分类算法有哪些; 4,简述K-MEANS算法; 5,设计一个智能的商品推荐系统; 6,简述你对观点挖掘的认识。其它题目同 点评:其它题目与上述第56题第一部分所述相同。 C/C++ 程序设计员应聘常见面试试题深入剖析本文的写作目的并不在于提供C/C++程序员求职面试指导,而旨在从技术上分析面试题的内涵。文中的大多数面试题来自各大论坛,部分试题解答也参考了网友的意见。 许多面试题看似简单,却需要深厚的基本功才能给出完美的解答。企业要求面试者写一个最简单的strcpy函数都可看出面试者在技术上究竟达到了怎样的程度,我们能真正写好一个strcpy函数吗?我们都觉得自己能,可是我们写出的strcpy很可能只能拿到10分中的2分。读者可从本文看到strcpy函数从2分到10分解答的例子,看看自己属于什么样的层次。此外,还有一些面试题考查面试者敏捷的思维能力。 分析这些面试题,本身包含很强的趣味性;而作为一名研发人员,通过对这些面试题的深入剖析则可进一步增强自身的内功。 2.找错题 试题1: 以下是引用片段: void test1() { char string[10]; char* str1 = “0123456789”;strcpy(string, str1); } 试题2: 以下是引用片段: void test2() { char string[10], str1[10]; int i; for(i=0;i<10;i++) { str1= 'a'; } strcpy(string, str1); } 试题3: 以下是引用片段: void test3(char* str1) { char string[10]; if(strlen(str1)<= 10) { strcpy(string, str1); } } 解答: 试题1字符串str1需要11个字节才能存放下(包括末尾的‟ ‟),而string只有10个字节的空间,strcpy会导致数组越界; 对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string,str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分; 对试题3,if(strlen(str1)<= 10)应改为if(strlen(str1)<10),因为strlen的结果未统计‟ ‟所占用的1个字节。 剖析: 考查对基本功的掌握: (1)字符串以‟ ‟结尾; (2)对数组越界把握的敏感度; (3)库函数strcpy的工作方式,如果编写一个标准strcpy函数的总分值为10,下面给出几个不同得分的答案: 2分 以下是引用片段: void strcpy(char *strDest, char *strSrc) { while((*strDest++ = * strSrc++)!= „ ‟); } 4分 以下是引用片段: void strcpy(char *strDest, const char *strSrc) //将源字符串加const,表明其为输入参数,加2分 { while((*strDest++ = * strSrc++)!= „ ‟); } 7分 以下是引用片段: void strcpy(char *strDest, const char *strSrc) { //对源地址和目的地址加非0断言,加3分 assert((strDest!= NULL)&&(strSrc!= NULL)); while((*strDest++ = * strSrc++)!= „ ‟); } 10分 以下是引用片段: //为了实现链式操作,将目的地址返回,加3分! char * strcpy(char *strDest, const char *strSrc) { assert((strDest!= NULL)&&(strSrc!= NULL)); char *address = strDest; while((*strDest++ = * strSrc++)!= „ ‟); return address; } 从2分到10分的几个答案我们可以清楚的看到,小小的strcpy竟然暗藏着这么多玄机,真不是盖的!需要多么扎实的基本功才能写一个完美的strcpy啊! (4)对strlen的掌握,它没有包括字符串末尾的' '。 读者看了不同分值的strcpy版本,应该也可以写出一个10分的strlen函数了,完美的版本为: int strlen(const char *str)//输入参数const 以下是引用片段: { assert(strt!= NULL);//断言字符串地址非0 int len; while((*str++)!= ' ') { len++; } return len; } 试题4: 以下是引用片段: void GetMemory(char *p) { p =(char *)malloc(100); } void Test(void) { char *str = NULL; GetMemory(str); strcpy(str, “hello world”); printf(str); } 试题5: 以下是引用片段: char *GetMemory(void) { char p[] = “hello world”; return p; } void Test(void) { char *str = NULL; str = GetMemory(); 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; GetMemory(str); 后的str仍然为NULL; 试题5中 char p[] = “hello world”; return p;的p[]数组为函数内的局部自动变量,在函数返回后,内存已经被释放。这是许多程序员常犯的错误,其根源在于不理解变量的生存期。 试题6的GetMemory避免了试题4的问题,传入GetMemory的参数为字符串指针的指针,但是在GetMemory中执行申请内存及赋值语句 tiffanybracelets *p =(char *)malloc(num); 后未判断内存是否申请成功,应加上: if(*p == NULL) { ...//进行申请内存失败处理 } 试题7存在与试题6同样的问题,在执行 char *str =(char *)malloc(100); 后未进行内存是否申请成功的判断;另外,在free(str)后未置str为空,导致可能变成一个“野”指针,应加上: str = NULL; 试题6的Test函数中也未对malloc的内存进行释放。 剖析: 试题4~7考查面试者对内存操作的理解程度,基本功扎实的面试者一般都能正确的回答其中50~60的错误。但是要完全解答正确,却也绝非易事。 对内存操作的考查主要集中在: (1)指针的理解; (2)变量的生存期及作用范围; (3)良好的动态内存申请和释放习惯。 再看看下面的一段程序有什么错误: 以下是引用片段: swap(int* p1,int* p2) { int *p; *p = *p1; *p1 = *p2; *p2 = *p; } 在swap函数中,p是一个“野”指针,有可能指向系统区,导致程序运行的崩溃。在VC++中DEBUG运行时提示错误“Access Violation”。该程序应该改为: 以下是引用片段: swap(int* p1,int* p2) { int p; p = *p1; *p1 = *p2; *p2 = p; }第五篇:C、C++程序员应聘常见面试题深入剖析