各种字符函数以及模拟

本文详细介绍了C语言中几个重要的字符串处理函数,包括strlen用于计算字符串长度,strcpy用于复制字符串,strcmp用于比较字符串,strcat用于连接字符串,以及strtr用于查找并替换字符串中的字符。每个函数都提供了原函数介绍、参数、返回值、使用示例及注意事项,并给出了相应的函数模拟实现,包括递归和非递归版本。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.strlen

1.原函数介绍

声明:

文档描述:

参数:

返回值:

使用例子:

注意事项 :

 2.函数模拟

说明:

代码实现:

2.strcpy

1.原函数介绍

声明:

文档描述:

参数:

返回值:

使用例子:

注意事项:

2.函数模拟

说明:

代码实现:

3.strcmp

1.原函数介绍

声明:

文档描述:

参数:

返回值:

使用例子:

注意事项:

2.函数模拟

说明:

代码实现:

4.strcat

1.原函数介绍

声明:

文档描述:

参数:

返回值:

使用例子:

注意事项:

2.函数模拟

代码实现:

5.strtr

1.原函数介绍

声明:

文档描述:

参数:

返回值:

使用例子:

2.函数模拟

代码实现:


1.strlen

1.原函数介绍

//头文件:
#include<string.h>

声明:

size_t strlen ( const char * str );

文档描述:

1.返回字符串str的长度。

2.字符串的长度由结束性的空字符( \0 )决定:一个字符串的长度是字符串的开头和结束性空字符之间的字符数(不包括结束性空字符本身)。

简而言之,就是计算字符串的字符个数,返回个数值,但这个数值不包括\0

参数:

  • str是要计算的字符串的地址。

返回值:

返回的是字符串的字符个数,类型是:size_t

使用例子:

/* strlen example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char szInput[256];
  printf ("Enter a sentence: ");
  gets (szInput);
  printf ("The sentence entered is %u characters long.\n",(unsigned)strlen(szInput));
  return 0;
}
//结果是12

注意事项 :

        1.不应该与存放字符串的数组的大小相混淆。比如:

char mystr[100]="test string";

这里定义了一个大小为100个字符的字符数组,但是mystr被初始化的字符串的长度只有11个字符。因此,虽然sizeof(mystr)被评估为100,但strlen(mystr)却返回11。从这里可以看出,strlen只计算\0前面的字符个数,与sizeof不一样。

        2.在定义字符数组的时候应该注意定义的方式,下面使用两种方式定义字符数组:

int main()
{
	char arr1[] = { 'a','b','c' };
	char arr2[] = "abc";
	printf("arr1的长度:%d\n",strlen(arr1));
	printf("arr2的长度:%d",  strlen(arr2));


	return 0;
}

结果:

为什么同样放abc,结果不一样???

原因在于\0的位置。第一种定义方式要自己放入\0,数组不会自己放,这就造成了\0的位置是不知道在哪的情况,这里显示35,下一次可能是其它数字;第二种数组会自己放入\0,数组会放到最后一个字符的后面,所以这次strlen就会算出3的结果。

修改后的代码:

int main()
{
	char arr1[] = { 'a','b','c','\0'};
	char arr2[] = "abc";
	printf("arr1的长度:%d\n",strlen(arr1));//结果是3
	printf("arr2的长度:%d",  strlen(arr2));//结果是3


	return 0;
}

 2.函数模拟

说明:

1,参数:

传参的时候应该是字符串的地址,所以类型是 char*,为了防止在写代码的时候修改原字符串的地址,应该再加上 const

2,返回值:

应该是:size_t   。

3,版本:

可分为非递归版和递归版。

4,防错

为了防止传的是空指针,在函数最前面加上assert断言。

代码实现:

1,非递归版本:

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

//非递归版本
size_t my_strlen(char* str)
{
	assert(str);
	int sum = 0;
	while (*str != 0)
	{
		sum++;
		str++;
	}
	return sum;
}
int main()
{
	char arr[] = "asdfg";
	char* str = arr;
	char arr1[] = { 'a','b' };
	char arr2[] = { 'a','b','\0' };
	printf("%d ", my_strlen(arr));//5
	printf("%d ", my_strlen(str));//5
	printf("%d ", my_strlen(arr1));//33,可能会变化
	printf("%d ", my_strlen(arr2));//2
	
	return 0;
}

2,递归版本:

//递归版本
size_t my_strlen(char* str)
{

	if (*str != 0)
	{
		return 1 + my_strlen(str+1);
	}
	else
	{
		return 0;
	}
}

int main()
{
	char arr[] = "asdfg";
	char* str = arr;
	char arr1[] = { 'a','b' };
	char arr2[] = { 'a','b','\0' };
	printf("%d ", my_strlen(arr));//5
	printf("%d ", my_strlen(str));//5
	printf("%d ", my_strlen(arr1));//33,可能会变化
	printf("%d ", my_strlen(arr2));//2
	
	return 0;
}

2.strcpy

1.原函数介绍

//头文件
#include<string.h>

声明:

char * strcpy ( char * destination, const char * source );

文档描述:

1.将source指向的字符串复制到destination指向的数组中,包括终止的空字符(并在该点停止)。

2.为了避免溢出,destination指向的数组大小应足够长,以包含与source相同的字符串(包括结束的空字符),并且在内存中不应与source重合

简而言之,就是把一个数组复制到另外一个数组上,目标数组要足够大,不能与原数组重合。

参数:

  • destination 是 指向要复制内容的目标数组的指针。
  • source 是 要复制的字符串的指针。

返回值:

返回一个指向目标数组的指针(char类型),即指向destination的指针。

使用例子:

/* strcpy example */
#include <stdio.h>
#include <string.h>

