详解字符串函数的使用

详解字符串函数的使用

  • 前言
  • 1.求字符串长度
    • 1.1strlen
  • 2.长度不受限制的字符串函数
    • 2.1 strcpy
    • 2.2 strcat
    • 2.3 strcmp
  • 3.长度受限制的字符串函数
    • 3.1 strncpy
    • 3.2 strncat
    • 3.3 strncmp
  • 4.字符串查找
    • 4.1 strstr
    • 4.2 strtok
  • 5.错误信息报告
    • 5.1 strerror
  • 6内存操作函数
    • 6.1 memcpy
    • 6.2 memmove
    • 6.3 memset
    • 6.4 memcmp

前言

C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常
量字符串中或者字符数组中。字符串常量适用于那些对它不能做修改的字符串函数。本章节重点介
绍处理字符和字符串的库函数的使用和注意事项。

在讲字符串函数使用之前我们先学一下const,和assert。
1:const的意思是不可修改的意思。
2:assert他是个断言函数,头文件是include,他的做作用之一是判断是否为有效值。

1.求字符串长度

1.1strlen

strlen的函数形式:

size_t strlen(const char* string)

头文件是include

这里size_t的意思是无符号整形,其实是用typedef重命名typedef unsigned int size_t由来的。

我们来简单的使用一下。
详解字符串函数的使用_第1张图片
这个函数使用起来是比较简单的,但是我们不光要学会使用还用知道这个函数是怎么实现的。但是在模拟实现这个函数的时候,我们必须知道这个函数的实现原理,即这个函数是从哪开始的,又是从哪里结束的。这里我们可以借鉴一下“注意事项”。

我们看下面一段代码:
详解字符串函数的使用_第2张图片
我们会发现,怎么计算的是74一个这么大的随机数数啊?这个正确答案明显是6。
我们再看这段代码:
详解字符串函数的使用_第3张图片
我们会发现它只计算了’\0’之前的的三个字符,那现在我们知道了strlen函数是从首个字符开始计算,知道遇到\0停止。

我们再看一段代码:

int main()
{
	if (strlen("abc") - strlen("abcdef") > 0)
	{
		printf("hehe\n");
	}
	else
	{
		printf("haha\n");
	}
	return 0;
}

你觉得答案是什么呢?相信大多数人的第一眼都认为答案是haha,但是我要告诉你们的是,答案是hehe。为什么呢?这我们就要回到strlen函数的返回值,返回值是size_t,这是个什么呢?这个其实是无符号整形的意思,其实是用来typedef重命名得来的 typedef unsigned int size_t。

所以上面的3-6=-3,无符号整型-无符号整型得到的还是无符号整型,所以得吧-3看成无符号整型来看,这就说的过去为什么是hehe了。

现在我们知道了strlen是怎么实现的,那我们就来模拟实现一下吧。接下来我会使用三种方法来模拟实现strlen函数。
1:计数器:

#include<stdio.h>
#include<string.h>
#include<assert.h>
size_t My_strlen(const char* str)//str是不可修改的,所以用const修饰。
{
	int count=0;
	assert(str!=NULL);//因为传过来的是指针,所以用assert断言判断指针的有效性。
	while(*str!='\0')
	{
		count++;
		str++;
	}
	return count;
}
int main()
{
	char arr[]="abcdef";
	int ret=My_strlen(arr);
	printf("%d",ret);
	return 0;
}

2:递归

#include<stdio.h>
#include<string.h>
#include<assert.h>
size_t My_strlen(const char* str)
{
	int count=0;
	assert(str!=NULL);
	while(*str!='\0')
	{
		return 1 + My_strlen(str + 1);
	}
}
int main()
{
	char arr[]="abcdef";
	int ret=My_strlen(arr);
	printf("%d",ret);
	return 0;
}

3:指针-指针

#include<stdio.h>
#include<string.h>
#include<assert.h>
size_t My_strlen(const char* str)
{
	char* source=str;
	assert(str!=NULL);
	while(*str!='\0')
	{
		str++;
	}
	return str-source;
}
int main()
{
	char arr[]="abcdef";
	int ret=My_strlen(arr);
	printf("%d",ret);
	return 0;
}

总结:

1 :字符串以'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个(不包含'\0')。
2:参数指向的字符串必须要以'\0'结束。
3:注意函数的返回值为size_t,是无符号的。

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

