C语言函数:字符串函数及模拟实现strcmp()

C语言函数:字符串函数及模拟实现strcmp()

strcmp()函数:

        作用:进行字符串的比较大小。

引入:如下代码,

#define _CRT_SECURE_NO_WARNINGS

#include 

int main()
{
	char* p = "wan";
	char* q = "ban";
	if (p > q)
		printf(">");
	else if ("abc" > "abeiqeaf")
		printf(">=");
	//这两种方法比较的都是字符串首元素地址,而不是字符串的ASCLL值
	else
		printf("<");
	return 0;
}

        这两种方法比较的都是字符串首元素地址,而不是字符串大小

        因此,如果要比较两个字符串大小,那么就需要用到strcmp()函数。

C语言函数:字符串函数及模拟实现strcmp()_第1张图片

        原理:依次比较两个字符串的ASCII码值,第一个和第一个比、第二个和第二个比。。。

        如上图p和q比较:'w'和'b'比较ASCII码值,w比'b'大。如此p就比q大,不会再看后面的字符串,无论这个q有多少个字符。

        如上图"abc"和"abeiqeaf"比较:'a'比较'a',ASCII码值相同,然后会一起跳到下一个字符,再比较'b''和'b',ASCII码值相同,然后会一起跳到下一个字符,再比较'c''和'e',ASCII不同,那么"abc"就比"abeiqeaf"大。

        如果一样,如"ab"和"ab",strcmp当遇到\0时就会停止,最后这两个字符串相同

        前面看到,strcmp返回值是int类型,这也是为什么strcmp是用来比较大小的关键。

        

         strcmp返回值有三个可能:-1(<0)、0(=0)、1(>0)。

        <0 说明第一个字符串比第二个字符串小。

        =0 说明第一个字符串和第二个字符串一样。

        >0 说明第一个字符串比第二个字符串大。

        

<0:

#define _CRT_SECURE_NO_WARNINGS

#include 

int main()
{
	printf("%d\n",strcmp("abc","abp"));
	//结果: -1
	return 0;
}

=0:

#define _CRT_SECURE_NO_WARNINGS

#include 

int main()
{
	printf("%d\n",strcmp("abc","aba"));
	//结果: 1
	return 0;
}

>0:

#define _CRT_SECURE_NO_WARNINGS

#include 

int main()
{
	printf("%d\n",strcmp("abc","abc"));
	//结果: 0
	return 0;
}

strcmp()函数的模拟实现:

第一种:

C语言函数:字符串函数及模拟实现strcmp()_第2张图片

 与strcmp原理如出一辙

        s1和s2是否相同,相同则继续寻找,当找到\0时停止

        s1和s2不同,判断s1和s2大小,s1>s2返回1,反之返回0。

第二种:

#define _CRT_SECURE_NO_WARNINGS

#include 

int my_strcmp(const char* str1, const char* str2)
{
	int ret = 0;

	while ((ret = *(unsigned char*)str1 - *(unsigned char*)str2) == 0 && *str2)
	{
		++str1, ++str2;
	}

	return ((-ret) < 0) - (ret < 0);
}

int main()
{
	char* p = "a";
	char* q = "a";
	int ret = my_strcmp(p, q);
	if (ret > 0)
		printf("p>q\n");
	else if (ret < 0)
		printf("p

        这里面的my_strcmp的实现,是和库函数内的strcmp是一样的。

        首先看到,while循环,当两个相减等于0并且其中一个不等于\0时,找下一个。

        因为,strcmp实际是比较两个字符串字符相同,既然如此,只需要知道其中一个字符串是不是\0就行,因为如果两个字符串相同,那么长度肯定是一样的,\0的位置就一定一样,如果,其中一个先找到\0或者后找到\0,那么长度肯定不同。因此,只需要找到其中一个不等于\0就行。

        当其中有不同的字符或全部相同时,结束while循环,其中不同的字符包括用\0比较的。
 

        

        return ((-ret) < 0) - (-ret) < 0);这是整段代码的核心,也是最难理解的:

        (-ret) < 0和ret < 0都是比较大小,因此结果肯定是:0或1

        0表示这个表达式不成立,1表示这个表达式成立

        首先是两个都是\0,那么都是0,表达式是0-0=0,则返回0,表示两个字符串相同

        (-ret) < 0如果结果是0说明-----(-ret)>0说明------ret<0(第一个肯定比第二个小)第二个表达式就为1----------0-1结果为:-1

        (-ret) < 0如果结果是1说明-----(-ret)<0说明------ret>0(第一个肯定比第二个大)第二个表达式就为0----------1-0结果为:1

        想必你肯定还是不懂,那就看看下面推导出这个表达式的思路把。

        

得到 return ((-ret) < 0) - (-ret) < 0)的思路:

        既然要返回-1,0,1这三个数,那么这三个数都可以通过0-1,0-0,1-0表示。发现0和1是二进制,就可以想到表达式是否成立的值就是0和1,这两个值的结合就可以完成输出,-1、0、1这三个结果。那么就是怎么组合表达式,使得这个表达式能够输出这三个结果呢? 

        之后发现,如果ret给的负数,就要创建一个表达式让这个表达式的结果为-1,那么就知道第一个肯定比第二个小,-1就可以用0-1表示。试试ret<0这个表达式的结果应该是1,1得到了就差前面的0了,0怎么得到呢?ret>0?那就是ret>0 - ret<0? 

        最后发现ret无论等于负数还是正数,都可以无误地输出-1,0,1这三个结果。代码都是探索出来的。是的,ret>0 - ret<0的确可以,只不过strcmp的作者把前面ret加了-号,学过数学都知道,两边同乘-数,符号方向改变。所以:(-ret) < 0 等同于 (ret > 0),所以(ret>0) - (ret<0)到最后变成了(-ret) < 0) - (-ret) < 0,这样确实是降低了代码的可读性。

        可以了解一下strncmp():

kC语言函数:字符串函数及模拟实现strncpy()、strncat()、strncmp()_srhqwe的博客-CSDN博客

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