本章内容会给大家展示
求字符串长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
长度受限制的字符串函数介绍
strncpy
strncat
strncmp
字符串查找
strstr
并将这些函数全部模拟出来,带给大家。
这个函数是用来实现求字符串长度的,话不多说我们上代码。
int main()
{
char str[] = "ABCDEFGHIJK";
int sz=strlen(str);
printf("%d", sz);
return 0;
}
#include
int my_strlen(const char* str)
{
assert(str);
int i = 0;
while (*str != '\0')
{
str++;
i++;
}
return i;
}
int main()
{
char str[] = "ABCDEFGHIJK";
int sz=my_strlen(str);
printf("%d", sz);
return 0;
}
我们知道strlen函数是以接收到’\0’为信号来计算的,所以我们传参传过去的是数字名也就是数组首元素地址,在自定义函数中我们只是计算数组长度,并不希望改变原数组,所以我们可以用const来修饰,为了防止穿过来的是空指针,我们用assert函数,不过需要引入一个
strcpy函数是字符串拷贝函数,我们直接看效果,上代码,来模拟。
int main()
{
char str1[] = "************";
char str2[] = "hello world";
strcpy(str1, str2);
printf("%s\n", str1);
return 0;
}
char* my_strcpy(char* str1, const char* str2)
{
char* ret = str1;
assert(str1 && str2);
while ((*str1++ = *str2++))
{
;
}
return 0;
}
int main()
{
char str1[] = "************";
char str2[] = "hello world";
my_strcpy(str1, str2);
printf("%s\n", str1);
return 0;
}
首先,strcpy需要两个参数一个是拷贝数组,一个是拷贝目标数组,而拷贝目标数组我们不希望他被改变所以用const来修饰,为了防止传参过来的是空指针所以两个参数我们都用assert函数来检验。之后再用while循环来实现字符拷贝,因为strcpy函数返回的是拷贝字符串首地址,所以我们设置ret来接受首地址,最后返回ret即可。
strcat是拼接函数,我们依然先看效果。
int main()
{
char str1[20] = "ABCD";
char str2[] = "EFGH";
strcat(str1, str2);
printf("%s", str1);
return 0;
}
char* my_strcat(char* str1,const char* str2)
{
char* ret = str1;
assert(str1 && str2);
while (*str1 != '\0')
{
str1++;
}
while ((*str1++ = *str2++))
{
;
}
return ret;
}
int main()
{
char str1[20] = "ABCD";
char str2[] = "EFGH";
my_strcat(str1, str2);
printf("%s", str1);
return 0;
}
其实,追加函数和拷贝函数的原理很相似,只不过是从拷贝函数的末尾开始拷贝,所以我们设置一个循环,跳过追加目标函数的所有字符从’\0’,开始拷贝,接下来就和strcpy函数一样了。
首先该函数是比较函数其中,str1和str2是要进行比较的字符串。函数返回一个整数值来表示比较结果,返回值的含义如下:
若返回值为 0,表示两个字符串相等;
若返回值小于 0,表示str1小于str2;
若返回值大于 0,表示str1大于str2。
我们先看效果
int main()
{
char str1[] = "ABCD";
char str2[] = "ABCD";
char str3[] = "ABC";
char str4[] = "ABCDF";
int ret1 = strcmp(str1, str2);
int ret2 = strcmp(str1, str3);
int ret3 = strcmp(str1, str4);
printf("%d\n", ret1);
printf("%d\n", ret2);
printf("%d\n", ret3);
return 0;
}
int my_strcmp(const char* str1, const char* str2)
{
int ret = 0;
assert(str1 && str2);
while (!(ret = *(unsigned char*)str1 - *(unsigned char*)str2) && *str2)
{
++str1;
++str2;
}
if (ret < 0)
return -1;
else if (ret > 1)
return 1;
else
return ret;
}
int main()
{
char str1[] = "ABCD";
char str2[] = "ABCD";
char str3[] = "ABC";
char str4[] = "ABCDF";
int ret1 = my_strcmp(str1, str2);
int ret2 = my_strcmp(str1, str3);
int ret3 = my_strcmp(str1, str4);
printf("%d\n", ret1);
printf("%d\n", ret2);
printf("%d\n", ret3);
return 0;
}
我们知道了strcmp的返回值是str1和str2进行比较后得出的,所以函数类型就是int型,在这里只是比较,不希望原字符串有任何改变,所以我们都用const来修饰两个参数,之后我们进入while循环来比较,因为当两个字符串的当前字符相等且尚未到达字符串的结束符时,继续执行循环体,即逐个比较两个字符串的字符,直到出现不同的字符或其中一个字符串到达结束符为止。所以我们设置了这样的循环条件,之后逐个比较str1和str2。
该函数和strcpy函数的区别在于多了一个拷贝字符个数限制的条件,由于效果仅在于拷贝个数的限制,所以我们不在看效果,直接开始模拟。
char* my_strncpy(char* str1, size_t size, const char* str2)
{
char* ret = str1;
assert(str1 && str2);
int i = 0;
while (i < size&&*str2)
{
*str1++ = *str2++;
i++;
}
*str1 = '\0';
return ret;
}
int main()
{
char str1[] = "***************";
char str2[] = "hello world!";
int k = 0;
printf("请输入拷贝字符个数:");
scanf("%d", &k);
my_strncpy(str1, k, str2);
printf("%s", str1);
return 0;
}
我们只需要多加一个size_t的参数,来限制拷贝个数即可,注意拷贝完成后,由于个数的限制没有到达结束,所以我们要令循环结束后的str指针也就是拷贝完成后的str指针所指向的内容是’\0’。
同样的这个函数也只是多了一个追加的个数限制条件。我们直接来模拟这个函数的实现。
char* my_strncat(char* str1, size_t size, const char* str2)
{
char* ret = str1;
assert(str1 && str2);
int i = 0;
while (*str1)
{
str1++;
}
while (i < size&&*str2)
{
*str1++ = *str2++;
i++;
}
*str1 = '\0';
return ret;
}
int main()
{
char str1[20] = "ABCD";
char str2[] = "EFGHIJKL";
int k = 0;
printf("请输入追加字符的个数:");
scanf("%d", &k);
my_strncat(str1, k, str2);
printf("%s", str1);
return 0;
}
同样的,我们在知道了strcat函数的模拟以及strncpy函数的模拟,仅需要添加一个限制追加字符个数,并且将追加循环完成后str1所指向的内容赋值为’\0’即可。 其他的地方基本和上面几个函数的实现相似。
这个函数与strcmp的区别也是多了一个比较个数的限制条件。为了防止大家误会这个函数的效果,我们来看一下这个函数的具体效果,再来模拟实现。
#include
#include
int main() {
char str1[] = "hello";
char str2[] = "world";
int result = strncmp(str1, str2, 3);
if (result == 0) {
printf("前 3 个字符相等\n");
}
else if (result < 0) {
printf("str1 小于 str2\n");
}
else {
printf("str1 大于 str2\n");
}
return 0;
}
#include
#include
int my_strncmp(const char* str1, const char* str2, size_t size)
{
int ret = 0;
assert(str1 && str2);
int i = 0;
while (i < size)
{
ret = *(unsigned char*)str1 - *(unsigned char*)str2;
if (ret != 0)
{
return ret > 0 ? 1 : -1;
}
if (*str1 == '\0')
break;
++str1;
++str2;
i++;
}
return 0;
}
int main()
{
char str1[] = "hello";
char str2[] = "world";
int k = 0;
printf("请输入str1和str2字符比较个数:");
scanf("%d", &k);
int result = my_strncmp(str1, str2, k);
if (result == 0) {
printf("前 3 个字符相等\n");
}
else if (result < 0) {
printf("str1 小于 str2\n");
}
else {
printf("str1 大于 str2\n");
}
return 0;
}
首先也是多了一个限制比较个数的参数,但是有一点不同的是,由于比较完前k个字符,接下来的字符不一定是’\0’,所以我们的代码和实现strcmp有一点不同,一个一个字符来比较即可。
首先我们了解一下strstr函数的作用:
strstr 函数是C语言标准库
函数原型如下:
char* strstr(const char* str1, const char* str2);
strstr 函数接受两个参数:str1 是要搜索的字符串,str2 是要查找的子字符串。
函数返回一个指向 str1 中第一次出现 str2 的位置的指针。如果未找到子字符串,返回 NULL。
来看一下效果:
int main() {
char str1[] = "Hello, World!";
char str2[] = "World";
char* result = my_strstr(str1, str2);
if (result != NULL) {
printf("'%s' 第一次出现在 '%s' 中的位置是:%ld\n", str2, str1, result - str1);
}
else {
printf("'%s' 未在 '%s' 中找到\n", str2, str1);
}
return 0;
}
#include
// 自定义实现 strstr 函数
char* my_strstr(const char* str1, const char* str2) {
assert(str1);
// 如果 str2 为空字符串,则直接返回 str1
if (*str2 == '\0') {
return (char*)str1;
}
// 遍历 str1
while (*str1 != '\0') {
const char* p1 = str1;
const char* p2 = str2;
// 在 str1 中查找 str2
while (*p1 == *p2 && *p1 != '\0') {
p1++;
p2++;
}
// 如果 p2 指向了 str2 的结尾,说明找到了 str2,返回位置
if (*p2 == '\0') {
return (char*)str1;
}
// 在 str1 中继续查找
str1++;
}
// 没有找到 str2,返回 NULL
return NULL;
}
int main() {
char str1[] = "Hello, World!";
char str2[] = "World";
char* result = my_strstr(str1, str2);
if (result != NULL) {
printf("'%s' 第一次出现在 '%s' 中的位置是:%ld\n", str2, str1, result - str1);
}
else {
printf("'%s' 未在 '%s' 中找到\n", str2, str1);
}
return 0;
}
首先,我们需要两个字符串数组参数,在str1中寻找str2,由于我们只是寻找,并不希望原字符串发生改变,所以我们在接受参数时用const来修饰一下,如果str2指向的是空指针那么我们直接返回str1,如果不是进入我们的代码中,遍历str1,我们把str1和str2赋给p1和p2,然后设置一个如果存在才能进入的循环,然后给一个if语句,如果p2解引用等于‘\0’,说明str2到了末尾,也就是找到了,我们返回这个时候的str1指针所指向的位置,之后在if语句外str1++,如果没有碰到str2就遍历str1,这样我们最后遍历完str1,就能知道str2是否存在于str1中了。
相信大家能看出来模拟这些函数有很多地方都是很相似的,那么就分享到这里,各位看客老爷万福金安。