模拟实现字符串函数
1.1 字符串是一种重要的数据类型,字符串以字符串常量的形式出现或者存储与字符数组中。字符串常量很适用于那些程序不会对他们进行修改的字符串。所有其它字符串都必须存储与字符数组或动态分配的内存中。此次我们描述处理字符串和字符的库函数,以及一组相关的,具有类似能力的既可以处理字符串也可以处理非字符串数据的函数
1.2字符串函数
1.2.1 strlen
strlen函数用于求字符串的长度,就是它所包含的字符个数。先来看一下库函数strlen的原型:
size_t strlen( char const *string);
注:strlen返回一个类型为size_t(无符号整数类型)的值。且传递进来的字符串不做修改所以用const修饰。
接下来我们模拟实现strlen(递归)
#include<stdio.h>
int my_strlen(char *p)
{
if (*p == '\0')
return 0;
else
return 1 + my_strlen(p + 1);//利用递归实现返回元素个数;
}
int main()
{
char arr[] = "abcdefgh";
int sz = sizeof(arr) / sizeof(arr[0]);//求数组中的元素个数
int ret = my_strlen(arr);
printf("%d\n", ret);
}
模拟实现strlen(计数器)
#include<stdio.h>
int my_strlen(char *p)
{
int count = 0;//引入一个监视哨 当p指向‘\0’时循环停止 return count;
while(*p!='\0')
{
p++;
count++;
}
return count;
}
int main()
{
char arr[] = "abcdefgh";
int sz = sizeof(arr) / sizeof(arr[0]);//求数组中的元素个数
int ret = my_strlen(arr);
printf("%d\n", ret);
}
前面提到的strlen返回的是一个size_t的值,所以strlen的返回值是不可以相减的。
例如:
if(strlen(x)>=strlen(y))
{
;
}
if(strlen(x)-strlen(y)>=0)
{
;
}
这两个表达式看上去是相等的,但事实却并非如此。第一条语句将按照我们预想的工作,但是第二条语句的结果将永远是真。因为strlen的结果是个无符号数,所以操作符’>='左边的表达式也将是个无符号数。
1.2.2 模拟实现strcpy(复制字符串)
同样我们先来看一下strcpy的原型:
char *strcpy( char *dest, char const *src);
这个函数把参数src字符串复制到dest参数。由于dest参数将进行修改,所以它必须是个字符数组或者是一个指向动态分配内存的数组的指针,不能使用字符串常量。接下来我们模拟实现strcpy:
#include<stdio.h>
#include<assert.h>
char *my_strcpy(char *dest, const char *src)
{
assert(dest != NULL&&src != NULL);//断言两个指针都不为空
char* ret = dest;//标记复制的起始位置,后续返回用
while (*dest++ = *src++)//将src中的内容逐个复制到dest中;
{
;
}
return ret;
}
int main()
{
char *p = "abcdef";
char arr[10];
my_strcpy(arr, p);//这里传参是传地址
printf("%s\n", my_strcpy(arr, p));
}
1.2.3 模拟实现strcat(连接字符串)
strcat函数实现的功能是将一个字符串添加到另一个字符串的后面它的原型: **char *strcat(char dest, char const src);
strcat函数要求dest参数原先已经包含了一个字符串(也可以是空字符串)。它找到这个字符串的末尾,并把src字符串的一份拷贝添加到这个位置。接下来看模拟实现的代码:
#include<stdio.h>
#include<assert.h>
char *my_strcat(char *dest, const char *src)
{
char *c = dest;//标记dest的起始位置
assert(dest&&src);
while (*dest)//当dest指向的值不为0时,一直向后找,直到找到'\0'的位置停下
{
dest++;
}
while (*dest++ = *src++)//将src指向的内容赋值给(覆盖)dest指向的内容
{
;
}
return c;
}
int main()
{
char arr1[20] = "suojie";
char arr2[] = "so beautiful";
char*ret=my_strcat(arr1, arr2);
printf("%s\n", ret);
}
1.2.4模拟实现strstr(查找一个子串)
为了在字符串中查找一个子串,我们可以使用strstr函数,它的原型如下:
**char *strstr(char const s1, char const s2);
注意:
这个函数在s1中查找整个s2第一次出现的起始位置。并返回一个指向该位置的指针。如果s2并没有完整地出现在s1的任何地方,函数将返回一个NULL指针。
接下来我们模拟实现strstr:
#include<stdio.h>
#include<assert.h>
char *my_strstr(const char *str1,const char *str2)
{
assert(str1&&str2);
char *cp = str1;//标记str的位置,最后进行返回
while (*cp)
{
char *s1 = cp;//常量字符串不能修改,所以做一个临时拷贝 不修改原参数内的任何东西
char *s2 = str2;
while (*s1 == *s2&&*s1&&*s2)//s1、s2指向的位置不为空
//且s1与s2指向的内容相等
{
s1++;
s2++;
}
if (*s2 == '\0')//跳出循环如果s2为空说明已经在s1中匹配完全了s2的内容
return cp;//返回指向我们找到的最后一次匹配的起始位置的指针
cp++;
}
return NULL;
}
int main()
{
char arr[] = "accddfeggh";
char arr1[] = "dfe";
char *ret = my_strstr(arr, arr1);
printf("%s", ret);
}