【C语言】字符串函数分析及模拟实现(万字详解!)


前言

在以前的学习我们掌握了基础的字符函数类型,知道了一些字符串函数如何使用,但不知道具体函数是如何实现的。本篇文章将系统介绍讲解C语言中的字符串函数。通过简洁高效的代码,为友友提供一个清晰明了的讲解,让我们开始吧!


前提!!在使用字符串函数前都要引用头文件#include<string.h>!!!

1.求字符串长度的字符函数

1.1strlen

strlen函数介绍

先看看C语言编译库是如何定义strlen函数的。

在这里插入图片描述
(不知道如何查询C语言编译库可以看我的这期博客,里面有提到 : qsort函数

根据定义我们知道是将目标字符串的首元素地址传给strlen来进行测量。

使用时需要注意以下几点:

  • 字符串以 ‘\0’ 作为结束标志,strlen函数返回的是在字符串中 ‘\0’ 前面出现的字符个数(不包 含 ‘\0’ )
  • 参数指向的字符串必须要以 ‘\0’ 结束。
  • 注意函数的返回值为size_t,是无符号的,所以返回值一定大于等于0

strlen函数简单应用

现在尝试运用一下strlen函数,代码如下:

#define  _CRT_SECURE_NO_WARNINGS 1 

#include<stdio.h>
#include<string.h>
int main()
{
	char arr[] = "1234567890";
	size_t ret = strlen(arr);
	printf("%zd\n", ret);
	return 0;
}

结果如下:
在这里插入图片描述

strlen函数模拟实现

通过上面的分析我们知道strlen函数的基本逻辑就是找到字符串的首地址然后一直计数直到遇到’\0‘就返回。那么根据这个逻辑我们试试模拟实现strlen函数,代码如下:

#define  _CRT_SECURE_NO_WARNINGS 1 
#include<stdio.h>
#include<assert.h>
//方法1:计数
size_t my_strlen1(const char* arr)
{
	assert(arr);//检验arr是否为空指针
	int count = 0;
	while (*arr != '\0')
	{
		count++;
		arr++;
	}
	return count;
}

//方法2:指针-指针
size_t my_strlen2(const char* arr)
{
	assert(arr);
	const char* arr1 = arr;
	while (*arr != '\0')
	{
		arr++;
	}
	return arr - arr1;
}

//方法3:递归
size_t my_strlen3(const char * str)
{
 	if(*str == '\0')
 	return 0;
 	else
 	return 1+my_strlen(str+1);
}

int main()
{
	char arr[] = "1234567890";
	size_t ret1 = my_strlen1(arr);
	printf("%zd\n", ret1);

	size_t ret2 = my_strlen2(arr);
	printf("%zd\n", ret2);

	size_t ret3 = my_strlen3(arr);
	printf("%zd\n", ret3);
	return 0;
}

结果如下:
在这里插入图片描述


2.长度不受限制的字符串函数

2.1strcpy

strcpy函数介绍

在这里插入图片描述
strcpy函数有复制字符串的作用,将source(源字符串)复制到destination(目标空间)。

使用时需要注意以下几点:

  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可更改(不是常量字符串也没有const修饰),否则报错。

strcpy函数简单应用

现在尝试运用一下strcpy函数,代码如下:

#include<stdio.h>
#include<string.h>

int main()
{
	char arr1[20] = "xxxxxxxxxxx";
	char arr2[] = "abcdef";
	char* ret = strcpy(arr1, arr2);
	printf("%s\n", ret);
	return 0;
}

结果如下:
在这里插入图片描述

同时我们可以看看arr1数组内部的变化:

在这里插入图片描述
在这里插入图片描述

strcpy函数模拟实现

知道了strcpy函数的逻辑,我们来试试模拟实现,代码如下:

#include<stdio.h>
#include<string.h>
#include<assert.h>

char* my_strcpy(char* str1, const char* str2)
{
	assert(str1 && str2);
	char* ret = str1;
	while (*str1++ = *str2++)
	{
		;
	}
	return ret;
}

int main()
{
	char arr1[20] = "xxxxxxxxxxx";
	char arr2[] = "abcdef";
	//char* ret = strcpy(arr1, arr2);
	char* ret = my_strcpy(arr1, arr2);
	printf("%s\n", ret);
	return 0;
}

结果如下:
在这里插入图片描述


2.2strcat

strcat函数介绍

在这里插入图片描述
strcat函数功能是追加字符串,即在目标字符串后接上源字符串实现追加。

使用时需要注意以下几点:

  • 源字符串必须以 ‘\0’ 结束。
  • 会将源字符串中的 ‘\0’ 拷贝到目标空间
  • 目标空间必须足够大,以确保能存放源字符串。
  • 目标空间必须可更改(不是常量字符串也没有const修饰),否则报错。

strcat函数简单应用

那么现在尝试运用一下strcpy函数,代码如下:

#include<stdio.h>
#include<string.h>
int main()
{
	char arr1[20] = "abcdef";
	char arr2[] = "12345678";
	char* ret = strcat(arr1, arr2);
	printf("%s\n", ret);
	return 0;
}

结果如下:
在这里插入图片描述

strcat函数模拟实现

strcat函数是找到目标空间的末尾后开始将源字符串存入空间,同时最后也将’\0‘拷贝。
现在知道了strcat函数的逻辑,我们来试试模拟实现,代码如下:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* my_strcat(char* arr1,const char* arr2)
{
	char* ret = arr1;
	assert(arr1 && arr2);
	while (*arr1)
	{
		arr1++;
	}
	while ((*arr1++ = *arr2++))
	{
		;
	}
	return ret;

}

int main()
{
	char arr1[20] = "abcdef";
	char arr2[] = "12345678";
	//char* ret = strcat(arr1, arr2);
	char* ret = my_strcat(arr1, arr2);
	printf("%s\n", ret);
	return 0;
}

结果如下:
在这里插入图片描述


2.3strcmp

strcmp函数介绍

在这里插入图片描述
strcmp函数意思是str compare,字符串比较。可以看到函数返回类型是整型,它通过 依次比较两字符串元素的ASCII值得出结果。那如何通过整型返回值来反映大小关系呢?
我们可以看看C程序编译库中对返回值的解释:
在这里插入图片描述

通过图片我们得知,ptr1是字符串1的地址,ptr2是字符串2的地址,而函数返回值的意思如下:

如果 *ptr1> *ptr2 ,那么就返回大于0的值,str1 > str2。
如果 *ptr1= *ptr2,那么就返回0即可 ’‘’‘’‘’‘ str1 = str2。
如果 *ptr1< *ptr2 ,那么就返回小于0的值,str1 < str2。

strcmp函数简单应用

基本明白之后我们就可以来试着应用一下了,代码如下:

#include<stdio.h>
#include<string.h>

void my_judge(int ret)//判断结果函数
{
	if (ret > 0)
	{
		printf(">\n");
	}
	if (ret < 0)
	{
		printf("<\n");
	}
	if (ret == 0)
	{
		printf("=\n");
	}
}

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abce";//与arr1元素有不同,与arr1比应输出‘<’
	char arr3[] = "abcde";//与arr1长度不同,其他元素相同,与arr1比应输出‘>’
	int ret1 = strcmp(arr1, arr2);
	my_judge(ret1);
	int ret2 = strcmp(arr1, arr3);
	my_judge(ret2);
	return 0;
}

