C语言字符串相关函数及其模拟实现(超详细!!)

目录

(一)strlen

1、strlen 相关细节

2、 strlen 模拟实现

计数器的方法:

递归的方法

指针向减的运算:

(二)strcpy

1、strcpy 相关细节

 2、strcpy 模拟实现

        3.1 strncpy 相关细节

3.2 strncpy 实例

(三)strcat

1、strcat 相关细节(与strcpy相似)

2、strcat 模拟实现

3.1 strncat 相关细节

3.2 strncat 模拟实现

(四)strcmp

1. strcmp 的相关细节

2. strcmp 模拟实现

3. strncmp 的相关细节

(五)strstr 函数

1. strstr 的相关细节

2. strstr 模拟实现

(六)strtok 

1. strtok 的相关细节

2. strtok 模拟实现

3.1 strchr 的相关细节 

3.2 strpbrk 的相关细节


输入字符串的相关函数:

scanf、gets、fgets

(一)strlen

1、strlen 相关细节

计算一个字符串的长度(‘\0’之前的长度)

例如字符串“abcd”,它的长度为4。实际上,"abcd"是“abcd\0”,在 \0 之前有4个字符,所以该字符串的长度是4.

还要注意的是,strlen的返回值是size_t类型的,即unsigned int 类型的,这也就代表用strlen函数求出的长度结果一定是一个整数。

易错点:

#include <stdio.h>
#include <string.h>
int main()
{
	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf(">\n");
	}
	else
	{
		printf("<=\n");
	}
	return 0;
}

可能会有人认为代码运行的结果是<=, 但实际上运行结果是>

导致这种现象的原因就是strlen 的返回值,strlen("abc")的运算结果是3,strlen("abcdef")的运算结果是6,但是3和6的数据类型是unsigned int 类型的,所以两者运算的结果也是unsigned int 类型的,即运算结果恒大于0. 

2、 strlen 模拟实现

计数器的方法:

#include <stdio.h>

int Strlen(char* s)
{
	int count = 0;
	while (*s != '\0')
	{
		count++;
		s++;
	}
	return count;
}
int main()
{
	char arr[] = "ABCDEF";
	int ret = Strlen(arr);
	printf("%d", ret);
	return 0;
}

递归的方法

#include <stdio.h>

int Strlen(char* s)
{
	if (*s == '\0')
		return 0;
	else
		return 1+Strlen(s+1);
}
int main()
{
	char arr[] = "ABCDEF";
	int ret = Strlen(arr);
	printf("%d", ret);
	return 0;
}

指针向减的运算:

#include <stdio.h>

int Strlen(char* s)
{
	char* start = s;
	char* end = s;
	while (*end != '\0')
		end++;
	return end - start;
}
int main()
{
	char arr[] = "ABCDEF";
	int ret = Strlen(arr);
	printf("%d", ret);
	return 0;
}

易错写法:

++的运算优先级高于解引用,所以先会进行++操作在进行解引用,但又因为++为后置++,所以解引用操作结束后才会把这个1加上,此时end指向的是\0后面的空间。

while (*end++ != '\0');

当我们换成这种写法,就正确了

while (*++end != '\0');

(二)strcpy

1、strcpy 相关细节

strcpy 会把源字符串拷贝到目标数组中,拷贝过程以\0 作为结束标志,拷贝的内容包括源字符串中的\0;这里会存在两种情况:

1)如果一个字符串中有一个\0 ,\0后面还有内容,比如“Hello\0World!”,strcpy 函数只能够将Hello\0拷贝到目标数组中,World 不会被拷贝过去。

2)如果source中没有\0, 使用strcpy会拷贝失败。

这里需要注意的是,不能够写成以下两种错误写法:

1)

char name[20] = { 0 };
name = "zhangsan";

 name是数组名,也就是一个地址,而地址是一个常量是不能被修改的,所以不能进行赋值操作。

2)

    char name[3] = "li";
	char* p = "zhangsan";
	strcpy(p, name);

