面试中经典函数的实现
来源:互联网 发布:oracle sql高级编程 编辑:程序博客网 时间:2024/05/16 13:57
很多经典的库函数如strcpy,memcpy等在面试中经常出现,虽然思想并不复杂,但要写出一个比较完善甚至是完全正确的程序非常考验一个程序员思维的严谨性和编程的风格,这里简单实现strcpy、strncpy、memcpy、memmove、memset、strlen等函数,仅供参考。
一 字符串复制strcpy
strcpy函数把一个字符串的内容复制到另一个字符串里,以'\0'作为结束符。实现时需要注意对const参数、参数检验,返回指针等几个方面。
另外还有一个跟strcpy类似的函数strncpy。strncpy在字符串复制时最多复制size个字符,即使没有遇到src的终止符'\0'。当src长度不够size时,效果跟strcpy完全一样。strncpy的实现跟strcpy类似,如下所示:
二 内存拷贝memcpy
关于内存拷贝的库函数有memcpy和memmove,二者均可以把src内存复制到dst内存中,并且一共复制size个字节。但是memcpy不考虑内存区域重叠的问题,当二者内存冲突时,函数的行为是未定义的。memmove是则考虑了这个问题,保证了复制之后的dst一定跟复制之前的src一致。
当自己实现memcpy时需要注意函数对内存重叠的情况有什么要求,必要时直接使用更完整的memmove的实现方式。
下面是没有检查内存重叠的实现:
下面是考虑了内存重叠之后的实现,也就是memmove的实现:
三 内存初始化memset
memset把buffer开始的连续size个字节全部初始化为字符c。使用时注意这里是以字节为单位进行的。
注意不要在类的构造函数里使用memset函数,因为有些类中含有虚表虚指针,使用memset会改变他们的值,造成程序运行的错误。
四 字符串长度strlen
strlen求取一个字符串的长度,以'\0'作为结束符,以下介绍几种简单的实现方法。
下面是不使用任何其他变量实现的版本,使用递归实现。
一 字符串复制strcpy
strcpy函数把一个字符串的内容复制到另一个字符串里,以'\0'作为结束符。实现时需要注意对const参数、参数检验,返回指针等几个方面。
char*strcpy(char*dst,constchar*src)//const约束,内容不可变{ assert((src!=NULL)&&(dst!=NULL));//参数非0检验 char *add=dst;//保存dst while((*dst++=*src++)!='\0') { /*do nothing*/ } returnadd;//返回dst,允许链式表达式}
另外还有一个跟strcpy类似的函数strncpy。strncpy在字符串复制时最多复制size个字符,即使没有遇到src的终止符'\0'。当src长度不够size时,效果跟strcpy完全一样。strncpy的实现跟strcpy类似,如下所示:
char*strncpy(char*dst,constchar*src,size_tsize){ assert((src!=NULL)&&(dst!=NULL)); char *add=dst; inti=0;// 控制复制的个数 while(i++<size&&(*dst++=*src++)!='\0') { /*do nothing*/ } if(*(--dst)!='\0')//注意字符串以'\0'结尾 { *dst='\0'; } returnadd;}
二 内存拷贝memcpy
关于内存拷贝的库函数有memcpy和memmove,二者均可以把src内存复制到dst内存中,并且一共复制size个字节。但是memcpy不考虑内存区域重叠的问题,当二者内存冲突时,函数的行为是未定义的。memmove是则考虑了这个问题,保证了复制之后的dst一定跟复制之前的src一致。
当自己实现memcpy时需要注意函数对内存重叠的情况有什么要求,必要时直接使用更完整的memmove的实现方式。
下面是没有检查内存重叠的实现:
void*memcpy1(void*dst,constvoid*src,size_tsize)//const约束,内容不可变{ assert((src!=NULL)&&(dst!=NULL));//参数非0检验 char *pDst=(char*)dst; const char *pSrc=(constchar*)src; while(size-->0) { *pDst++=*pSrc; } returndst;//返回dst,允许链式表达式}
下面是考虑了内存重叠之后的实现,也就是memmove的实现:
void*memcpy2(void*dst,constvoid*src,size_tsize)//const约束,内容不可变{ assert((src!=NULL)&&(dst!=NULL)); //参数非0检验 if(src<dst&&(char*)src+size> (char*)dst)//地址重叠 { char *pDst=(char*)dst+size-1; //从后向前复制 const char *pSrc=(constchar*)src+size-1; while(size-->0) { *pDst--=*pSrc--; } } else { char *pDst=(char*)dst;//从前向后复制 const char *pSrc=(char*)src; while(size-->0) { *pDst++=*pSrc++; } } returndst;//返回dst,允许链式表达式}
三 内存初始化memset
memset把buffer开始的连续size个字节全部初始化为字符c。使用时注意这里是以字节为单位进行的。
注意不要在类的构造函数里使用memset函数,因为有些类中含有虚表虚指针,使用memset会改变他们的值,造成程序运行的错误。
void* memset(void*src,intc,size_tsize){ assert(src!=NULL); char *pSrc=(char*)src; while(size--) { *pSrc++=(char)c;//转化为char } returnsrc;}
四 字符串长度strlen
strlen求取一个字符串的长度,以'\0'作为结束符,以下介绍几种简单的实现方法。
intstrlen1(constchar*src){ assert(src!='\0'); int len=0;//长度计数 while((*src++)!='\0') { len++; } returnlen;} intstrlen2(constchar*src){ assert(src!='\0'); const char *pSrc=src; while((*pSrc++)!='\0') { /*Do nothing*/ } returnpSrc-src-1;//使用指针计算长度}
下面是不使用任何其他变量实现的版本,使用递归实现。
intstrlen3(constchar*src){ assert(src!=NULL); return *src=='\0'?0:(1+strlen3(++src));}
0 0
- 面试中经典函数的实现
- 淘宝面试-Strcpy与memcpy两函数的经典实现
- 面试的经典问题--函数中开空间
- 面试中经典的算法
- 面试中memcopy函数实现中的陷阱!
- 【面试经典题之字符串】用C或C++写一个函数,实现反转一个null结尾的字符串
- 简单实现C中sizeof函数是怎么实现的(面试的时候可能用到)
- 经典面试题目--在C++ 程序中调用被C 编译器编译后的函数,为什么要加extern “C”?
- 经典的strcpy 的函数实现
- 面试的经典问题
- 面试的经典问题
- 经典的面试回答
- 【LeetCode-面试算法经典-Java实现】【028-Implement strStr() (实现strStr()函数)】
- strcpy函数的实现【面试攻略】
- 面试中可能用到的英语(经典收藏)
- 面试中常见的五个问题经典分析(转载)
- 雅思口语面试中大放异彩的经典长句
- 分享Java面试中遇到的一些经典算法题目
- 框架搭建---文件目录结构
- 初探单例模式学习笔记
- ubuntu 13.10 安装 ia32-libs
- checkio -- Open Labyrinth python BFS的使用
- 虚数 计算圆形面积
- 面试中经典函数的实现
- WIN 64位VirtualBox安装Ubuntu 13.10,重启Ubuntu后黑屏
- Python中的数据对象
- C# 文档编辑器中查找替换的实现(自定义事件)
- Andrew Ng 机器学习(2.1)--线性回归--原理
- forward与sendRedirect区别
- STL操作总结
- JBOSS修改端口号
- Windows socket之IO完成端口(IOCP)模型开发