1.strlen 的模拟实现
//方法一:计数器
//用count计数,记录parr不等于'\0'之前的一共跑了几次,就是字符串的长度
int my_strlen(char* parr)
{
assert(parr);
int count = 0;
while (*parr)
{
parr++;
count++;
}
return count;
}
//方法二:指针相减
//相同类型的指针相减,得数是两个指针之间的元素个数
int my_strlen(char* parr)
{
assert(parr);
char* ret = parr;
while (*parr)
{
parr++;
}
return parr - ret;
}
2.strcpy的模拟实现
//++优先级大于解引用*,且后置++先使用再++,所以在while循环的判断中,先将parr2赋值给parr1
//后,再解引用,然后将+1后的parr2再次赋值给parr1后,进行解引用,以此类推
//直到parr2指向'\0',赋值给parr1,两者均为'\0',跳出循环;
char* my_strcpy(char* parr1, const char* parr2)
{
assert(parr1 && parr2);
char* ret = parr1;
while (*parr1++=*parr2++)
{
;
}
return ret;
}
3.strcat的模拟实现
strcat是字符串追加函数,是在一个字符串后再继续追加想要添加的字符串,模拟代码如下:
//先找到被追加的字符串的'\0'
//从该位置开始加入需要添加的字符串parr2;
char* my_strcat(char* parr1, const char* parr2)
{
assert(parr1 && parr2);
char* ret = parr1;
while (*parr1)
{
parr1++;
}
while (*parr2)
{
*parr1++ = *parr2++;
}
return ret;
}
4.strcmp的模拟实现
//strcmp函数,比较的是字符的ASCII码值,parr1比parr2大,返回正值,小返回负值,等于返回0;
int my_strcmp(const char* parr1, const char* parr2)
{
assert(parr1 && parr2);
while (*parr1==*parr2)
{
if (*parr1 == '\0'||*parr2=='\0')
{
return 0;
}
parr1++;
parr2++;
}
return *parr1 - *parr2;
}
5.strncpy的模拟实现
char *strncpy(char *dest, const char *src, size_t n)
strncpy把源字符串的字符复制到目标数组。然而,它总是正好向dest写入n个字符。如果strlen(src)的值小于n,dst数组就用额外的NUL字节填充到len长度,如果strlen(src)的值大于或等于len,那么只有len个字符被复制到dst中。”注意!它的结果将不会以NUL字节结尾。(NUL即‘\0’).
即:如果parr1一开始未被初始化成0,则必须手动添加'\0'
//也就是说,通过对比parr2的长度和num的大小,判断以什么作为循环的标准;
char* my_strncpy(char* parr1, const char* parr2,size_t num)
{
size_t len = strlen(parr2);
assert(parr1 && parr2);
if (len <= num)
{
char* ret = parr1;
while (len--)
{
*parr1++ = *parr2++;
}
*parr1 = '\0';
return ret;
}
else
{
char* arr = parr1;
while (num--)
{
*parr1++ = *parr2++;
}
*parr1 = '\0';
return arr;
}
}
6.strstr的模拟实现(寻找字串的函数)
返回源字符串中的第一个子串的位置处
char* my_strstr(const char* parr1, const char* parr2)
{
assert(parr1 && parr2);
const char* cp = parr1;
char* s1 = NULL;
char* s2 = NULL;
while (*cp)
{
const char*s1 = cp;
const char*s2 = parr2;
while (*s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cp;
}
cp++;
}
return NULL;
}
7.strtok函数
char * strtok (char *str, const char * delim);
当strtok()在参数str的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数str字符串,往后的调用则将参数str设置成NULL。每次调用成功则返回指向被分割出片段的指针,具体代码使用如下图所示:
int main()
{
char arr[] = "aa&bbb.c12c&ddd";
char arr1[50] = { 0 };
strcpy(arr1, arr);
const char* ret = "&.";
char* str = NULL;
for (str = strtok(arr1, ret); str != NULL; str = strtok(NULL, ret))
{
printf("%s\n", str);
}
return 0;
}
//strtok为分割字符串的函数,首次调用时,s指向要分解的字符串,之后再次调用要把s设成NULL
8.内存操作函数memcpy的模拟实现
//memcpy函数是字符串拷贝函数,从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存
//地址的起始位置中
//memcpy与strcpy有以下不同:
//1.可以拷贝的内容不同。strcpy只能拷贝字符串,而memcpy不限制类型,字符数组、整型、结构体、类等。
//2.拷贝的方法不同。strcpy遇到被复制字符串的'\0'结束,memspy由第三个参数决定复制的长度,即受到长度
//限制
void* my_memcpy(void* dest, const void* src, size_t sum)
{
assert(dest && srckaobei);
void* ret = dest;
while (sum--)
{
*((char*)dest)++ = *((char*)src)++;
}
return ret;
}
9.内存操作函数memmove的模拟实现
//memmove不用考虑内存覆盖的问题,是memcpy的进化版
//即目标在前,从前往后拷贝,目标在后,从后往前拷贝
void* my_memmove(void* dest, const void* src, size_t sum)
{
void* ret = dest;
if (dest < src)
{
int i = 0;
while (sum--)
{
*((char*)dest+i) = *((char*)src+i);
i++;
}
}
else
{
while (sum--)
{
*((char*)dest+sum) = *((char*)src+sum);
}
}
return ret;
}
10.内存操作函数memset
memset() 函数是初始化内存的函数,通常为新申请的内存进行初始化,它是直接操作内存空间的
void *memset(void *str, int num, size_t n)
将指针变量 str 所指向的前 n 字节的内存单元用一个“整数” num 替换,num 是 int 型。str 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。memset 函数的第三个参数 n 的值一般用 sizeof() 获取。