2.1 strcpy

strcpy的函数形式:

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

头文件include
strcpy名为字符拷贝,顾名思义就是将source的字符拷贝到destination里面去。
我们来间的的使用一下。
详解字符串函数的使用_第4张图片
这里我们发现’\0’也拷贝过去了,那我们就可大胆的猜测一下,是不是他就是以’\0‘为结束标志呢?答案是肯定的。

那如果将arr1里面的字符拷贝到arr2行不行呢?
详解字符串函数的使用_第5张图片
这里我们的发现虽然可以打印出来,但是会报错误。其实原理很简单,你可以模拟一下穿鞋子,你的脚是41码的,但是你非要穿36的鞋子,你说会不会出问题吧,所以,拷贝的目标空间必须足够大,起码要大于源字符串的空间。

那我们看一下下面的代码。
详解字符串函数的使用_第6张图片
我们就是吧刚才的arr1改成了*p,改完后p就是个常量字符串,是可修改的,这个时候我发现系统有报错了,并且也没法运行,也就出不了结果来。
这就说明了,我们的目标空间必须时可变的。

现在我们知道了他是怎开始和结束的,也知道了他的使用规范,那我们就来模拟实现一下strcpy函数。

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* My_strcpy(char* dest,const char* src)
{
	assert(dest!=NULL);
	assert(src!=NULL);
	char* bigan=dest;
	while(*src!='\0')
	{
		*dest=*src;
		dest++;
		src++;
	}
	*dest=*src;//拷贝\0;
	return bigan;//返回起始空间的地址,因为他的返回类型是char*指针。
}
int main()
{
	char arr1[]="abcdefg";
	char arr2[]="hijk";
	char* ret=My_strcpy(arr1,arr2);
	printf("%s",ret);
	return 0;
}

这里我们可以升级一下:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* My_strcpy(char* dest,const char* src)
{
	assert(dest!=NULL);
	assert(src!=NULL);
	char* bigan=dest;
	while(*dest++=*src++)
	{
		;
	}
	return bigan;
}
int main()
{
	char arr1[]="abcdefg";
	char arr2[]="hijk";
	char* ret=My_strcpy(arr1,arr2);
	printf("%s",ret);
	return 0;
}

总结:

1:源字符串必须以'\0'结束。
错误示范:char arr[]={'a','b','c'};
2:会将源字符串中的'\0'拷贝到目标空间。
3:目标空间足够大,以确保能存放源字符串。
错误示范:char arr1="a",char arr2="abcdefg";
4:目标空间必须可变。

2.2 strcat

strcat的函数形式:

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

头文件include

strcat名为字符串追加,顾名思义就是将source里面的字符串追加到destination里面去。
我们来简单的使用一下:
详解字符串函数的使用_第7张图片
这里我们可以很清楚的知道,再追加的时候他是从destination的\0开始追加的,并且source里面的\0也会追加过去,也就是说字符串追加是从第一个遇到的’\0’开始追加的,并且还会把\0追加过去。

同样的道理这里的目标空间必须有足够大的空间,能容纳源字符串的内容。
详解字符串函数的使用_第8张图片

这张图出现了和strcpy相同的错误,同样也说明了目标空间必须可修改。

现在我们知道了他是怎开始和结束的,也知道了他的使用规范,那我们就来模拟实现一下strcat函数。

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* My_strcat(char* dest,const char* src)
{
	char* bigan=dest;
	assert(dest!=NULL);
	assert(src!=NULL);
	while(dest!='\0')
	{
		dest++;
	}
	while(*dest++=*src)
	{
		;
	}
	return bigan;
}
int main()
{
	char arr1[30]="hello";
	char arr2[]="world";
	char* ret=My_strcat(arr1,arr2);
	printf("%s",ret);
	return 0;
}

那如果字符串追自己给自己追加会是怎么样呢?我们来试一试

int main()
{
	char arr1[30] = "hello";
	strcat(arr1, arr1);
	printf("%s", arr1);
	return 0;
}

注:这里其实是不能够实行的,但是有些编译器是可以编译出来的,但是实际上这样是错误的写法的,报错。因为再找到arr1的\0并开始追加arr1的时候,arr1就是在变化的,那么source也就是arr1就是在变化的,因为你在给自己追加自己,这样的话,那你的结束标记也就是找到arr1的\0就永远找不到,就会报错。

