这篇博客是我自己对字符串操作库函数的模拟实现,包括(长度不受限制[^1])的操作函数 strlen()、strcmp()、strcat()、strstr(),以及 memcpy()、memmove(). 这些函数都来源于<string.h>.
strlen()
函数介绍
作用: 计算字符串长度 函数原型:size_t strlen( const char *string ); 参数: string 以’\0’结尾的字符串 类型: const char* 因为不会修改字符串,因此用const修饰 返回值: 返回字符串中的字符数,不包括’\0’。没有返回则说明发生错误错误。size_t[^2] 指的是无符号整型。
函数实现
int my_strlen(const char* str)
{
assert(str != NULL);
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char str[] = "abcdefg";
printf("%d ", my_strlen(str));
return 0;
}
strcmp()
函数介绍
作用: 比较两个字符串的长度大小。 函数原型: int strcmp( const char *string1, const char *string2 ); 参数: string1、string2 都是以’\0’结尾的字符串 类型: const char* 不会修改字符串,因此用const修饰 返回值: int整型:如果string1长,返回>0的数;如果string2长,返回<0的数;如果两字符串长度相等,返回0。
函数实现
int my_strcmp(const char* str1, const char* str2)
{
while (*str1 == *str2)
{
if (*str1 == '\0')
return 0;
str1++;
str2++;
}
if (*str1 > *str2)
{
return 1;
}
else
{
return -1;
}
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "abd";
char arr3[] = "Hello World!";
char arr4[] = "Hello World!";
int ret = my_strcmp(arr1, arr2);
printf("%s %s %d\n", arr1, arr2, ret);
int ret1 = my_strcmp(arr3, arr4);
printf("%s %s %d\n", arr3, arr4, ret1);
return 0;
}
strcat()
函数介绍
作用: 把一个字符串追加到一个字符串后面。 函数原型: char *strcat( char *strDestination, const char *strSource ); 参数: strDestination、strSource 都是以 ‘\0’ 结尾的字符串。destination是目的地的意思,所以strDestination指的是要被追加的字符串,strSource指的是追加的内容。 类型: strDestination会被修改,所以是char* 类型;const char* 不会修改字符串,因此用const修饰 返回值: char*类型变量,是strDestination字符串的地址。
函数实现
char* my_strcat(char* str1, const char* str2)
{
assert(str1 != NULL);
assert(str2 != NULL);
char* ret = str1;
while (*str1)
{
str1++;
}
while (*str1++ = *str2++)
{
;
}
return ret;
}
int main()
{
char arr1[20] = "Hello ";
char arr2[] = "World!";
printf("%s ", my_strcat(arr1, arr2));
return 0;
}
strstr()
函数介绍
作用: 判断一个字符串中是否包含另一个字符串 函数原型: char *strstr( const char *string, const char *strCharSet ); 参数: string、strCharSet 都是以 ‘\0’ 结尾的字符串。 类型: const char* 不会修改字符串,因此用const修饰 返回值: 函数返回一个指针,指向string字符串中第一个出现的strCharSet,如果strCharSet没有出现在字符串中,则返回NULL。如果strCharSet指向长度为零的字符串,则函数返回string。
函数实现
char* my_strstr(const char* str1, const char* str2)
{
assert(str1 != NULL);
assert(str2 != NULL);
const char* s1 = str1;
const char* s2 = str2;
const char* cp = str1;
if (*s2 == '\0')
return (char*)str1;
while (*cp != '\0')
{
s1 = cp;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return (char*)cp;
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abcdefghi";
char arr2[] = "cde";
printf("%s", my_strstr(arr1, arr2));
return 0;
}
memcpy()
函数介绍
作用: 拷贝一块内存上的数据到另一块内存,因此称为内存拷贝函数 函数原型: void *memcpy( void *dest, const void *src, size_t count ); 参数: dest: destination的缩写,指的是目标内存;src:source的缩写,指的是要拷贝的内存;count:指的是要拷贝的内容的字节数。 类型: void*: void* 可以接收各种类型的指针变量,因为事先是不知道要输入哪种类型的指针; const void* 不会修改该内存上的值,因此用const修饰;size_t: 因为拷贝是逐字节拷贝的,所以要传入需要拷贝的字节数 返回值: dest的地址。
函数实现
void* my_memcpy(void* dest, void* src, int count)
{
assert(dest != NULL);
assert(src != NULL);
void* ret = dest;
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
return ret;
}
int main()
{
char arr1[20] = { 0 };
char arr2[] = "Hello World!";
printf("%s ", my_memcpy(arr1, arr2, sizeof(arr2)));
return 0;
}
memmove()
函数介绍
作用: 拷贝一块内存上的数据到另一块内存,但是memcpy函数的区别是:这memmove可以从同一个字符串上拷贝,也就是说可以把一个字符串上的部分内容拷贝到另一部分 函数原型: void *memcpy( void *dest, const void *src, size_t count ); 参数: dest: destination的缩写,指的是目标内存;src:source的缩写,指的是要拷贝的内存;count:指的是要拷贝的内容的字节数。 类型: void*: void* 可以接收各种类型的指针变量,因为事先是不知道要拷贝哪种类型的数据; const void* 不会修改该内存上的值,因此用const修饰;size_t: 因为拷贝是逐字节拷贝的,所以要传入需要拷贝的字节数 返回值: dest的地址。
在实现这个函数之前,我们需要明确拷贝过程中会遇到的两种情况。
- 情况一:dest指向的地址在src之前。
如果我们要把红框中的四个数据拷贝到绿框中去,那么从src指向的地址开始(从前往后),逐字节往dest指向的地址处拷贝就行。 - 情况二:dest指向的地址在src之后。
和上面一样,我们要把红框中的数据拷贝到绿框中去,此时如果继续从src指向的地址开始,从前往后逐字节往dest指向的地址拷贝数据的话,会覆盖掉红框后面的数据,我们本来的设想是把数字5放到数字8的位置,从前往后拷贝最终会导致将数字2放到数字8的位置。所以我们应该从后往前拷贝,也就是说先把数字5放到8的位置,然后把4放到7的位置,以此类推。
代码实现
void* my_memmove(void* dest, void* src, int count)
{
assert(dest != NULL);
assert(src != NULL);
void* ret = dest;
if (dest < src)
{
while (count--)
{
*(char*)dest = *(char*)src;
dest = (char*)dest + 1;
src = (char*)src + 1;
}
}
else
{
while (count--)
{
*((char*)dest + count) = *((char*)src + count);
}
}
return ret;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
my_memmove(arr + 2, arr + 5, 4 * sizeof(int));
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
printf("%d ", arr[i]);
}
return 0;
}
结语
除了上述几个函数,还有一些函数会在后续自己实现。因为最近比较忙,所以隔了这么久才写了这篇博客,其实我有很多想记录的内容。以后要是有时间,我就会写写博客,很多东西在输出的时候才会发现自己有没有理解。最后,如果内容有问题,恳请指正!
|