c语言实现C++字符串操作的相关函数
利用C语言实现一些常见的C++字符串操作的相关函数。
1.strcmp函数
int _strcmp(const char *s1, const char *s2)
{
int ret = 0;
while (!(ret = *( unsigned char *)s1 - *( unsigned char*)s2) && *s1) //使用*(unsigned char*)s1而不是用(*s1)。这是因为传入的参数为有符号数
{
s1++;
s2++;
}
if (ret < 0)
ret = -1;
else if (ret > 0)
ret = 1;
return ret;
}
2.stract函数
char *_strcat( char *s1, const char *s2)
{
char *s = s1; //返回值保存,下面的操作会改变目的指针指向,先定义一个指针记录s1
assert((s1 != NULL)&& (s2 != NULL));
while (*s) //是while(*s!=’\0’)的简化形式
s++; //若使用while(*s++),则会出错,因为循环结束后s还会执行一次++,那么s将指向'\0'的下一个位置。所以要在循环体内++;因为要使*s最后指向该字符串的结束标志’\0’
while (*s++ = *s2++) ; //也可行:while ((*s++ = *s2++) != '\0')
return s1;
}
3.strlen函数
int _strlen(const char *s)
{
int len = 0;
if (NULL != s)
{
while (*s++ != '\0')
{
len++;
}
return len;
}
return len;
}
4.strcpy函数
char *_strcpy( char *s1, const char *s2)
{
char* s = s1;
assert((s1 != NULL) && (s2 != NULL));
while ((*s++ = *s2++) != '\0'); //赋值表达式返回左操作数,所以在赋值'\0'后,循环停止
return s1;
}
5.memcpy函数
void *_memcpy(void *s1, const void *s2, size_t count) //未考虑复制效率与内存重叠,可优化
{
assert((s1 != NULL) && (s2 != NULL));
char *s1_tmp = (char *)s1;
const char *s2_tmp = (char *)s2;
while (count--)
*s1_tmp++ = *s2_tmp++;
return s1;
}
5.memcpy函数优化1
//memcpy函数改进版1,考虑复制效率
void * update1_memcpy(void *s1, const void *s2, size_t count)
{
assert((s1 != NULL) && (s2 != NULL));
//64位电脑能够一次性处理8字节数据
int nchunks = count / 8;
int slice = count % 8;
double * s2_tmp = (double *)s2; //double占8个字节,若s2_tmp+1则地址在s2_tmp的基础上移动8个字节
double * s1_tmp = (double *)s1;
while (nchunks--) //一次性复制8个字节数据
{
*s1_tmp++ = *s2_tmp++;
}
char *s1_temp = (char *)s1_tmp; //剩余小于8字节的数据按照1字节的长度进行复制
char *s2_temp = (char *)s2_tmp;
while (slice--)
{
*s1_temp++ = *s2_temp++;
}
return s1;
}
6.memcpy函数优化2
//memcpy函数改进版2,考虑复制内存重叠
//s1<s2情况,执行函数操作有可能会改变原始数据s2,但对s1数据不影响
//s1>s2情况,就需要考虑重叠问题,当s1<=s2+count情况下,s1与s2数据执行函数后都会改变
void * update2_memcpy(void *s1, const void *s2, size_t count)
{
assert((s1 != NULL) && (s2 != NULL));
char *s1_temp = (char*)s1;
const char *s2_temp = (const char*)s2;
if ((s1_temp > s2_temp + count) || (s1_temp < s2_temp))
{
while (count--)
*s1_temp++ = *s2_temp++;
}
else //overlap情况下需要从高地址处向前copy
{
char *s1_temp_h = s1_temp + count - 1;
const char *s2_temp_h = s2_temp + count - 1;
while (count--)
*s1_temp_h-- = *s2_temp_h--;
}
return s1;
}