int main()
{
	char arr1[6] = "abcde";//长度是6不是5
	char arr2[4] = "qwf";

	strcpy(arr1, arr2);//虽然拷贝到arr1那边,但arr2比arr1短,e还是会保留,但因为前面的d已经被
	//复制成\0,所以在输出arr1的时候会在e的前面停下来.
	puts(arr1);
	return 0;
}

注意事项:

  1. 数组destination的大小应该和source的大小一样或者更大。
  2. destination的内容不能与source的内容重叠。
  3. 当strcpy复制到\0的时候就会停止,即使\0后面还有内容。
  4. source必须以\0结束。
  5. strcpy会把\0也复制到destination里面。
  6. destination必须是可以改变的空间。
  7. arr2arr1短的时候,arr1中自己的\0前面的字符还是会保留,但因为最后的时候arr1已经完成对arr2的复制,此时arr1存在两个\0,所以在输出完成复制后的arr1的时候会在arr1的第一个\0停下来。

2.函数模拟

说明:

参数:传参的时候两个都应该是字符串的地址,所以类型是 char*,为了防止在写代码的时候修改原字符串的地址,应该在source加上 const

返回值:应该是: char*  。

防错:为了防止传的是空指针,在函数最前面加上assert断言。

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>

//模拟实现strcpy
//功能:复制字符串
char* my_strcpy(char* dest, const char* src)
{
	assert(dest && src);
	while (*dest++ = *src++)
	{
		;
	}
 return dest;
}

int main()
{

	char arr1[] = "abcde";//存了6个元素
	char arr2[100] = { 0 };
	char arr3[] = "abc\0d";//arr3存了6个元素,包括d前面的\0
	//strcpy(arr2, arr3);//遇到\0就停止复制,后面的d不会复制上去,而且\0不会显示出来
	//printf("%s ", arr2);
	//printf("%s ", arr3);
	//printf("\n");

	my_strcpy(arr2, arr3);
	printf("%s ", arr2);
	printf("%s ", arr3);

	return 0;
}

3.strcmp

1.原函数介绍

//头文件
#include<string.h>

声明:

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

