strcpy(),memcpy(),memmove(),memset(),strcmp(),strstr()的实现
2013-08-12 16:41
519 查看
在C语言中strcpy的原型是char *strcpy(char *dest,const char *src),它的的功能是把src所指由'\0'结束的字符串复制到dest所指的数组中,下面是实现
内存拷贝:memcpy(),函数memcpy(),与strcpy()不同,需要考虑内存重叠的可能。当(pSrc<pDst) && ((char*)pSrc+size > pDst)时,如果拷贝是从头开始正向拷贝,就会在拷贝过程中污染pSrc中还未拷贝的数据。因此在这种情况下必须反向拷贝。实际上在C语言库中,与内存复制有关的函数有两个:memcpy()和memmove()。前者没有考虑内存重叠,而后者考虑了内存重叠。所以使用时需要注意。下面是实现代码(我的实现代码加入了处理内存重叠的情况):
既然要考虑源地址段与拷贝的目标地址段重复的问题,那么为了便于记忆,我们可以不管它是否源地址段与目标地址段重复,我们都可以进行反向拷贝(????????这里是有问题的,见下面memmove()函数的分析)。
memmove()函数分析:下面是以memmove()的例子来说明边界问题的考虑:memmove()实现的算法是将内存中某块固定大小的区域移动到另外一个区域。最常见的写法
·
由于在内存拷贝时会出现目标区域的尾地址落在源区域内这一情况,所以前面在实现memcpy(),函数时不管怎么样都从尾地址开始拷贝,遇到这种情况时就会出问题,所以完整的分析见实现memmove()函数的分析。
void *memset(void *s, int ch, size_t n);将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,
块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向S的指针。:
strcmp()函数的实现:在C语言中int strcmp(char *str1,char * str2),它的功能是比较str1和str2,
当str1<str2,返回值<0
当str1>str2,返回值>0
当str1=str2,返回值=0
char *strcpy(char *dest,const char *src) { assert((NULL != dest) && (NULL != src)); char* pDest = dest; while(*src != '\0') { *pDest++ = *src++; } return dest; }
内存拷贝:memcpy(),函数memcpy(),与strcpy()不同,需要考虑内存重叠的可能。当(pSrc<pDst) && ((char*)pSrc+size > pDst)时,如果拷贝是从头开始正向拷贝,就会在拷贝过程中污染pSrc中还未拷贝的数据。因此在这种情况下必须反向拷贝。实际上在C语言库中,与内存复制有关的函数有两个:memcpy()和memmove()。前者没有考虑内存重叠,而后者考虑了内存重叠。所以使用时需要注意。下面是实现代码(我的实现代码加入了处理内存重叠的情况):
void memcpy(void *pDest,const void *pSrc, int size) { assert((NULL != pDest) && (NULL != pSrc) && (size>=0)); //内存拷贝,参数都是void类型的指针,所以要将其转换成char*类型的指针以便按字节进行拷贝 char* dest = static_cast<char*> (pDest); const char* src = static_cast<const char*> (pSrc); //拷贝的目标地址段与原字符串的地址段有重复,则进行反向拷贝 if(src<dest && (src+size)>dest) { dest = dest+size-1; src = src+size-1; while(size>0) { *dest-- = *src--; size--; } } else//拷贝的目标地址段与原字符串的地址段无重复,则正向拷贝 { while(size>0) { *dest++ = *src++; size--; } } }
既然要考虑源地址段与拷贝的目标地址段重复的问题,那么为了便于记忆,我们可以不管它是否源地址段与目标地址段重复,我们都可以进行反向拷贝(????????这里是有问题的,见下面memmove()函数的分析)。
void memcpy(void *pDest,const void *pSrc, int size) { assert((NULL != pDest) && (NULL != pSrc) && (size>=0)); //内存拷贝,参数都是void类型的指针,所以要将其转换成char*类型的指针以便按字节进行拷贝 char* dest = static_cast<char*> (pDest); const char* src = static_cast<const char*> (pSrc); //为了便于记忆,不管是否源地址段与目标地址段重复,我们从尾端进行拷贝。 dest = dest+size-1; src = src+size-1; while(size>0) { *dest-- = *src--; size--; } }
memmove()函数分析:下面是以memmove()的例子来说明边界问题的考虑:memmove()实现的算法是将内存中某块固定大小的区域移动到另外一个区域。最常见的写法
·
void memmove(void* pDst,const void* pSrc, size_t size) { assert(pDst != NULL); assert(pSrc != NULL); assert(size >= 0); char* pstrSrc=(char*)pSrc; char* pstrDst=(char*)pDst; while(size--) *pstrDst++ = *pstrSrc++; }仔细观察上面程序,会发现有问题。两块内存区域之间由于位置关系可能会发生重叠。重叠通常有三种情况,一是目标区域的首地址落在源区域内;二是目标区域的尾地址落在源区域内;三是两个区域完全重叠。从结果上来看,只有第一种情况才有可能发生与预期不相同的结果,即复制的数据被后续复制数据覆盖的错误。为了解决这个问题,memmove()通常使用反方向复制的方法,从源区域的尾地址开始复制,这样就能避免出现已复制的数据被后续复制覆盖的错误。代码如下:
void memmove(void* pDst,const void* pStr, size_t size) { assert(NULL != pDst); assert(NULL != pStr); assert(size >= 0); //上面的第一种情况,目标区域的首地址落在源区域内,从尾端开始复制 if((pSrc<pDst) && ((char*)pSrc+size > pDest)) { char *pstrSrc = (char*)pSrc + size -1; char *pstrDst = (char*)pDst + size -1; while(size--) *pstrDst-- = *pstrSrc--; } else { char* pstrSrc = (char*)pStr; char* pstrDst = (char*)pDst; while(size--) *pstrDst++ = *pstrSrc++; } }
由于在内存拷贝时会出现目标区域的尾地址落在源区域内这一情况,所以前面在实现memcpy(),函数时不管怎么样都从尾地址开始拷贝,遇到这种情况时就会出问题,所以完整的分析见实现memmove()函数的分析。
void *memset(void *s, int ch, size_t n);将s所指向的某一块内存中的每个字节的内容全部设置为ch指定的ASCII值,
块的大小由第三个参数指定,这个函数通常为新申请的内存做初始化工作, 其返回值为指向S的指针。:
void* Memset(void* buffer, char c, int count) { assert(NULL != buffer && count>=0); //按字节赋值,所以将void*类型的指针转换为char*类型 char* pBuff = static_cast<char*> (buffer); while(count--) { *pBuff++ = c; } return buffer; }
strcmp()函数的实现:在C语言中int strcmp(char *str1,char * str2),它的功能是比较str1和str2,
当str1<str2,返回值<0
当str1>str2,返回值>0
当str1=str2,返回值=0
int strcmp(char *str1,char *str2) { while(*str1&& *str2 && *str1==*str2) { ++str1; ++str2; } return *str1 - *str2; }在C语言里strstr()的原型为:char* *strstr(char *s1,char *s2),他的功能是从字符串s1中寻找s2第一次出现的位置(不比较结束符)返回第一次出现位置的指针。下面是代码:
/*未经过优化过的算法*/ const char* strstr1(const char* s1, const char* s2) { assert(s1 && s2); const char *r = s2,*p; const char *p1 = s1; while('\0' != *p1) { p = p1; r = s2; while(*p == *r) { p++; r++; } if('\0' == *r) { return p1; } else { p1++; } } return NULL; }
/*经过优化过后的算法,加入了很多条件判断*/ const char* strstr2(const char* str1,const char* str2) { assert(NULL != str1 && NULL != str2); const char* ps1 = str1; const char* ps2 = str2; int len1 = strlen(str1); int len2 = strlen(str2); if((len1 == 0) || (len2 == 0)) //两个字符串中有空串则返回NULL return NULL; /*如果str2的长度大于str1的长度,那么在str1中不可能存在str2,直接返回NULL*/ if(len2 > len1) return NULL; while('\0' != *ps1) { while((*ps1 == *ps2) && ('\0' != *ps2)) { ps1++; ps2++; } if('\0' == *ps2)//str2是str1的字串,返回str2在str1中首次出现的位置 { return str1; } else//从str1中的下一个字符开始重新比较,重置ps1和ps2 { ps2 = str2; str1++; ps1 = str1; len1--; } /*此时str1中剩余的字符串已经小于str2的长度,已无法继续查找的必要*/ if(len1<len2) { return NULL; } } return NULL; }
相关文章推荐
- strcpy,strcmp,strstr,strcat,memcpy,memmove,memset的模拟实现
- 模拟实现函数库中的常用函数,1实现strcpy 2.实现strcat 3.实现strstr 4.实现strchr 5.实现strcmp 6.实现memcpy 7.实现memmove,8实现memset
- 模拟实现部分库函数(strcpy,strcmp,strcat,strstr,memcpy,memmove,memset)
- memset,memcpy,memmove,strcpy,strcat,strcmp的实现(其实很简单,每个程序都只有几行代码)
- 字符串处理函数的模拟实现(strlen、strstr、strcat、strcmp、strcpy、memmove、memcpy)
- 【C语言】str类与men库函数的实现(如:strcpy,strcmp,strstr,strcat,memmove,memcpy)
- 模拟实现c库函数strcpy,strcat,strstr,strcmp,memcpy,memmove
- strcpy()、memcpy()、memmove()、memset() 、strcmp()、strlen()、strcat()的实现
- strcat,strcpy,strcmp,strstr,memset,memcpy,strsep在内核中的实现
- 字符串函数的原型实现(strcpy, strcat, strcmp, memset, memcpy, memmove)
- 【C语言】str类与men库函数的实现(如:strcpy,strcmp,strstr,strcat,memmove,memcpy)
- 笔试题 字符串函数的实现(strcpy, strcat, strcmp, memset, memcpy, memmove)
- 模拟实现strstr,strcpy,strlen,strcat,strcmp,memcpy,memmove
- 模拟实现strcmp,strncmp,strstr,strcat,strncat,strcpy,strncpy,strlen ,memcpy,memmove等函数
- 模拟实现字符串操作函数(strcpy,strstr,strcat,strcmp,strlen)与内存操作函数(memcpy,memmove)
- memcmp,memcpy,memmove,memset,strcat,strcmp,strcpy,strlen 8个函数的实现
- 字符串函数模拟实现(strcpy,strcat,strstr,strchr,strcmp,memcpy,memmove)
- 模拟实现strstr,strcpy,strlen,strcat,strcmp,memcpy,memmove
- 模拟实现strlen,strcpy,strcat,strstr,strcmp,memcpy,memmove
- 模拟实现strcpy、strcat、strstr、strchr、strcmp、memcpy、memmove