总结:

1:源字符串必须以'\0'结束。
2:目标空间必须有足够大的空间,能容纳源字符串的内容。
3:a目标空间必须可修改。

2.3 strcmp

strcmp的函数形式:

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

头文件:include

strcmp名为字符串比较,其实比较的就是字符的ASCLL码值。

他的返回特点:

1:第一个字符串大于第二个字符串,返回大于0的数字。
2:第一个字符串小于得二个字符串,返回小于0的数字。
3:第一个字符串等于第二个字符串,返回0。

我们来简单的使用一下:
详解字符串函数的使用_第9张图片
这里返回的是-1小于0的数,那就说明p1小于p2的,但是我们发现p1由6个字符,p2只有5个字符,这就说明了strcmp比较的不是字符的个数。其实strcmp是对字符串里面的字符是一对一对的进行比较的。举个例子。

char* p1="abcdef";
char* p2="abcghi";

这里首先是p1里面的a和p2里面的a进行比较,发现他们相同,这个时候就跳过a进行下一对进行比较,就是p1里面的b和p2里面的b比较,以此类推直到遇到不同的字符进行比较或者两者都遇到\0就会停止。而这里遇到p1的d和p2的g比较,发现p2大于p1,就返回小于0的数。
详解字符串函数的使用_第10张图片
现在我们来模拟实现一下:

#include<stdio.h>
#include<string.h>
#include<assert.h>
int My_strcmp(const char* str1, const char* str2)
{
	assert(str1 != NULL);
	assert(str2 != NULL);
	//比较
	while (*str1 == *str2)
	{
		if (*str1 == '\0')
			return 0;
		str1++;
		str2++;
	}
	return *str1 - *str2;
}
int main()
{
	const char* p1 = "abcdef";
	const char* p2 = "sqwer";
	int ret = My_strcmp(p1, p2);
	printf("%d", ret);
	return 0;
}

总结:

1:字符串比较的是字符的ASCLL码值,不是字符的个数。
2:比较的时候是一对一对的比较的,直到遇到不相等的或者遇到\0才会停止。

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

3.1 strncpy

strncpy的函数形式:

char* strncpy(char* destination,const char* source,size_t num)

头文件:include

可以发现strncpy就比strcpy多了一个参数size_t num,而strncpy的作用就是将source里面的num个字符拷贝到destination里面。

我们来简单的使用一下:
详解字符串函数的使用_第11张图片
那如果num的个数大于source的字符个数会怎么样呢?
详解字符串函数的使用_第12张图片
我们会发现这里arr2没有7个字符,只有5个字符,但是他拷贝的时候却拷贝了7个过去,剩下的两个用\0充当了。

现在我们模拟实现一下:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* My_strncpy(char* dest, const char* source, int num)
{
	assert(dest && source);
	char* ret = dest;
	while (num != 0 && (*dest++ = *source++))
	{
		num--;
	}
	if (num)//源字符串长度小于num
	{
		while (num)
		{
			*dest++ = '\0';
			num--;
		}
	}
}
int main()
{
	char arr1[12] = "abcdefghij";
	char arr2[] = "hello";
	My_strncpy(arr1, arr2, 5);
	printf("%s", arr1);
	return 0;
}

总结:(其实strncpy的特点和strcpy的特点是相似的)

    1:源字符串必须以'\0'结束。
错误示范:char arr[]={'a','b','c'};
2:会将源字符串中的'\0'拷贝到目标空间。
3:目标空间足够大,以确保能存放源字符串。
错误示范:char arr1="a",char arr2="abcdefg";
4:目标空间必须可变。
5:拷贝num个字符从源字符串到目标空间
6:如果源字符串的长度小于num,则拷贝完源字符串之后,在目标的后面追加\0,直到num个。

3.2 strncat

strncat的函数形式:

char* strncat(char* destination,const char* source,size_t num)

头文件:include

这里也是一样的strncat就比strcat多了size_t num这一个参数,他也是将source里面的num个字符追加到destination里面去。

我们来简单的实现一下:
详解字符串函数的使用_第13张图片
我们再看一下下面一段代码:
详解字符串函数的使用_第14张图片
我们就会发现它和strcat一样遇到第一个\0后开始追加的。