这是因为p指向的是一个常量字符串,常量字符串是不能被修改的

 2、strcpy 模拟实现

char* my_strcpy(char* destination, const char* source)
{
	assert(destination);
	assert(source);
	char* pmove = destination;
	while (*pmove++ = *source++);
	return destination;
}
int main()
{
	char arr1[] = "abcdef";
	char arr2[20] = { 0 };
	my_strcpy(arr2, arr1);
	printf("%s\n", arr2);
	return 0;
}

3.1 strncpy 相关细节

size_t num

Maximum number of characters to be copied from source.
size_t is an unsigned integral type.

3.2 strncpy 实例

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

(三)strcat

1、strcat 相关细节(与strcpy相似)

1. 源字符串必须以 '\0' 结束。

2. 目标空间必须有足够的大,能容纳下源字符串的内容。

3. 目标空间必须可修改。

2、strcat 模拟实现

第一步:先找到destination 的字符串末尾;

第二步:将source拷贝到destination的末尾。

char* my_strcat(char* destination, const char* source)
{
	assert(destination && source);
	char* pmove = destination;
	while (*pmove != '\0')
		pmove++;
	while (*pmove++ = *source++);
	return destination;
}
int main()
{
	char arr1[20] = "Hello ";
	char arr2[] = "World!";
	my_strcat(arr1, arr2);
	printf("%s\n", arr1);
	return 0;
}

这里还需要注意一个点:当给一个字符串追加自己时,会出现一下问题:

 因为自己追加自己时,会把原字符串中的\0覆盖掉,导致会一直进行拷贝,直到空间用完然后越栈。

如果想要自己给自己追加时,可以使用 strncat,该函数不会出现上述现象。

3.1 strncat 相关细节

相较于 strcat 函数,strncat 函数多了一个要拷贝数据的大小的参数(单位是字节)

size_t num   

Maximum number of characters to be appended 

size_t is an unsigned integral type

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

int main()
{
	char arr1[20] = "Hello ";
	strncat(arr1, arr1, strlen(arr1)*sizeof(char));
	printf("%s\n", arr1);
	return 0;
}

3.2 strncat 模拟实现

其实能不能实现自我追加,完全看编译器是如何实现 strcat 和 strncat 函数的,这里只需要分两种情况分别实现就可以了:

① 当 strncat 的两个字符串参数不为同一个字符串时,实现方法就如同上述 strcat 的模拟实现一样;

② 当 strncat 的两个字符串参数为同一个字符串时, 只需要创建临时缓冲区保存一下原字符串,再用临时缓冲区的内容追加到原字符串中即可(这样就不会出现追加覆盖原先内容的情况了)。

具体代码如下:

char* my_strncat(char* destination, const char* source, size_t num)
{
	assert(destination && source);
	if (destination == source)
	{
		char* pmove = destination;
		char a[30] = { 0 };
		char* temp = a;
		strcpy(temp, destination);
		while (*pmove != '\0')
			pmove++;
		while (*temp != '\0' && num > 0)
		{
			*pmove = *temp;
			pmove++;
			temp++;
			num--;
		}
		*pmove = '\0';
	}
	else
	{
		char* pmove = destination;

		// 将指针移动到目标字符串的末尾
		while (*pmove != '\0') 
			pmove++;
		// 将源字符串的最多n个字符拼接到目标字符串的末尾
		while (*source != '\0' && num > 0) 
		{
			*pmove = *source;
			pmove++;
			source++;
			num--;
		}
		*pmove = '\0';
	}
	return destination;
}

(四)strcmp

1. strcmp 的相关细节

strcmp 函数是C语言标准库中的一个字符串比较函数,用于比较两个字符串的大小关系。它的函数原型如下:

int strcmp(const char* str1, const char* str2);

strcmp 函数接收两个参数,即要比较的两个字符串str1str2,并返回一个整数值,表示两个字符串的大小关系。返回值的含义如下:

  • 如果str1str2相等,返回值为0。
  • 如果str1大于str2,返回值大于0。
  • 如果str1小于str2,返回值小于0。