结果如下:

在这里插入图片描述

我们可以发现,字符串并不是越长值就越大,而是在比较过程中谁先有较大的元素,谁就是较大者 😃。

strcmp函数模拟实现

进行了一系列实践,现在我们可以试试来模拟实现strcmp函数,代码如下:

#include<stdio.h>
#include<string.h>
#include<assert.h>

void my_judge(int ret)//判断结果函数
{
	if (ret > 0)
	{
		printf(">\n");
	}
	if (ret < 0)
	{
		printf("<\n");
	}
	if (ret == 0)
	{
		printf("=\n");
	}
}

int my_strcmp(const char* ptr1, const char* ptr2)
{
	assert(ptr1 && ptr2);
	while (*ptr1 == *ptr2)
	{
		if (*ptr1 == '\0')
		{
			return 0;
		}
		ptr1++;
		ptr2++;
	}
	if (*ptr1 > *ptr2)
	{
		return 1;
	}
	else
		return -1;
}

int main()
{
	char arr1[] = "abcdef";
	char arr2[] = "abce";//与arr1元素有不同,与arr1比应输出‘<’
	char arr3[] = "abcde";//与arr1长度不同,其他元素相同,与arr1比应输出‘>’
	//int ret1 = strcmp(arr1, arr2);
	//my_judge(ret1);
	//int ret2 = strcmp(arr1, arr3);
	//my_judge(ret2);

	int ret1 = my_strcmp(arr1, arr2);
	my_judge(ret1);
	int ret2 = my_strcmp(arr1, arr3);
	my_judge(ret2);
	printf("\n别忘了点赞三连支持欧o(>ω< )o!!!\n");
	printf("(深情)\n");
	return 0;
}

