int strcmp(const char* str1,const char *str2)
strcmp函数用来比较字符串的,strcmp函数是根据ASCII码来比较两个字符串的。若两个字符串完全相等,则返回0;若第一个字符串大于第二个字符串,则返回大于0的数值;若第一个字符串小于第二个字符串,则返回小于0的数值。
传说中的源码:(看看原理即可)
int __cdecl strcmp (const char * src, const char * dst)
{
int ret = 0 ;
while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;
if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;
return( ret );
}
改编:
为了减少函数参数的传参局限性,进行了如下的变动,主要是判断字符的情况看注释,关于比较大小的情况,用的时候返回的非零值情况也不多,主要是看是否相等
int str_cmp(void *str1,void *str2)
{
uint8_t * str_1=(uint8_t*) str1;//强制转化
uint8_t * str_2=(uint8_t*) str2;
if((*str_1)=='\0'&&(*str_2)=='\0')
{
printf("都为空");
return 0;
}
else
{
while(*str_1==*str_2)
{
str_1++;
str_2++;
if(*str_1==*str_2&&*str_1=='\0')
{ printf("不为空,且相等");
return 2;
}
}
printf("不为空,但是不相等");
return 1;
}
}
int strlen(const char * const s)
源码
int strlen(const char * const s)
{
int i;
for (i = 0; s[i]; i++) ;
return i;
}
改编:
三种改编,分别是常用情况,递归调用,指针写法,自行理解
int str_len1(void *str)//一般调用
{
uint8_t *st=(uint8_t*)str;
uint8_t i=0;
while(*st++!='\0')
{
i++;
}
return i;
}
int str_len2( void *str)//递归调用
{
uint8_t *st=(uint8_t *)str;
return (*st!='\0'?(1+str_len2(st+1)):0);
}
int str_len3(void *str)//指针写法
{
uint8_t *st=(uint8_t*)str;
while(*st!='\0')
{
st++;
}
return st-str;
}
char * __cdecl strstr(const char *str1, const char *str2)
strstr()函数接受两个指向字符串的指针作为参数,如果第2个字符串包含在第1个字符串中,该函数将返回第1个字符串开始的地址。若没有对应子串,则返回NULL。
源码
char * __cdecl strstr(const char *str1, const char *str2)
{
char *cp = (char *)str1;
char *s1, *s2;
if (!*str2)
return((char *)str1);
while (*cp)
{
s1 = cp;
s2 = (char *)str2;
while (*s2 && !(*s1 - *s2))
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
改编:
1)递归调用
uint8_t的使用注意调用头文件
思路:
以子串第一个字符串为基准开始在母串中遍历查找,一旦找到第一个相同的字符,开始对字串长度的数量进行比较,如果符合,此字符串为母串中第一个符合条件的字符串,反之,如果不符合回调此函数,传入的母串地址增加
uint8_t *str_(void *str_1,void *str_2)
{
uint8_t *str1=(uint8_t*) str_1;
uint8_t *str2=(uint8_t*) str_2;
int len;
uint8_t i;
len=(uint8_t)str_len2(str_2);
while(*str1!=*str2)
{
str1++;
if(*str1=='\0')
{
return (NULL);
}
}
for(i=0;i<len;i++)
{
if(*str1==*str2)
{
str1++;
str2++;
}
else
{
str_(str1,str_2);
}
}
return str1-len;
}
2)根据源码后改编的思路
思路:
首先判断两个字符串,如果其中一个为空,则返回NULL,从母串开始遍历
uint8_t *str_str(void *str_1,void *str_2)
{
uint8_t *str1=(uint8_t*) str_1;
uint8_t *str2=(uint8_t*) str_2;
uint8_t *cp;
uint8_t len;
uint8_t i;
len=str_len2(str_2);
if(str_len2(str_2)==0||str_len2(str_1)==0)
{
return NULL;
}
while(*str1)
{
cp=str1;
if(*cp==*str2)
{
for(i=0;i<len;i++)
{
if(*cp==*str2)
{
cp++;
str2++;
}
else
{
break;
}
return str1;
}
}
str1++;
}
return NULL;
}
其他
对于源码的追求是不能减少的,这样的算法很经典,值得我们模仿和学习