strcmp 函数的比较规则如下:

  • 首先,从两个字符串的首字符开始逐个比较,直到遇到不相等的字符或者达到字符串的结束符(\0)。
  • 如果遇到不相等的字符,比较它们的ASCII码值,返回差值(str1[i] - str2[i])(不过在VS中,大于0是返回 1 ,小于0是返回 -1 )。
  • 如果两个字符串的长度不同,且较短的字符串在相同位置上的字符都与较长字符串相等,则较长字符串更大。

2. strcmp 模拟实现

根据 strcmp 函数的比较规则,可以一个一个字符遍历比较两者的ASCII码值,直到遇到不相等的字符或者达到字符串的结束符(\0)即可。

具体代码如下:

int my_strcmp(const char* str1, const char* str2)
{
	assert(str1 && str2);
	char* pmove1 = str1;
	char* pmove2 = str2;
	while (*pmove1 != '\0' && *pmove2 != '\0')
	{
		int count = *pmove1 - *pmove2;
		if (count > 0)
			return 1;
		else if(count < 0)
			return -1;
		else
		{
			pmove1++;
			pmove2++;
		}
	}
	if (*pmove1 != '\0')
		return 1;
	else if (*pmove2 != '\0')
		return -1;
	else
		return 0;
}

3. strncmp 的相关细节

还有 strncmp 函数,有了以上基础,模拟实现这个函数也是很容易的,这里我就不实现了。

(五)strstr 函数

1. strstr 的相关细节

strstr 函数是C语言标准库中的一个字符串查找函数,用于在一个字符串中查找另一个字符串的出现位置。它的函数原型如下:

char* strstr(const char* haystack, const char* needle);

strstr函数接收两个参数,即待搜索的字符串haystack和要查找的目标字符串needle,并返回一个指向第一次出现目标字符串的位置的指针。如果目标字符串不存在于待搜索的字符串中,则返回NULL

strstr 函数的工作原理如下:

  • 首先,从待搜索的字符串haystack的第一个字符开始,逐个比较字符。
  • 如果当前字符与目标字符串needle的第一个字符相等,则继续比较后续字符,直到找到完全匹配的子字符串或者遇到不匹配的字符。
  • 如果找到了完全匹配的子字符串,返回指向该子字符串的指针。
  • 如果遍历完待搜索的字符串haystack仍未找到匹配的子字符串,则返回NULL

2. strstr 模拟实现

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	int len = (int)strlen(str2);
	while (*str1 != '\0')
	{
		int count = 0;
		int i = 0;
		for (i = 0; i < len; i++)
		{
			if (*(str1 + i) == *(str2 + i))
				count++;
			else
				break;
		}
		if (count == len)
			return str1;
		else
			str1++;
	}
	return NULL;
}

(六)strtok 

1. strtok 的相关细节

strtok 函数是C语言标准库中的一个字符串分割函数,用于将一个字符串按照指定的分隔符进行分割。它的函数原型如下:

char* strtok(char* str, const char* delimiters);

strtok 函数接收两个参数,即待分割的字符串str和分隔符字符串delimiters。在第一次调用时,需要将待分割的字符串作为参数传入;之后的调用中,将第一个参数设为NULL即可。

strtok函数的工作原理如下:

  • 在第一次调用时,strtok函数会在待分割的字符串str中查找第一个不属于分隔符的字符,并将其作为分割后的第一个子字符串的起始位置。
  • 之后,strtok函数会继续查找下一个属于分隔符的字符,并将其替换为字符串结束符\0,以分割当前的子字符串。
  • 在后续的调用中,strtok函数会继续从上一次分割的位置开始,查找下一个不属于分隔符的字符,重复上述步骤,直到分割完所有的子字符串。
  • 如果无法找到下一个不属于分隔符的字符,则返回NULL,表示分割完成。