结果如下:

在这里插入图片描述


3.长度受限制的字符串函数

3.1strncpy

strncpy函数介绍

在这里插入图片描述
strncpy函数和strcpy多了一个参数num,具体作用如下:

拷贝num个字符从源字符串到目标空间。
如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后边追加0,直到num个。

strncpy简单应用

了解明白新内容现在就来简单应用一下!代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[] = "To be or not to be";
	char str2[40];
	char str3[40];

	strncpy(str2, str1, sizeof(str2));

	strncpy(str3, str2, 5);
	str3[5] = '\0';  

	puts(str1);
	puts(str2);
	puts(str3);

	return 0;
}

结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


3.2strncat

strncat函数介绍

在这里插入图片描述
和strcat函数很像,不过同样多了个num参数,具体作用如下:

函数将源字符串的前 num 个字符复制到目标字符串,外加一个终止空字符’\0’。
如果源字符串的长度小于 num,则只复制终止空字符之前的内容。

strncat简单应用

了解明白新内容现在就来简单应用一下!代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
	char str1[20];
	char str2[20];
	strcpy(str1, "To be ");
	strcpy(str2, "or not to be");
	strncat(str1, str2, 6);
	puts(str1);
	return 0;
}

结果如下:
在这里插入图片描述
可以看到只在str1后接了6个元素,然后停止,不论是否遇到’\0’。


3.3strncmp

strncmp函数介绍

在这里插入图片描述
一样的道理,多了一个num,具体作用如下:

该函数从每个字符串的第一个字符开始比较。如果两个字符串的第一个字符相等,则继续比较下面的字符对,直到两个字符串的字符不同,或者比较到一个终止的空字符’\0’,或者比较到两个字符串中匹配的字符个数,以先发生者为准。

通俗来讲可以理解成:在strcmp函数功能的基础上,由以往的从头比到尾变成了可以控制在一定长度范围内进行比较

strncmp简单应用

都多余了,开始实践!代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
    char str[3][5] = { "R2D2" , "C3PO" , "R2A6" };
    int n;
    puts("查找 R2 ...");
    for (n = 0; n < 3; n++)
        if (strncmp(str[n], "R2xx", 2) == 0)
        {
            printf("found %s\n", str[n]);
        }
    return 0;
}

结果如下:
在这里插入图片描述
可以看到,找到的字符串和“R2XX”后两位还是不一样的,但是还是成功找到了R2,成功使用strncmp!!^ ^


4.字符串查找函数

4.1strstr

strstr函数介绍

在这里插入图片描述
strstr函数具体内容如下:

返回 字符串str1 中第一次完整出现 字符串str2 的指针,如果 str2 不是 str1 的一部分,即查找不到,则返回空指针NULL
匹配过程不包括空字符’\0’,但会在此位置时停止。

strstr简单应用

还是得实操一下才能真正理解,代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
    char str[] = "This is a simple string";
    char* pch;
    pch = strstr(str, "simple");//pch存放查找到对应字符串的首字母地址
    if (pch != NULL)
        strncpy(pch, "sample", 6);
    puts(str);
    return 0;
}

结果如下:

在这里插入图片描述
也就意味着查找到了地址并用strcpy更改了内容,成功!!


4.2strtok

strtok函数介绍

在这里插入图片描述

sep参数是个字符串,定义了用作分隔符的字符集合。
第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记。
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针

strtok简单应用

开始冻手!!代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
	char arr[] = "tobe@or.not to be";

	char buf[200] = {0};//"tobe@or.not to be"
	strcpy(buf, arr);

	char* p = "@.";
	char* s = strtok(buf, p);
	printf("%s\n", s);

	s = strtok(NULL, p);
	printf("%s\n", s);

	s = strtok(NULL, p);
	printf("%s\n", s);

	return 0;
}

结果如下:
在这里插入图片描述


5.错误信息报告函数

5.1strerror

strerror函数介绍

在这里插入图片描述

这个函数有些特别,它所返回的是错误码所对应的错误信息的地址

