C语言实现strcmp、strcpy、strlen函数

本文详细介绍了C/C++中的strcmp,strcpy,strlen函数的使用、源代码实现和工作原理。强调了这些函数在实际编程中的作用以及它们在面试中可能的考察点,帮助提升自学能力和错误排查能力。
摘要由CSDN通过智能技术生成

引言

关于 s t r c m p strcmp strcmp s t r c p y strcpy strcpy s t r l e n strlen strlen 这三个系列其实在竞赛中不常用,但是你面试一些公司的时候他可能会让你去现场把这几个函数写一下来检验你自己的能力吧,因为在学校中肯定是不交实现的,有的甚至都学不到这块来,所以这就考验你自己的自学能力,而且知道了底层实现,在使用过程中出现错误了,也能够更加深入的知道是哪里出错了,用起来也更加得心应手。


头文件

头文件:

#include <cstring>  //cpp风格
#include <string.h>  //c风格

一、strcmp

1.使用介绍

int strcmp(const char* src, const char* dest);  

strcmp:通过字符对应的 ASCLL码来将 s r c src src d e s t dest dest 中的每个字符进行比较

比较规则通过例子来展示:

src   dest
"a"   "b"      -> -1  
"b"   "a"      -> 1
"a"   "a"      -> 0
"a"   "d"      -> -1   //跟差值没关系,只有三种值-1,0,1
"abc"  "abcd"  -> -1
"abcd" "abc"   -> 1
"abc"  "abc"   -> 0
"abc"  "dbc"   -> -1   //只要从左到右只要发现一个字符不一样,就返回该字符的比较结果:-1,0,1

2.源代码实现

int strcmp(const char* src, const char* dest)
{
	int ret = 0;
	unsigned char* p1 = (unsigned char*)src;
	unsigned char* p2 = (unsigned char*)dest;
	while( !(ret = *p1 - *p2) && *p2)
		++p1, ++p2;
	
	if(ret < 0) ret = -1;
	if(ret > 0) ret = 1;
	return ret;
}

3.源码解析

  • 为什么强转成unsigned char*
    答:因为 c h a r char char 类型只有一字节,也就是八位二进制数,最大 127 127 127 (有一位是符号位),而有的特殊字符 ¥ ¥ 存值为 190 190 190 ,如果用 c h a r char char 来存的话值为 − 60 -60 60 ,如此与其它字符进行比较比如’a’,应该是 1 1 1 而结果却是 − 1 -1 1 。而使用无符号类型就比原来在最大值上多了一位,最大为 255 255 255 ,这样就可以了。而且如果超过 255 255 255 的话,这个数的结果为 m o d   256 mod\ 256 mod 256 的值,如果该符号对应的ASCLL为 256 256 256 则为 0 0 0 ,所以还是错的,那么就应该没有比 A S C L L ASCLL ASCLL 码值为 255 255 255 还大的符号了。
  • while( !(ret = *p1 - *p2) && *p2)详解:
    首先是()和!的优先级是更高的所以先算这两个,如果 r e t ret ret 为0,说明这两个字符相等了,取非为真,然后*p2判断p2是否为'\0',如果是解引用为 0 0 0 ,则退出循环,返回 r e t ( 0 ) ret(0) ret(0 。如果不是则两个指针继续向后走,直至遇到 r e t ret ret 不为 0 0 0 ,取非为假,然后根据 r e t ret ret 的正负赋值
  • 为什么不对指针进行判空操作?
    这个可能是设计的问题,因为不能对空地址解引用,否则会返回错误,可能默认不允许传 N U L L NULL NULL 操作,否则解引用让系统去处理这个错误吧。

二、strcpy

1.使用介绍

char* strcpy(char* dest, const char* src);

strcpy: s r c src src 为首地址的字符串拷贝到以 d e s t dest dest 为首地址的上,会把 s r c src src 全部拷贝完直至遇见第一个\0,并最后补上'\0',所以要确保 s r c src src 中有足够的空间使用,否则可能会影响到其它变量的值

2.源代码实现

char* strcpy(char* dest, const char* src)
{
	char* ret = dest;
	while(*src) *dest++ = *src++;  //若遇见第一个'\0'退出
	*dest = '\0';
	return ret;
}

3.源码解析

  • 把字符串 s r c src src 全部拷贝到 d e s t dest dest 上,最后末尾补 0 0 0 ,返回 d e s t dest dest 头(可用链式编程)
  • *dest++ = *src++:++优先级高,所以是先dest++,结果为dest,再*dest,效果就是把src赋值给dest,然后两个指针同时++

三、strlen

1.使用介绍

strlen:返回以str为首地址的字符串的长度

unsigned strlen(const char* str);  

2.源代码实现

unsigned strlen(const char* str)
{
	int cnt = 0;
	while(*str) cnt++, str++;
	return cnt;
}

四、测试

测试代码:

#include <cstdio>
#include <iostream>

using namespace std;

int strcmp(const char* src, const char* dest)
{
	int ret = 0;
	unsigned char* p1 = (unsigned char*)src;
	unsigned char* p2 = (unsigned char*)dest;
	while( !(ret = *p1 - *p2) && *p2)
		++p1, ++p2;
	
	if(ret < 0) ret = -1;
	if(ret > 0) ret = 1;
	return ret;
}

char* strcpy(char* dest, const char* src)
{
	char* ret = dest;
	while(*src) *dest++ = *src++;
	*dest = '\0';
	return ret;
}

unsigned strlen(const char* str)
{
	int cnt = 0;
	while(*str) cnt++, str++;
	return cnt;
}

int main()
{
	//strcmp
	char a[20] = "a";
	char b[20] = "b";
	int res = strcmp(a,b);
	if(res > 0) printf("%s > %s\n", a, b);
	else if(res == 0) printf("%s = %s\n", a, b);
	else printf("%s < %s\n", a, b);
	
	strcpy(a, "abc");
	strcpy(b, "ab");
	res = strcmp(a,b);
	if(res > 0) printf("%s > %s\n", a, b);
	else if(res == 0) printf("%s = %s\n", a, b);
	else printf("%s < %s\n", a, b);
	
	strcpy(a, "ab");
	strcpy(b, "abc");
	res = strcmp(a,b);
	if(res > 0) printf("%s > %s\n", a, b);
	else if(res == 0) printf("%s = %s\n", a, b);
	else printf("%s < %s\n", a, b);
	
	strcpy(a, "ab");
	strcpy(b, "ac");
	res = strcmp(a,b);
	if(res > 0) printf("%s > %s\n", a, b);
	else if(res == 0) printf("%s = %s\n", a, b);
	else printf("%s < %s\n", a, b);
	
	
	//strcpy
	strcpy(a, "e");
	strcpy(b, "abcd");
	strcpy(a,b);
	cout << a << endl;
	
	strcpy(a, "a123456");
	strcpy(b, "abce");
	strcpy(a,b);
	cout << a << endl;
	
	//strlen
	strcpy(a, "12345");
	cout << strlen(a) << endl;
	
	char c[20] = {'1','2','3','\0','4'}; //按道理这就不是个字符串,可是总有些有病的人爱这样出题 
	cout << strlen(c) << endl;
	
	strcpy(a, "123\0456");  //这个挺有意思的\045当成八进制的转义字符了,极为% 
	cout << a << endl;  //123%6
	cout << strlen(a) << endl;  //5
	
	strcpy(a, "");
	cout << strlen(a) << endl;
	
	return 0;
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lijiachang030718

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值