1. C++函数的实现
(1)实现strlen
方法一:
int strlen(const char *StrDest){
assert(StrDest != NULL);
int i, i=0;
while((*StrDest++)!='\0'){
i++;
}//从字符串第一个字符起计数,只遇到字符串结束标志'\0’停止
return i;
}
方法二:
int strlen(const char*StrDest){
assert(NULL != StrDest);
return ('\0'!= *StrDest)?(1+mystrlen(StrDest+1)):0;//递归调用,无需申请全局和局部变量
}
标准库的实现:
size_t __cdecl strlen (const char * str)
{
const char *eos = str;
while( *eos++ ) ;
return( eos - str - 1 );
}
(2)实现strcpy
方法一:
char * strcpy(char *dst,const char *src) { //[1]
assert(dst != NULL && src != NULL); //[2]
char *ret = dst; //[3]
while ((*dst++=*src++)!='\0'); //[4]
return ret;
}
[1]源字符串参数用const修饰,防止修改源字符串。
[2]空指针检查
(A)不检查指针的有效性,说明答题者不注重代码的健壮性。
(B)检查指针的有效性时使用assert(!dst && !src);
char *转换为bool即是类型隐式转换,这种功能虽然灵活,但更多的是导致出错概率增大和维护成本升高。
©检查指针的有效性时使用assert(dst != 0 && src != 0);
直接使用常量(如本例中的0)会减少程序的可维护性。而使用NULL代替0,如果出现拼写错误,编译器就会检查出来。
[3]返回目标地址
(A)忘记保存原始的strdst值。
[4]’\0’
(A)循环写成while (*dst++=*src++);明显是错误的。
(B)循环写成while (*src!=’\0’) *dst++=*src++;
循环体结束后,dst字符串的末尾没有正确地加上’\0’。
关于strcmp:
- 为什么要返回char*类型;
为了实现链式连接。返回内容为指向目标内存的地址指针,这样可以在需要字符指针的函数中使用strcpy,例如strlen(strcpy(str1, str2))。 - 源地址和目标地址出现内存重叠时,如何保证复制的正确性;
内存重叠上面的实现无法完成正常复制。c运行库中strcpy函数实现,还加入了检查内存重叠的机制:
//my_memcpy实现重叠内存转移
char* my_memcpy(char* _Dest, const char* _Source, int count){
//检查传入参数的有效性
assert(NULL != _Dest);
assert(NULL != _Source);
if (NULL ==_Dest || NULL == _Source)
return NULL;
char* ret = _Dest; //记录初始位置
/**
_Dest和_Source的内存地址有三种排列组合:
1. _Dest和_Source没有发生重叠;
2. _Dest的地址大于_Source的地址;
3. _Dest的地址小于_Source的地址;
第一种情况和第三种情况,直接从低位字节开始复制,即可;
第二种情况,必须从高位字节开始复制,才能保证复制正确。
*/
if (_Dest > _Source && _Dest < _Source + count - 1) {
_Dest = _Dest + count - 1;
_Source = _Source + count - 1;
while(count--) {
*_Dest-- = *_Source--;
}
}else{
while(count--) {
*_Dest++ = *_Source++;
}
}
return ret;
}