首先,我们在这里讲一下字符串的两种定义方法
char str1[8] = "hello";
char* str2 = "cpp";
str1是数组, 可以改变数组空间里的值。
str2是指针,是指向cpp这个空间的,那么它是不能改变cpp那个空间的值的,因此我们在对字符串进行操作的话,我们一边是对数组进行操作的话。
1、size_t my_strlen(const char* string);这是对字符串求长度的函数,我们都知道字符串的结束标记是'\0',对于用strlen()求字符串长度是不包含'\0'的,这是很重要的。
void main()
{
char str1[20] = "hello";
char* str2 = "cpp";
int len1=strlen(str1);
int size1=sizeof(str1);
int len2 = strlen(str2);
int size2 = sizeof(str2);
printf("len1=%d\n", len1);
printf("len2=%d\n", len2);
printf("size1=%d\n", size1);
printf("size2=%d\n", size2);
}
那我们如何对strlen()函数进行实现呢?我们可以用两种方法对strlen()进行实现。
第一种是用中间变量count进行技术,当string没有遇到’\0'时count++,否则就退出。
size_t my_strlen(const char* string)
{
int count = 0;
while(*string !='\0')
{
count++;
string++;
}
return count;
}
void main()
{
char *str2 = "hellocpp";
my_strlen(str2);
printf("str2 len=%u\n", my_strlen(str2));
}
第二种使用递归的方式,递归的方式一定要记得进行加1,因为当*string!='\0'时此时也满足条件。
//函数递归
size_t my_strlen(const char* string)
{
if (*string == '\0')
return 0;
return my_strlen(string + 1) + 1;
}
void main()
{
char* str2 = "hellocpp";
my_strlen(str2);
printf("str2 len=%u\n", my_strlen(str2));
}
2、char* my_strcpy(char *strDestination, const char *strSource);字符串的拷贝函数 ,是将
char *strSource所指的字符串常量拷贝到char *strDestination里面。我们对这个函数进行实现。
char* my_strcpy(char *strDestination, const char *strSource)
{
//判断参数的有效性
assert(strDestination != NULL && strSource != NULL);
//保护参数
char* p1 = strDestination;
const char* p2 = strSource;
//进行拷贝
while (*p2 != '\0')
{
*p1++ = *p2++;
}
//拷贝结束标记
*p1=*p2;
//返回目标指针
return strDestination;
}
void main()
{
char str1[20] = "hello";
char *str2 = "cpp";
char *res=my_strcpy(str1, str2);
printf("%s\n", res);
}
这里面五个步骤都是很重要的
(1)用assert()判断参数的有效性。
(2)对参数进行保护,因为对于这个拷贝函数来说,他要返回一个char*,因此我们不希望对strDestination进行改变,因此我们要用一个指针p1和strDestination指向相同的空间,对p1进行空间里字符进行操作。最终返回strDestination,得到我们想要的结果。
(3)进行拷贝操作。
(4)拷贝结束标记'\0',这是非常重要的,如果不拷贝结束标记有可能会生成随机数或和我们想要的结果不一样。
(5)返回目标指针。这里注意不能返回p1。
3、strcant 字符串的链接函数
char* my_strcat(char* strDestination, const char* strSource)是将strSource连接到strDestination里面。下来我们对这个函数进行实现。
char* my_strcat(char* strDestination, const char* strSource)
{
//判断参数的有效性
assert(strDestination != NULL && strSource != NULL);
//保护参数
char* p1 = strDestination;
const char* p2 = strSource;
//进行链接
while (*p1 != '\0')
{
p1++;
}
while (*p2 != '\0')
{
*p1++ = *p2++;
}
//结束标记拷贝
*p1 = *p2;
//返回目标指针
return strDestination;
}
void main()
{
char str1[20] = "hello";
char* str2 = "cpp";
char* res = my_strcat(str1, str2);
printf("%s\n", res);
}
这个上面也包含了五个步骤,和上面讲解的内容差不多。
4、strcmp 字符串的比较函数实现
int my_strcmp(const char* string1, const char* string2)将string1所指向的字符串和string2所指向的字符串进行比较。下来我们对这个函数实现。
int my_strcmp(const char* string1, const char* string2)
{
//判断参数的有效性
assert(string1 != NULL & string2 != NULL);
//进行比较
while (*string1 != '\0' && *string2 != '\0')
{
if (*string1 > *string2)
return 1;
else if (*string1 < *string2)
return -1;
string1++;
string2++;
}
if (*string1 == '\0')
return -1;
if (*string2 == '\0')
return 1;
return 0;
}
void main()
{
char *str1 = "hello";
char* str2 = "helloooo";
int res = my_strcmp(str1, str2);
printf("%d\n", res);
}
string1>string2则返回一个大于0的数;
string1<string2则返回一个小于0的数;
string1=string2则返回0。
在这里边就不用对参数进行保护,因为返回的是一个整型的数。而且在主函数中我们可以定义两个指针指向字符串常量也可以定义两个字符类型的数组。
5、strncmp 函数这里比strcmp多了一个n,这里的n表示将两个字符串的前n个字符进行比较。
int my_strncmp(const char* string1, const char* string2, size_t count)这里就是将两个字符串的前count的字符串进行比较。下面我们对这个函数进行实现。
int my_strncmp(const char* string1, const char* string2, size_t count)
{
assert(string1 != NULL & string2 != NULL);
while (count != 0)
{
if (*string1 - *string2 != 0)
break;
string1++;
string2++;
count--;
}
return *string1 -* string2;
}
void main()
{
char* str1 = "hello";
char* str2 = "helloooo";
int res = my_strncmp(str1, str2,8);
printf("%d\n", res);
}
同理我们可以对strncpy和dtrncat分别进行实现。
6、strncpy 函数的实现
char* my_strncpy(char* strDest, const char* strSource, size_t count)
//strncpy 函数的实现
char* my_strncpy(char* strDest, const char* strSource, size_t count)
{
//判断参数有效性
assert(strDest != NULL && strSource != NULL);
//保护参数
char *p1 = strDest;
const char *p2 = strSource;
//进行拷贝
while (count-- != 0)
{
*p1++ = *p2++;
count--;
}
return strDest;
}
void main()
{
char str1[20] = "hello";
char* str2 = "cpp";
char* res = my_strncpy(str1, str2,2);
printf("%s\n", res);
}
7、strncat 函数的实现
char* my_strncat(char* strDest, const char* strSource, size_t count)
//strncat 函数的实现
char* my_strncat(char* strDest, const char* strSource, size_t count)
{
//判断参数的有效性
assert(strDest != NULL && strSource != NULL);
//保护参数
char* p1 = strDest;
const char* p2 = strSource;
//进行操作
//先找末尾
while (*p1 != '\0')
{
p1++;
}
while (count != 0)
{
*p1++ = *p2++;
count--;
}
return strDest;
}
void main()
{
char str1[20] = "hello";
char* str2 = "cpp";
char* res = my_strncat(str1, str2,1);
printf("%s\n", res);
}
8、strstr()这是字符串查找的函数
char* my_strstr(const char* string, const char* strCharSet)在string所指的字符串里面找是否有strCharset所指的字符串,如果有,将包含strCharSet和后面的字符串返回。因此我们在这里还是要对字符串的指针进行保护。下面是对这个函数的实现。我们下面是一个一个字符的查找,找到就返回,找不到向后移一个位置继续查找。也称暴力查找,学过数据结构的同学,应该知道还有KMP算法,这里先不讲解,你们可以自己写一下。
//下边是对字符串操作的函数
//strstr 函数的实现
char* my_strstr(const char* string, const char* strCharSet)
{
//判断参数的有效性
assert(string != NULL && strCharSet != NULL);
//保护参数
const char* p1 = string;
const char* p2 = strCharSet;
//开始查找
while (*p1!= '\0')
{
//对参数进行保护
char* p3 = p1;
//当相等时继续向后查找
while (*p1 == *p2)
{
p1++;
p2++;
}
//找到了将从p3位置往后的字符串进行返回
if (*p2=='\0')
{
return p3;
}
//没找到返回NULL
if (*p1=='\0')
{
return NULL;
}
p1++;
}
return NULL;
}
void main()
{
char* str1 = "hello";
char* str2 = "ell";
char* res =my_strstr(str1, str2);
printf("%s\n", res);
}
我就先对这几个函数进行实现,后边我会对memcpy()函数实现 ,memmove函数()实现,
memcat()函数实现,memcmp()函数等函数进行实现。
希望大家可以多多提出建议,我会认真改正。