那我就会问了,错误码是什么呢?其实很好理解,我们上网打开网页经常会出现问题,例如“404Not found!!”等等,这些都是错误码。通过strerror函数可以把这些错误码对应的具体问题详细输出,就不仅仅只是个数字在屏幕上了。

strerror简单应用

冻手!冻手!代码如下:

#include <stdio.h>
#include <string.h>

int main()
{
    int i = 0;
    for (i = 1; i < 10; i++)
    {
        printf("%d:%s\n", i, strerror(i));
    }
    return 0;
}

结果如下:

在这里插入图片描述
可以看到每个数字对应的错误问题,有意思哦 ^ ^。


6.字符分类函数

在这里插入图片描述


7.内存操作函数

memcpy

memcpy函数介绍

在这里插入图片描述
函数memcpy具体功能实现是从source的位置开始向后复制num个字节的数据到destination的内存位置。这个函数在遇到 ‘\0’ 的时候并不会停下来。

注意!! 如果source和destination有任何的重叠,复制的结果都是未定义的。

memcpy简单应用

那就试试呗,代码如下:

#include <stdio.h>
#include <string.h>

void test()
{
	char arr1[] = "abcdef";
	char arr2[5] = { 0 };
	memcpy(arr2, arr1, 3);
	printf("%s", arr2);
}

int main()
{
	test();
	return 0;
}

结果如下:
在这里插入图片描述

memcpy函数模拟实现

在这也试试模拟实现memcpy,代码如下:

#define  _CRT_SECURE_NO_WARNINGS 1 
//模拟实现memcpy
//void* memcpy(void* destination, const void* source, size_t num);
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memcpy(void* dest,const void* str, size_t sz)
{
	void* ret = dest;
	while (sz--)
	{
		*(char*)dest = *(char*)str;
		djieguoest = (char*)dest + 1;
		str = (char*)str + 1;
	}
	return ret;
}

int main()
{
	char arr1[] = "hello world";
	char arr2[] = "abc";
	my_memcpy(arr1, arr2, 3);
	printf("%s\n", arr1);

	printf("\n别忘了点赞三连支持欧o(>ω< )o!!!\n");
	printf("(深情)\n");
	return 0;
}

结果如下:
在这里插入图片描述


memmove

memmove函数介绍

在这里插入图片描述
这个很好理解,它和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。
如果源空间和目标空间出现重叠,就得使用memmove函数处理。

memmove简单应用

尝试着使用一下,都差不多的了,我就不在这里赘述了,我觉得很彳亍 😃

memmove函数模拟实现

那memmove是如何实现的呢?代码如下:

//memmove模拟实现
//void * memmove ( void * destination, const void * source, size_t num );
#include<stdio.h>
#include<string.h>
#include<assert.h>
void* my_memmove(void* dest,const void* str, size_t num)
{
	assert(dest && str);
	void* ret = dest;
	if (dest < str)
	{
		//从前到后
		while (num--)
		{
			*(char*)dest = *(char*)str;
			dest = (char*)dest + 1;
			str = (char*)str + 1;
		}
	}
	else
		//从后到前
	{
		dest = (char*)dest + num - 1;
		str = (char*)str + num - 1;
		while (num--)
		{


			*(char*)dest = *(char*)str;
			dest = (char*)dest - 1;
			str = (char*)str - 1;
		}
	}
	return ret;
}


int main()
{
	char arr[] = "memmove can be very useful......";
	void* str = my_memmove(arr + 20, arr + 15, 5);
	puts(arr);
	return 0;
}



结语

好了以上就是本篇“【C语言】字符串函数分析及模拟实现”博客的全部内容啦,感谢各位的阅读=v=,如有不足之处欢迎在评论区指出哦!!
觉得可以的话别忘了点赞三连支持一下欧!拜托啦这对我真的很重要o(>ω< )o!!!

请添加图片描述

  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