由函数的工作原理可以知道,分割一个字符串,第一次调用参数是带分割的字符串和分隔符字符串;第二次调用参数是NULL和分隔符字符串。所以可以利用for循环来调用函数实现任何长度的待分割的字符串进行分割:

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

int main()
{
	char pa[20] = "I am a student!";
	const char* pb = " ";
	char temp[20] = { 0 };
	char* str = NULL;
	strcpy(temp, pa);
	for (str = strtok(temp, pb); str != NULL;str = strtok(NULL, pb))
	{
		printf("%s\n", str);
	}
	return 0;
 }

2. strtok 模拟实现

char* my_strtok(char* str, const char* delimiters)
{
	static char* token = NULL;
	char* start = NULL;
	if (str != NULL) // 第一次调用strtok
	{
		token = str;
	}
	// 跳过开头是分隔符的字符
	while (*token != '\0' && strchr(delimiters, *token) != NULL)
	{
		token++;
	}
	// 如果token已经达到字符串末尾,直接返回NULL
	if (*token == '\0')
		return NULL;
	// 记录分隔符前字符串的起始位置
	start = token;
	// 找到下一个分隔符的位置并将分隔符替换为\0
	token = strpbrk(start, delimiters);
	if (token != NULL)
	{
		*token = '\0';
		token++;
	}
	return start; // 返回分隔符前字符串的起始位置
}

 在实现这个函数时,我用到了一下两个字符串函数:

3.1 strchr 的相关细节 

strchr 函数是C语言标准库中的一个字符串查找函数,用于在一个字符串中查找指定字符的第一个出现位置。它的函数原型如下:

char* strchr(const char* str, int character);

strchr 函数接收两个参数,即待查找的字符串str和要查找的字符character。它会在str字符串中查找第一个等于character的字符,并返回该字符在str中的地址(指针)。

strchr 函数的工作原理如下:

  • strchr函数从str字符串的开头开始逐个字符地比较,直到找到第一个等于character的字符或者到达字符串结尾(即遇到空字符\0)。
  • 如果找到了等于character的字符,则返回该字符在str中的地址(指针)。
  • 如果未找到等于character的字符,则返回NULL

3.2 strpbrk 的相关细节

strpbrk 函数是C语言标准库中的一个字符串查找函数,用于在一个字符串中查找包含指定字符集合中任意字符的第一个出现位置。它的函数原型如下:

char* strpbrk(const char* str, const char* charset);

strpbrk 函数接收两个参数,即待查找的字符串str和包含待查找字符集合的字符串charset。它会在str字符串中查找第一个包含charset中任意字符的字符,并返回该字符在str中的地址(指针)。

strpbrk 函数的工作原理如下:

  • strpbrk函数从str字符串的开头开始逐个字符地比较,直到找到第一个包含在charset中的字符或者到达字符串结尾(即遇到空字符\0)。
  • 如果找到了包含在charset中的字符,则返回该字符在str中的地址(指针)。
  • 如果未找到包含在charset中的字符,则返回NULL

以上两个函数我就不一一实现了,读者可以自己思考一下。

好了,以上就是我所要分享关于C语言字符串相关函数及其模拟实现的所有内容,我所实现的字符串函数,效率不是很高(基本上都是遍历实现的,大佬勿喷),比如 strstr  函数,如果使用KMP算法效率会大大提高。


如果你觉得这篇博客对你有帮助的话 ,希望你能够给我点个赞,鼓励一下我。感谢感谢……

  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答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); } ``` 这个函数的思路是首先计算出原字符串、需要查找的字符串以及替换的字符串的长度。然后以原字符串为基础,通过遍历每个字符的方式,查找需要替换的字符串,然后将替换的字符串复制到结果字符串中,同时跳过原字符串中已经被替换的部分。最后将结果字符串复制回原字符串中,完成字符串的替换。在主函数中,我们可以看到使用这个函数对原始字符串中的特定字符串进行了替换操作。运行程序后,可以输出替换后的字符串

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值