发布时间:2023-01-26 23:00
简介:
介绍字符串库函数:strlen,strcpy,strcmp,strstr,strcat;
内存库函数:memmove,memcpy的使用和模拟实现
具体用法:
从图中可得知,这是一个获取字符串长度的库函数;从传过来的地址开始依次往后遍历,直到遇到‘\0'时停止;返回遍历过的次数,但不包括’\0‘本身;最后返回一个无符号的整形。
需要注意的是,函数需要的是一个字符串,而字符串中自动会创建一个’\0‘,但如果用的时候创建的是一个由单个组成的字符数组,strlen就没用了,因为没用’\0‘,致使strlen只能不停往后遍历,直到找到’\0‘为止。
得到这些内容我们就可以着手实现它了;
具体实现
三种方法实现
#include
#include
#include
//模拟实现库函数strlen(求字符串长度)
//1.参数部分需要一个被查找字符串首元素的地址
//2.从首元素开始,遇到'\0'时停止,返回一个无符号整形
//#计数器方式实现
size_t my_strlen1(const char* ptr)//const修饰,指针指向的内容不可被修改
{
assert(ptr != NULL);//断言assert不为空指针
int count = 0;
while (*ptr!='\0')
{
ptr++;
count++;
}
return count;
}
//#递归方式实现
size_t my_strlen2(const char* ptr)//const修饰,指针指向的内容不可被修改
{
assert(ptr != NULL);//断言assert不为空指针
if (*ptr != '\0')
{
return 1 + my_strlen2(ptr + 1);
}
else
{
return 0;
}
}
//1+"bcdef"
//1+1+"cdef"
//1+1+1+"def"
//...
//指针-指针方式实现
size_t my_strlen3(const char* ptr)//const修饰,指针指向的内容不可被修改
{
assert(ptr != NULL);//断言assert不为空指针
char* str = ptr;
while (*ptr)
{
ptr++;
}
return ptr - str;//指针减指针得出它俩间元素的个数,且它们指向同一块空间
}
int main()
{
char arr[20] = "abcdef\0ghijklmn";
size_t ret=my_strlen3(arr);
printf("%d\n", (int)ret);
return 0;
}
具体作用:将源字符串的内容拷贝到目标字符串内
函数应该有两个参数,第一个destination为被拷贝的字符串首元素地址,第二个source为源字符串首元素地址,返回类型应该为字符串首元素地址。
需要注意的是被拷贝的字符串必须要有足够的空间接受源字符串,否则程序会越界访问。
具体实现
//模拟实现strcpy(字符串拷贝)
//1.参数部分需要两个地址,返回类型是目标的首元素地址
//2.解引用指针,依次拷贝,在源字符串遇到‘\0’时停止
//3.目标首元素的地址创建一个变量存储,返回它
//#在目标空间不够源字符串拷贝时,依然会打印,但程序会报错(总结来说就是愣头青)
char* my_strcpy(char* arr1,const char* arr2)
{
assert(arr1 && arr2);
char* str = arr1;
while (*arr1++ = *arr2++)
{
;
}
return str;
}
int main()
{
char arr1[20] = { 0 };
char arr2[] = "hello bit";
//printf("%s", strcpy(arr1, arr2));
printf("%s\n",my_strcpy(arr1, arr2));
return 0;
}
具体作用:
函数参数跟strcpy一样,但strcat是在目标字符串后,从’\0‘直接进行追加,并且替换掉’\0‘;
在源字符串遇到’\0‘时停止,’\0‘会追加。
具体实现:
//模拟实现strcat(字符串追加)
//1.参数是两个字符串的首元素地址,返回类型是目标的首元素地址
//2.找到目标字符串‘\0’的位置,源字符串再依次追加,源字符串遇到‘\0’是停止,执行返回
//
char* my_strcat( char* arr1, const char* arr2)
{
assert(arr1 && arr2);
char* str = arr1;
while (*arr1)
{
arr1++;
}
while (*arr2)
{
*arr1 = *arr2;
arr1++;
arr2++;
}
return str;
}
int main()
{
char arr1[20] = "hi! ";
char arr2[] = "hello bit";
printf("%s\n", my_strcat(arr1, arr2));
return 0;
}
具体作用:
比较两个字符串大小,以一个字符的ASCII码进行比较,相等则往后继续,小于则返回<0的数,大于则返回>0的数;当找到一个小于或大于的数时后面不进行比较。
具体实现:
//模拟实现库函数strcmp
int my_strcmp(const char* arr1, const char* arr2)
{
assert(arr1 && arr2);
while (*arr1 == *arr2)
{
if (*arr1 == '\0')
{
return 0;
}
arr1++;
arr2++;
}
return *arr1 - *arr2;
}
int main()
{
char arr1[] = "abcdefg";
char arr2[] = "abcdac";
int ret = my_strcmp(arr1, arr2);
if (ret == 0)
{
printf("相等\n");
}
else if (ret < 0)
{
printf("<\n");
}
else if (ret > 0)
{
printf(">\n");
}
return 0;
}
具体作用:
在字符串1中找字符串2,找到就返回第一次出现的地址,找不到就返回空指针。
具体实现:
char* my_strstr(const char* arr1, const char* arr2)
{
const char* s1 = arr1;
const char* s2 = arr2;
const char* cur = arr1;
assert(arr1 && arr2);
while (*cur)
{
s2 = arr2;
s1 = cur;
while (*s1 && *s2 && (*s1 == *s2))
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cur;
}
cur++;
}
return NULL;
}
int main()
{
char arr1[] = "abbbc";
char arr2[] = "bbc";
char* ret = my_strstr(arr1, arr2);
if (ret == NULL)
{
printf("找不到\n");
}
else
{
printf("%s", ret);
}
return 0;
}
具体作用:
将源字符串的具体字节数num拷贝到目标字符串中,不检测是不是有’\0‘存在
为避免溢出,目标参数和源参数所指向的数组的大小应至少为 num 字节,并且不应重叠
参数为两个void*,一个int,返回类型为void*;
具体实现 :
//模拟实现memcpy(内存拷贝)
//一个字节一个字节移动,循环num次
//强转为char*,再+i
void* my_memcpy(void* ptr1, void* ptr2, int num)
{
assert(ptr1 && ptr2);
void* ret = ptr1;
while (num--)
{
*(char*)ptr1 = *(char*)ptr2;
ptr1 = (char*)ptr1 + 1;//ptr1原来类型为void*
ptr2 = (char*)ptr2 + 1;
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9 };
int arr2[] = { 3,3,3,3,3,3,3,3 };
my_memcpy(arr1, arr2, 20);
int sz = sizeof(arr1) / sizeof(arr1[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}
具体作用:
memcpy的升级版,现在可以拷贝自身的数了
参数为两个void*,一个int,返回类型为void*;
具体实现:
//模拟实现memmove
//循环num次
//在ptr1小于ptr2时,从前向后拷贝;ptr1>ptr2时,从后向前拷贝
void* my_memmove(void* ptr1, void* ptr2, int num)
{
assert(ptr1 && ptr2);
void* ret = ptr1;
if (ptr1 < ptr2)
{
while (num--)
{
*(char*)ptr1 = *(char*)ptr2;
ptr1 = (char*)ptr1 + 1;//ptr1原来类型为void*
ptr2 = (char*)ptr2 + 1;
}
}
else
{
while (num--)
{
*((char*)ptr1 + num) = *((char*)ptr2 + num);
}
}
return ret;
}
int main()
{
int arr1[] = { 1,2,3,4,5,6,7,8,9 };
int arr2[] = { 3,3,3,3,3,3,3,3 };
my_memmove(arr1, arr1+4, 20);
int sz = sizeof(arr1) / sizeof(arr1[0]);
for (int i = 0; i < sz; i++)
{
printf("%d ", arr1[i]);
}
return 0;
}