部分字符串处理函数的介绍

由于C语言中的字符串没有对应的字符串变量储存,所以在C语言中用字符数组存储字符串。字符数组的各个数组元素依次存放字符串的各个字符,字符数组的数组名代表该字符串的首地址。
字符数组的初始化
charc[8]={‘H’,‘e’,‘l’,‘l,‘o’};把6个字符分别赋值给c[0]到c[7]的8个元素,如果初值个数小于数组长度,则将这些字符赋给数组中前面那些元素,将其余元素自动赋值为空字符(’\0’)。字符个数大于数组长度则发生语法错误。
在这里插入图片描述
字符串与字符数组的区别
本质的区别在于“字符串结束标志的使用”,字符数组中的每个元素都可以存放任意的字符,并不要求最后一个字符是“\0”。但对于字符串来说必须以“\0”结束。
字符串的输入与输出
1.采用“%c”格式符,每次输入或者输出一个字符。
eg:用格式符“%c”逐个字符的输出一个字符数组。

#define _CRT_SECURE_NO_WARNINGS 1
#include"stdio.h"
int main()
{
	char c[5] = { 'h', 'e', 'l', 'l', 'o' };
	int i;
	for (i = 0; i < (sizeof(c) / sizeof(c[0])); i++)
	{
		printf("%c", c[i]);
	}
}

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

字符串处理函数

1.求字符串长度函数strlen()
调用新式:size_t strlen( const char *str)
功能:返回字符串str或者字符数组str中字符串的实际长度,不包括’\0’.
Eg:

#define _CRT_SECURE_NO_WARNINGS 1
#include"stdio.h"
int main()
{
	char c[20]= "hello world";
	
		printf("%d\n", strlen(c));
}

函数的模拟实现:(计数器模式)

#define _CRT_SECURE_NO_WARNINGS 1
#include"stdio.h"
int my_strlen(const char * str)
{
	int count = 0;
	while (*str)//遇到\0循环截止
	{
		count++;
		str++;
	}
	return count;
}
 main()
{
	char *str = "addhcb";
	char temp = my_strlen(str);
	printf("%d\n", temp);
}

执行结果:
在这里插入图片描述
2.(不能创建临时变量的计数器)递归

int my_strlen(const char * str)
{
	if (*str == '\0')
		return 0;
	else
		return 1 + my_strlen(str + 1);//递归调用函数本身
}
 main()
{
	char *str = "addhcb";
	char temp = my_strlen(str);
	printf("%d\n", temp);
}

运行结果:
在这里插入图片描述
3.使用指针通过指针的的运算来计算字符个数:

int my_strlen(const char * str)
{
	char*p = str;
	while (*p != '\0')//指针p走到\0的位置处截止
	{
		p++;
	}
	return p - str;//从而计算字符串中的字符个数
}
 main()
{
	char *str = "addhcb";
	char temp = my_strlen(str);
	printf("%d\n", temp);
}

在这里插入图片描述
2.字符拷贝函数strcpy()
Copy a string.
函数调用形式:
char *strcpy( char *strDestination, const char *strSource );
功能:将原字符数组考到目标字符数组中去。
Eg:

 int main()
 {
	 char str1[20], str2[] = "dfsdsf";
	 strcpy(str1, str2);
	 printf("%s", str1);

 }

在这里插入图片描述
模拟实现:通过循环把str中的字符赋给dest中。

 char *my_strcpy(char *dest, const char*src)
 {
	 assert(dest != NULL);//判断字符数组不为空
	 assert(src != NULL);
	 int len = strlen(src); int i;
	 for (i = 0; i < len+1; i++)//多拷贝一个\0
	 {
		 *dest = *src;
		 dest++;
		 src++;
	 }
 }
 int main()
 {
	 char str1[20], str2[] = "dfsdsf";
	 my_strcpy(str1, str2);
	 printf("%s", str1);

 }

执行结果
在这里插入图片描述
2.代码优化:

 char *my_strcpy(char *dest, const char*src)
 {
	 char *ret = dest;//定义ret来接收dest
	 assert(dest != NULL);//判断字符数组不为空
		 assert(src != NULL);
	 while ((*dest++ = *src++))//*的优先级大于后置++,当遇到\0循环截止
	 {
		 ;
	 }
	 return ret;
 }

运行结果:
打印在这里插入图片描述
memcpy()
调用形式:void *memcpy( void *dest, const void *src, size_t count );
1.函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置。
2.这个函数在遇到 ‘\0’ 的时候并不会停下来(strcpy()拷贝时遇到\0会停止。)。
3.如果source和destination有任何的重叠,他所复制的结果都是为定义的。
Eg:
在这里插入图片描述
在打印过程中拷贝了str1中的13个字符到str中,打印str结果为 i love you说明第11字符 \0也被拷贝到了str中。
模拟实现:

void * my_memcpy(void * dst, const void * src, size_t count)
 {
	 void *ret = dst;
	 assert(dst);
	 assert(src);
	 while (count--)//控制循环次数
	 {
		 *(char*)dst = *(char*)src;
		 dst = (char*)dst+1;
		 src = (char*)src + 1;
	 }
	 return ret;
 }
 int main()
 {
	 char str[20], str1[] = { "i love you\0 baby" };
	 my_memcpy(str, str1, 13);
	 printf("%s\n", str);
 }

运行结果:
在这里插入图片描述
strcat()
连接两个字符数组中的字符串,把str2连接到str1的后面,并自动覆盖str1所指字符串的尾部字符‘\0’,结果放在str1中,函数调用后得到str1的地址。
Eg:

 void main()
 {
	 char str1[30] = "hello";
	 char str2[] = "world";
	 strcat(str1, str2);
	 printf("%s", str1);
 }

实现结果:
在这里插入图片描述
调用形式
char *strcat( char *strDestination, const char *strSource );
模拟实现:

char *my_strcat(char *dest, const char*src)
{
	char *ret = dest;//接收dest的结果值
	assert(dest != NULL);//保证字符数组不为空
	assert(src != NULL);
	while (*dest)//循坏截止条件:在遇到\0
	{
		dest++;//让dest地址走到\0位置处
	}
	while ((*dest++ = *src++))//把str中的得字符考到dest的后面。
	{
		;
	}
	return ret;
}
void main()
{
	char str1[30] = "hello";
	char str2[] = "world";
	my_strcat(str1, str2);
	printf("%s", str1);
}

运行结果:
在这里插入图片描述
strstr()
Find a substring.
判断字符串str2是否是str1的的字串,如果是返回str1字符串从str2第一次出现的位置开始到str1结尾的字符串。
调用形式:
char *strstr( const char *string, const char *strCharSet );
Eg:

void main()
{
	char str1[20] = "sggdbnkscd";
	char  str2[] = "gdb";
	char*p;
	p=strstr(str1, str2);
	puts(p);
}

运行结果:
在这里插入图片描述
模拟实现:
在这里插入图片描述
str2中的字符跟str1的数组进行比较一个位置进行比对直到str2中的最后一字符能在str1中与之对因就从str1中的开始位置输出剩余字符。否则从str1+1位置处在于str2进行比较。

char *my_strstr(const char* str1, const char* str2)
{
	assert(str1);//确保不为空
	assert(str2);
	char *cp = (char*)str1;
	char *substr = (char *)str2;
	char *s1 = NULL;
	if (*str2 == '\0')
		return NULL;
	while (*cp)
	{
		s1 = cp;
		substr = str2;
		while (*s1 && *substr && (*s1 == *substr))//确保两个数组没走到最后并且两个数组中的字符匹配。
		{
			s1++;
			substr++;
		}
		if (*substr == '\0')
			return cp;
		cp++;
	}
}

void main()
{
	char str1[20] = "sggdbnkscd";
	char  str2[] = "gdb";
	char*p;
	p = my_strstr(str1, str2);
	puts(p);
}

运行结果:
在这里插入图片描述
memmove()
用于拷贝字节,如果目标区域和源区域有重叠的话,memmove()能够保证源串在被覆盖之前将重叠区域的字节拷贝到目标区域中,但复制后原内容将会被更改。但是目标区域没有重叠的话跟memcpy的作用是一样的。
调用形式:
void *memmove( void *dest, const void *src, size_t count );
Eg:

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

运行结果:
在这里插入图片描述
模拟实现:

void * my_memmove(void * dst, const void * src, size_t count)
 {
	 void * ret = dst;
	 if (dst <= src || (char *)dst >= ((char *)src + count)) 
	 {

		 while (count--) 
		 {
			 *(char *)dst = *(char *)src;
			 dst = (char *)dst + 1;
			 src = (char *)src + 1;
		 }
	 }
	 else {

		 dst = (char *)dst + count - 1;
		 src = (char *)src + count - 1;
		 while (count--)
		 {
			 *(char*)dst = *(char*)src;
			 dst = *(char*)dst - 1;
			 src = *(char*)src - 1;
		 }
	 }
 }
 int main()
 {
	 char str[] = "memmove can be very useful......";
	 my_memmove(str + 20, str + 15, 11);
	 puts(str);
	 return 0;
 }

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值