### 回答1: C语言中常用的字符串替换函数是`str_replace`,它可以在一个字符串中查找并替换指定的子字符串。下面我将简单地模拟实现一个`str_replace`函数。 ```c #include <stdio.h> #include <stdlib.h> #include <string.h> char* str_replace(const char* str, const char* search, const char* replace) { char* result; int search_len = strlen(search); int replace_len = strlen(replace); int count = 0; // 统计需要替换的次数 const char* s = str; while ((s = strstr(s, search)) != NULL) { count++; s += search_len; } // 计算替换后的字符串长度 int result_len = strlen(str) + count * (replace_len - search_len); result = (char*)malloc(result_len + 1); // 开始替换 char* p = result; s = str; while ((s = strstr(s, search)) != NULL) { int n = s - str; strncpy(p, str, n); p += n; strncpy(p, replace, replace_len); p += replace_len; str = s + search_len; } strcpy(p, str); return result; } int main(void) { const char* str = "Hello, world!"; const char* search = "world"; const char* replace = "everyone"; char* result = str_replace(str, search, replace); printf("替换前: %s\n", str); printf("替换后: %s\n", result); free(result); return 0; } ``` 上述代码实现了一个简单的`str_replace`函数。它首先统计了需要替换的次数,并根据替换的次数计算了替换后的字符串长度。然后,它分配了足够的内存空间来存储替换后的字符串,并进行了替换操作。最后,它返回了替换后的字符串。在`main`函数中,我们可以看到如何使用这个函数来替换一个字符串中的子字符串。 需要注意的是,本示例只是对`str_replace`函数的简单模拟实现,实际使用中还需要处理更多的边界情况和错误处理。 ### 回答2: C语言中没有内置的字符串替换函数,但我们可以通过模拟实现一个字符串替换函数。 首先,我们可以定义一个函数,该函数接受三个参数:源字符串、待替换的子字符串、替换后的子字符串函数的返回值是替换完成后的字符串。 接下来,我们可以使用循环来遍历源字符串。在每次循环中,比较源字符串中是否存在待替换的子字符串。如果存在,我们就将替换后的子字符串复制到新的字符串中。如果不存在,我们将源字符串中的当前字符复制到新的字符串中。 最后,返回新的字符串即可。 下面是一个简单的模拟实现示例: ```c #include <stdio.h> #include <string.h> char* stringReplace(char* source, const char* search, const char* replace) { char* result; int i, j, sourceLen, searchLen, replaceLen, count; sourceLen = strlen(source); searchLen = strlen(search); replaceLen = strlen(replace); count = 0; for (i = 0; i < sourceLen; i++) { if (strstr(&source[i], search) == &source[i]) { count++; i += searchLen - 1; } } result = (char*)malloc(sourceLen + count * (replaceLen - searchLen) + 1); i = 0; j = 0; while (source[i]) { if (strstr(&source[i], search) == &source[i]) { strcpy(&result[j], replace); j += replaceLen; i += searchLen; } else result[j++] = source[i++]; } result[j] = '\0'; return result; } int main() { char source[] = "Hello, World!"; const char search[] = "World"; const char replace[] = "C Language"; char* result = stringReplace(source, search, replace); printf("替换后的字符串: %s\n", result); free(result); return 0; } ``` 这是一个简单的模拟实现,实际上字符串替换还涉及到更多复杂的情况和细节,比如大小写敏感、替换次数限制等等。需要根据实际需求进行更进一步的完善。 ### 回答3: C语言字符串替换函数模拟实现的方法有很多,以下是一种可能的实现方式: ```c #include <stdio.h> #include <string.h> void str_replace(char *str, const char *find, const char *replace) { int find_len = strlen(find); int replace_len = strlen(replace); int str_len = strlen(str); char result[100]; int result_len = 0; int i = 0; while (i < str_len) { if (strncmp(&str[i], find, find_len) == 0) { // 找到需要替换的字符串 strncpy(&result[result_len], replace, replace_len); result_len += replace_len; // 跳过被替换的部分 i += find_len; } else { // 将原字符串的字符复制到结果字符串中 result[result_len] = str[i]; result_len++; i++; } } // 将新的结果字符串复制回原字符串中 strncpy(str, result, result_len); str[result_len] = '\0'; } int main() { char str[100] = "Hello, World!"; char find[10] = "World"; char replace[10] = "Alice"; printf("Before replace: %s\n", str); str_replace(str, find, replace); printf("After replace: %s\n", str); } ``` 这个函数的思路是首先计算出原字符串、需要查找的字符串以及替换的字符串的长度。然后以原字符串为基础,通过遍历每个字符的方式,查找需要替换的字符串,然后将替换的字符串复制到结果字符串中,同时跳过原字符串中已经被替换的部分。最后将结果字符串复制回原字符串中,完成字符串的替换。在主函数中,我们可以看到使用这个函数对原始字符串中的特定字符串进行了替换操作。运行程序后,可以输出替换后的字符串

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值