那我我们来尝试一下,当num大于source里面的字符个数会不会像strncpy一样把多余的用\0充当。
详解字符串函数的使用_第15张图片
这里我们发下他并没有将多余的用\0充当,也就是说无论你多了多少没追加的,他都只会追加一个\0过去。

现在我们来模拟实现一下:

#include<stdio.h>
#include<stdio.h>
#include<assert.h>
char* my_strncat(char* dest, const char* src, int num)
{
	assert(dest != NULL);
	assert(src != NULL);
	char* bigan = dest;
	while (*dest != '\0')
	{
		dest++;
	}
	while (num-- &&*src!='\0')
	{
		
		*dest++ = *src++;
	}
	*dest = '\0';
	return bigan;
}
int main()
{
	char arr1[20] = "hell\0oxxxx";
	char arr2[] = "world";
	char* ret = my_strncat(arr1, arr2, 3);
	printf("%s\n", ret);
	return 0;
}

总结:
1:源字符串必须以’\0’结束。
2:目标空间必须有足够大的空间,能容纳源字符串的内容。
3:a目标空间必须可修改。
3:如果num大于source的字符个数,剩余的空间只追加一个\0。

3.3 strncmp

strncmp的函数形式:

size_t strncmp(const char* string1,const char* string2,int num)

strncmp的大概意思就是比较num个字符。

来简单的实现一下:
详解字符串函数的使用_第16张图片
这个比较方法和strcmp是一样的,只是多了个比较的个数。

现在来模拟实现一下:

#include<stdio.h>
#include<string.h>
#include<assert.h>
 My_strncmp(const char* arr1, const char* arr2, int num)
{
	assert(arr1 && arr2);
	while (--num && (*arr1) && (*arr1 == *arr2))
	{
		arr1++;
		arr2++;
	}
	return *arr1 - *arr2;
}
int main()
{
	const char* p1 = "hello";
	const char* p2 = "world";
	int ret = My_strncmp(p1, p2,1);
	printf("%d", ret);
	return 0;
}

4.字符串查找

4.1 strstr

strstr的函数形式:

char* strstr(const char* p1,const char* p2)

他的功能是在p1里面找p2,如果找到了就返回找到的字符的首地址回去,如果没找到就返回NULL。
我们来实现一下:
详解字符串函数的使用_第17张图片
我们再看一段代码
详解字符串函数的使用_第18张图片
这里虽然找到了def但是打印出来的却是defghi,这是因为找到了def他就会返回arr1中d的地址,打印的时候就会从d开始打印,直到遇到\0停止。

那我们再看一段代码:
详解字符串函数的使用_第19张图片
这里arr1中虽然有两个def,但是他还是会从第一次出现的def开始打印。

现在我们来模拟实现一下:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* My_strstr(const char* p1,const char* p2)
{
	assert(p1!=NULL);
	assert(p2!=NULL);
	if(*p1=='\0')
	{
		return p1;
	}
	while(*p1)
	{
		while((*p1==*p2)&&(*p1!='\0')&&(*p2!='\0'))
		{
			p1++;
			p2++;
		}
		if(*p2=='\0')
		{
			//一般这是我们的正常思路,但是你会发现当找到了全部的p2的时候,找不到返回的
			//地址了,所以这样是错误的代码,那现在我们就可以设置一个变量来代替p1和p2,
			//而p1和p2不变
			
		}
		p1++;
	}
	return NULL;
}
int main()
{
	char* arr1 = "abbbcdef";
	char* arr2 = "bbc";
	char* ret = My_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("子串不存在\n");
	}
	else
	{
		printf("%s", ret);
	}
	return 0;
}

另外有种特殊情况:

char* arr1[]="abcdddef";
char* arr2[]="dde";

详解字符串函数的使用_第20张图片
当这种情况的时候,看上去么有找到,其实是可以找到的,那这个时候s2就要回到p2,而s1只向后退一步,再重新开始就可以找到了,这个时候我们就得再要一个变量ret来储存这个变量。
详解字符串函数的使用_第21张图片

现在我们来写正确的代码:

#include<stdio.h>
#include<string.h>
#include<assert.h>
char* My_strstr(const char* p1,const char* p2)
{
	assert(p1!=NULL);
	assert(p2!=NULL);
	char* s1=NULL;
	char* s2=NULL;
	char* ret=p1;
	if(*p1=='\0')
	{
		return p1;
	}
	while(*ret)
	{
		s1=ret;
		s2=p2;
		while((*s1 == *s2) && (s2 != '\0') && (*s1 != '\0'))
		{
			s1++;
			s2++;
		}
		if(*s2=='\0')
		{
			return ret;
		}
		ret++;
	}
	return NULL;
}
int main()
{
	char* arr1 = "abbbcdef";
	char* arr2 = "bbc";
	char* ret = My_strstr(arr1, arr2);
	if (ret == NULL)
	{
		printf("子串不存在\n");
	}
	else
	{
		printf("%s", ret);
	}
	return 0;
}

4.2 strtok

strtok的函数形式:

char* strtok(char* str,const char* sep)

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

下来简单的使用一下:
详解字符串函数的使用_第22张图片
我们看到这里只打印了123后面的却没有出来,这是因为是声明了一个库函数。
详解字符串函数的使用_第23张图片
这样声明了三个函数,虽然都显示出来了,但是不难想象一下如果由几百个怎么办,所以我们来优化一下:
详解字符串函数的使用_第24张图片
这样是不是更加简便而且还通用。

5.错误信息报告

5.1 strerror

strerror的函数形式:

 char* strerror(int errnum)

作用:将错误码转换成错误信息。
详解字符串函数的使用_第25张图片
上面的数字就是错误码,输出的结果就是错误信息。
但是我们使用的时候肯定不是直接的输入数字的。

#include<stdio.h>
#include<errno.h>
int main()
{
	char* str=strerror(errno);//errno 是一个全局的错误码的变量,当C语言中的库函数在执行
							  //过程中发生了错误,就会把对应的错误码赋值到errno中。
							  //头文件include
	printf("%s",str);
}

我们来使用一下:
详解字符串函数的使用_第26张图片

另外我们还有有些字符分类函数:
字符分类函数:
函数        如果它的参数符合下列条件就返回真
iscntrl     任何控制字符
isspace     空白字符:空格‘ ’,换页‘\f’,换行'\n',回车'\r',制表符'\t',或垂直制表符'\v'
isdigit     十进制数字0~9
isxdigit    十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F
islower     小写字母a~z
isupper     大写字母A~Z
isalpha     字母a~z或A~Z
isalnum     字母或数字a~z,A~Z或0~9
ispunct     标点符号,任何不属于数字或字母的图像字符(可打印符号)
isgraph     任何图像字符
字符转换:
int tolower ( int c );  //大写字符转小写字符
int toupper ( int c );  //小写字符转大写字符

6内存操作函数

像之前的
strcpy
strncpy
strcat
strncat
strcmpy
strncmp
····
这些字符串函数,他们的操作对象都是字符串,并且都必须以\0结尾,但是他们不适用于整形数组,浮点数组,结构体数组等其他的数组,只单独对字符数组有用。所以这就有了内存操作数组,他是针对都有类型的。

例如:
详解字符串函数的使用_第27张图片
我们原本想把arr1中的12345拷贝到arr2中,但是只有1拷贝过去了,这个时候我们就要注意了,之前的所有字符串函数对应的都是一个字节,这里的strcpy也是,他是一个一个字节的拷贝的,这里arr1在内存里的存放方式是:

01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 05 00 00 00

而拷贝的时候是一个一个字节的拷贝过去的,而遇到’\0’(0)就停止了,所以遇到1后面的0就停止拷贝了,这就是为什么只拷贝了一个1过去的原因。

6.1 memcpy

memcpy的函数形式:

void* memcpy(void* destination,const viod* source,size_t num)

头文件:include

之所以可以针对所有类型的数组,就在于void*。如果还有不明白void*的,可以去 详解之进阶指针中的qsort函数冒泡函数模拟实现里面了解。

我们来简单的实现一下:
详解字符串函数的使用_第28张图片
现在我们来模拟实现一下:

void* My_memcpy(void* dest, const void* src, size_t num)
{
	assert(dest != NULL);
	assert(src != NULL);
	void* ret = dest;
	while (num--)
	{
		*(char*)dest = *(char*)src;
		++(char*)dest;
		++(char*)src;
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[5] = { 0 };
	int i=0;
	char* ret=My_memcpy(arr2, arr1, sizeof(arr1));
	for(i=0;i<5;i++)
	{
		printf("%d ",arr1[i]);
	}
	return 0;
}

6.2 memmove

memmove函数的形式:

void* My_memcpy(void* dest, const void* src, size_t num)
这里的num指的是拷贝多少个字节。

头文件:include

memmove的功能是处理重叠拷贝。
就比如:
详解字符串函数的使用_第29张图片
本来我们要的是1 2 1 2 3 4 5 6 7 8 9 10,但是他给我们却不是这样,这个原理其实和strcpy自己拷贝字节的原理是一样的。

注:这里用的不是库函数里面的memcpy是因为,memcpy其实在有些编译器里面是可以进行重叠拷贝的。但是:

C语言标准:
memcpy 只要处理 不重叠的内存拷贝就可以了
memmove 是处理重叠内存拷贝
这个时候memmove就派上用场了

我们现在来简单的实现一下:
详解字符串函数的使用_第30张图片
那现在我们来分析一下:
详解字符串函数的使用_第31张图片
像这样的情况 dest 详解字符串函数的使用_第32张图片
像这样的情况 dest>src 我们就可以将src里面的字符按照从后到前的方式一一拷贝过去。
这样,我们就可以进行模拟实现了:

 void* My_memmove(void* dest,const void* src,size_t num )
{
	assert(dest!=NULL);
	assert(src!=NULL);
	char* ret=dest;
	if(dest<src)//前->后
	{
		while(num--)
		{
			*(char*)dest=*(char*)src;
			++(char*)dest;
			++(char*)src;
		}
	}
	else//后->前
	{
		while(num--)
		{
			*((char*)dest+num)=*((char*)+num);
		}
	}
	return ret;
}
int main()
{
	int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };
	int i = 0;
	My_memmove(arr1+2, arr1, 20);
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

6.3 memset

memset函数形式:

void* memset(void* dest,int c,size_t)
c指的是设置多少个符。

功能:将dest的num个字节,用c替换。

在一段内存中填充某个给定的值,它是比较大的结构体或数组进行清零操作的一种最快的方法。

我们来简单的使用一下:
详解字符串函数的使用_第33张图片
模拟实现:

void* My_memset(void* src, int n, size_t num)
{
	assert(src != NULL);
	void* bigan = src;
	while (num--)
	{
		*(char*)src = (char)n;
		++(char*)src;
	}
	return bigan;
}
int main()
{
	char arr[] = "abcdef";
	char* ret=My_memset(arr, '#', 4);
	printf("%s", arr);
	return 0;
}

6.4 memcmp

memcmp的函数形式:

int memmove(const void* ptr1,const void* ptr2,size_t num)
num指的是待比较的字节。
这个函数不会因为 遇到\0就停止比较了。

头文件:include

他的返回之特点和strcmp是一样的。

1:第一个字符串大于第二个字符串,返回大于0的数字。
2:第一个字符串小于得二个字符串,返回小于0的数字。
3:第一个字符串等于第二个字符串,返回0。

我们来简单的实现一下:

详解字符串函数的使用_第34张图片
详解字符串函数的使用_第35张图片
我们看上面两段代码,那他们是怎么比较出来的呢

详解字符串函数的使用_第36张图片
详解字符串函数的使用_第37张图片
刚才我们知道了,num是比较多少个字节,这里是一个一个字节的比较,知道比较到两个内存数组不相等,或者num个直接都相同返回0。

现在我们来模拟实现一下:

#include<stdio.h>
#include<string.h>
#include<assert.h>
int My_memcmp(const void* ptr1, const void* ptr2, size_t num)
{
	assert(ptr1 != NULL);
	assert(ptr2 != NULL);
	const char* s1 = (char*)ptr1;
	const char* s2 = (char*)ptr2;
	if (!num)
		return 0;
	while (--num && *s1 == *s2)
	{
		s1++;
		s2++;
	}
	return *s1 - *s2;
}
int main()
{
	int arr1[] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,5,6,3 };
	int ret = My_memcmp(arr1, arr2, 8);
	printf("%d", ret);
}

好了到这里,学习也就完毕了,能看到这的小伙伴们你们是我最大的动力,博主我也是尽我最大的努力,用最平常的话来讲明白知识点,我也是花了大量的时间来做这个,望大家多多支持。

你可能感兴趣的:(c语言,c++,开发语言)