1.strlen函数: size_t strlen ( const char * str )
返回非零整数
用途:用于计算字符数组长度,计算 '\0'之前的长度不包括 '\0'
所需头文件:include <string.h>
案例:
#include <stdio.h>
#include <string.h>
int main()
{
char arr[] = "abcde";
int sz = strlen(arr);
printf("%d",sz);
return 0;
}
//输出结果为5
模拟strlen:
原理:定义一个指针访问数组首地址,并一直向后访问,指针走一次num记录一次,输出num值
void My_strlen(char* arr)
{
char* p = arr;
int num = 0;
while (*p != '\0')
{
p++;
num++; //这里用num记录字符数组长度
}
printf("%d", num);
}
int main()
{
char arr[10] = "abcde";
My_strlen(arr);
return 0;
}
2.strcpy函数:char * strcpy ( char * destination, const char * source )
返回字符串
用途:把二个数组的值复制给第一个
所需头文件:include <string.h>
案例:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[10] = "x";
char arr2[10] = "abcde";
strcpy(arr1,arr2);//把括号里面第二个值复制给第一个
printf("%s",arr1);
return 0;
}
这里面的复制是直接覆盖,此时的arr1里面有无元素最后都是输出与arr2里一样的元素。
模拟strcpy:
void My_strcpy(char* arr1, char* arr2)//这里的arr1和下面的arr1是反的
{
char* p1 = arr1;//此时arr1是空
char* p2 = arr2;//arr2是有元素
while (*p1 != '\0')
{
*p1 = *p2;
p2++;
p1++;
}
int sz = My_strlen(arr1);//这里直接调用了之前写的My_strlen来求长度
for (int i = 0; i < sz; i++)
{
printf("%c", arr1[i]);
}
}
int main()
{
char arr1[] = "abcde";
char arr2[10] = { 0 };
My_strcpy(arr2, arr1);//这里注意是谁复制谁
return 0;
}
这里有点点绕,但是清楚谁复制谁的值就好了,在调用函数里面可以重新命名数组名以免混淆
3.strcmp函数:int strcmp ( const char * str1, const char * str2 )
这个函数是返回整数
用途:比较两个字符串大小
所需头文件:include <string.h>
这里注意一下:str1>str2返回1,str1=str2返回0,str1<str2返回-1.其中两个字符数组的比较方式是比较同位不同值的大小,比出来就不用在比后面
案例:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[20] = "abcdex";
char arr2[20] = "abcderzzzzz";
int sz = strcmp(arr1,arr2);
printf("%d",sz);//这里arr2看起来是大于arr1的,但是arr1的第6个元素大于arr2,所以返回1
return 0;
}
上图:
模拟strcmp:
#include <stdio.h>
#include <string.h>
int My_strcmp(char* arr1, char* arr2, int a, int b)
{
char* p1 = arr1;
char* p2 = arr2;
while (*p1 != '\0')
{
if (*p1 == *p2)
{
p1++;
p2++;
}
if (*p1 > *p2)//此时里面比较是ASCLL值
{
return 1;
break;
}
if (*p1 < *p2)
{
return -1;
break;
}
if (*p1 == *p2 && *p1 == arr1[a - 1])//这里的arr1[a-1]表示已经来到了arr1最后一项
{
if(a<b) //这里还有两种情况,arr1和arr2在a个元素前都一样,此时不确定arr2
return -1; //是否结束,若b>a,arr2没有结束,返回-1
else //照着这个逻辑还有一种情况a>b返回1,但是我却没写,其实如果b提前结束
return 0;//已经在本循环第二个if就返回了,其次剩a=b返回0的情况
break;
}
}
}
int main()
{
char arr1[] = "abcd";
char arr2[] = "abcdc";
int sz1 = strlen(arr1);//为了方便就直接用strlen求长度了
int sz2 = strlen(arr2);
int num = My_strcmp(arr1, arr2, sz1, sz2);
printf("%d", num);
return 0;
}
可以输入多组用例测试
4.strcat函数:char * strcat ( char * destination, const char * source )
用途:用来追加字符串
所需头文件:include <string.h>
案例:
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[100] = "abcdx";
char arr2[100] = "abcdaaaa";
strcat(arr1,arr2);
printf("%s", arr1);//输出abcdxabcdaaaa
return 0;
}
模拟strcat:
#include <stdio.h>
#include <string.h>
void My_strcat(char* arr1, char* arr2, int a, int b)
{
char* p1 = arr1;
char* p2 = arr2;
int i = 0;
for (i = a; i < a + b; i++)
{
arr1[i] = *p2;//直接在arr1后面把arr2加上
p2++;
}
for (int i = 0; i < a + b; i++)
{
printf("%c", arr1[i]);
}
}
int main()
{
char arr1[10] = "abce";
// 首先arr1要有足够的空间,如果没有的话,创建一个新数组,一次拷贝arr1,arr2
char arr2[10] = "cv";
int sz1 = strlen(arr1);
int sz2 = strlen(arr2);
My_strcat(arr1, arr2, sz1, sz2);
return 0;
}
5.strstr函数:
const char * strstr ( const char * str1, const char * str2 ); char * strstr ( char * str1, const char * str2 );
用途:不太好描述,举例arr1[] = "acavefgavavag", arr2[]=''vef" ,其中arr2与arr1中间元素一样,那么就输出arr1的这段元素以及之后的,看看案例就知道了。
所需头文件:include <string.h>
案例
#include <stdio.h>
#include <string.h>
int main()
{
char* p1 = "abcefgheg";
char* p2 = "cef";
char* p3 = strstr(p1,p2);
printf("%s",p3);
return 0;
}
结果:
模拟strstr:这个是我按照自己的逻辑写的,还没有优化
void My_strstr(char* a, char* b, int sz, int sum)
{
char* p1 = a;
char* p2 = b;
//定义这么多指针后面有用处
char* p5 = b;
char* p6 = a;
int num = 1;
while (*p1 != '\0')
{
if (*p1 != *p2)
//开始直接判断两个数组元素不相等的情况,为什么不从相等开始判断,因为我试过了要不得0.0
{
p1++;//不相等时a的指针开始后走,b不变
p6++;//这个先不用管,后面解释
}
else//两个数组相等的情况
{
char* p3 = p1;
char* p4 = p2;
//这一步时遍历a,b数组,看看是否b的整体都在a内,这时候为了不改变p1,p2重新定义指针
for (int i = 0; i < sz; i++)//sz时a数组的长度
{
p3++;
p4++;
if (*p3 == '\0')
//这是结束标志,为啥要整个这个,因为把p1的地址赋给p3时,p1可能已经++过了
//可能已经不是首地址了,不需要循环sz次
break;
if (*p3 != *p4)
break;
//如果此时两个数组内的元素又不相等了就直接跳出
else
num++;//记录a,b字符串有多少个相等
}
p1++;//保证循环一直运动的条件
}
if (*p1 == '\0' && num != sum)//sum是b的长度,sum和num不相等,说明要不得
printf("NULL");
if (num == sum)//这种就是要得的情况,可以开始输出了
{
while (*p5 != '\0')//*p5是b的首地址,先把b内的元素给打印出来
{
printf("%c", *p5);
p5++;
p6++;
}
while (*p6 != '\0')
{
printf("%c", *p6);
p6++;
//还要打印a内的元素,p1已经是\0不能用了,p3用来测试也不能拿来用,所以定义p6
//并且p6必须对应走完b内元素的地址,所以一开始p6就要和p1一块走到与p2相同之前
//然后再把b内元素走了,就可以打印后面的了
}
}
}
}
int main()
{
char* s = "vacokdgjksdk";
char* x = "acb";
//首先这是会返回空指针的
int sum = strlen(x);
int sz = strlen(s);
My_strstr(s, x, sz, sum);
}
这个是精简版(标志答案):
#include <stdio.h>
#include <string.h>
char * my_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 ( *s1 && *s2 && !(*s1-*s2) )
s1++, s2++;
if (!*s2)
return(cp);
cp++;
}
return(NULL);
}
int main()
{
char* str1 = "abceafgheg";
char* str2 = "cef";
char* p2 = my_strstr(str1,str2);
printf("%s",p2);
return 0;
}
这段代码后面再给注释,写几个测试用例调试一下看看代码是什么意思