文档描述:

  1. 将C语言字符串str1与C语言字符串str2进行比较。
  2.  这个函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续进行下面的配对,直到字符不同或达到一个终止的空字符为止。
  3. 该函数对字符进行二进制比较

说人话就是比较两个字符串的字符的二进制大小,当比较字符一样的时候会跳到下一个字符继续比较,直到\0。

参数:

  • str1str2都是要进行比较的字符串的首字符的指针。

返回值:

  • 返回值是int类型,除了等于的情况会返回0,大于和小于的情况的返回值要看编译器的种类。
  • 标准规定:
返回值表示意义
<0当比较到两个字符不一样的时候,str1的字符比str2的大

=0

两个字符串一样大
>0当比较到两个字符不一样的时候,str1的字符比str2的小

  • 编译器的不同 ,返回 " <0 ” 和 “ >0 ”这两种情况会各自产生不一样的数值,例如:str1str2大的时候,有些编译器会返回1,有些会返回随机大于0的值。

使用例子:

#include <stdio.h>
#include <string.h>
int main()
{
	char key[] = "apple";
	char buffer[80];
	do {
		printf("Guess my favorite fruit. ");
		scanf("%s", buffer);
	} while (strcmp(key, buffer) != 0);
	puts("Correct answer!");

	return 0;
}

注意事项:

  1. 比较的是两个字符串的第一个不同的字符大小(字符的二进制的大小),而不是字符串的长度。
  2. 编译器的不同 ,返回 " <0 ” 和 “ >0 ”这两种情况会各自产生不一样的数值,例如:str1str2大的时候,有些编译器会返回1,有些会返回随机大于0的值。

2.函数模拟

说明:

  1. 因为编译器的不同,返回值可能会有所差别,故写出两个版本供参考。

代码实现:

#include<stdio.h>
//版本1 
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == 0)//在str1和str2都相等的情况下,一直到结尾\0都相等,此时说明两者都等于\0
		{
			return 0;
		}

//		1和2向前遍历
		str1++;
		str2++;
	}

	if (*str1 - *str2 > 0)
	{
		return 1;
	}
	else
	{
		return -1;
	}
}

//版本2
int my_strcmp(const char* str1, const char* str2)
{
	while (*str1 == *str2)
	{
		if (*str1 == 0)//一直到结尾\0都相等
		{
			return 0;
		}

		//1和2向前遍历
		str1++;
		str2++;
	}

	return *str1 - *str2;

}

int main()
{
	char arr1[] = "abcd";
	char arr2[] = "bcd";
	char arr3[] = "aacd";
	char arr4[] = "abc";
	char arr5[] = "abcd";
	//int ret = my_strcmp(arr1, arr4);//arr1比arr4大
	//int ret = my_strcmp(arr1, arr2);//arr1比arr2小
	//int ret = my_strcmp(arr1, arr1);//返回0
	int ret = my_strcmp(arr1, arr5);//返回0
	printf("%d", ret);

	return 0;
}

4.strcat

1.原函数介绍

//头文件
#include<string.h>

声明:

char * strcat ( char * destination, const char * source );

文档描述:

  1. 将源字符串的副本添加到目标字符串中。目标字符串中的结束性空字符被源字符串的第一个字符覆盖,并且在目标字符串中由两者串联形成的新字符串的末尾包含一个结束性字符。
  2. destinationsource不应重叠。

就是把source字符串复制多一份,然后再添加到destination上,destination\0字符会被source的首元素替换掉,并且在形成新字符串的最后面加上\0

参数:

  • destination是指向目标数组的首字符指针,该数组应该包含一个字符串,并且要足够大,以包含连接后的字符串。
  • source是要追加的字符串的首字符指针,不应该与destination字符串重叠。

返回值:

  • 返回destination的首字符指针。

使用例子:

/* strcat example */
#include <stdio.h>
#include <string.h>

int main ()
{
  char str[80];
  strcpy (str,"these ");
  strcat (str,"strings ");
  strcat (str,"are ");
  strcat (str,"concatenated.");
  puts (str);
  return 0;
}

//int main()
//{
//	char arr1[] = "abcd";
//	char arr2[] = "efghi";
//	strcat(arr1, arr2);//后面的复制到前面
//	printf("%s", arr1);
//	//没有规定arr1和arr2的数组长度,编译器会报警
//
//	char arr1[] = "abcd";		//这里实际放着5个元素,数组自己在d后面加了一个\0
//	char arr2[] = "efgh";
//
//	char arr1[8] = "abcd";	//8不行,因为后面还要放一个\0,把abcdefgh放在arr1等于放了9个元素,abcdfgh\0
//	char arr2[] = "efgh";
//	strcat(arr1, arr2);
//	puts(arr1);
//
//	char arr1[9] = "abcd";
//	char arr2[] = "efgh";		//9可以
//	strcat(arr1, arr2);
//	puts(arr1);
//
//
//	return 0;
//}

注意事项:

  1. 在声明destinationsource数组的时候应该写上destination的长度,source可不写,destination的长度不写就会导致destination数组不够容纳source的内容。
  2. 在声明destination数组的时候应该最起码多预留一个空间存放\0
  3. destinationsource的内容不应该重叠。

2.函数模拟

代码实现:

char* my_strcat(char* destinaton, const char* source)
{
	assert(destinaton && source);

	char* dest = destinaton;
	char* src = source;

	while (*dest != 0)//找destination的\0
	{
		dest++;
	}

	while (*src != 0)//在遇到source的\0之前把source的元素放到destination里面
	{
		*dest = *src;
		dest++;
		src++;
	}

	*dest = 0;//在destination数组最后面加上\0
}

int main()
{
	char arr1[9] = "abcd";
	char arr2[] = "efgh";
	my_strcat(arr1, arr2);
	puts(arr1);//结果是:abcdefgh

	return 0;
}

5.strtr

1.原函数介绍

//头文件
#include <string.h>

声明:

 char * strstr ( const char * str1, const char * str2 );

文档描述:

  1. 返回str1中第一次出现的str2的指针,如果str2不是str1的一部分,则返回一个空指针。
  2. 匹配过程不包括结束性的空字符,但它在此停止。

检查str1里面有没有str2,有就返回str1里面第一个和str2一样的字符的指针,没有就返回空指针。

参数:

  • str1:要被检查的字符串的指针。
  • str2:要被匹配的字符的指针。

返回值:

        返回指向str2中指定的整个字符在str1中首次出现的指针,如果str1中不存在str2字符,则为空指针。

使用例子:

/* strstr example */
#include <stdio.h>
#include <string.h>

int main()
{

	char arr1[] = "apple is healthy";
	char arr2[] = "healthy";

	char* p = strstr(arr1, arr2);

	if (p == NULL/*或者0*/)//不能写*p
	{
		printf("no");
	}
	else
	{
		printf("%s", p);//结果是healthy
	}

	return 0;
}

2.函数模拟

代码实现:

#include<stdio.h>
char* my_strstr(const char* str1, const char* str2)//在str1里面找str2
{
	char* s1 = NULL;
	char* s2 = NULL;
	char* p = str1;
	
	while (*p)//遍历str1
	{
		s1 = p;//p前面的已经检查过了
		s2 = str2;//看看从str2的首元素开始是否一样

		while (*s1 && *s2 && *s1 == *s2)//遇到有一样的字符,再确定一下是否等于整个str2字符串
		{
			s1++;
			s2++;
		}

		if (*s2 == 0)//直到str2的最后一个字符都相等,说明str2在str1里面
		{
			return p;//返回str1里首个一样的字符的指针
		}

		p++;//继续向前遍历
	}
	return NULL;
}


int main()
{
	char arr1[] = "apple is healthy";
	char arr2[] = "healthy";

	char* p = my_strstr(arr1, arr2);

	if (p == NULL/*或者0*/)//不能写*p
	{
		printf("no");
	}
	else
	{
		printf("%s", p);
	}

	return 0;
}

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值