目录
一、求字符串长度
1.1 strlen函数
用法:该函数主要用来求字符串的长度(不含\0),引用头文件为<string.h>
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="abcd";
int ret=strlen(c);
printf("%d ",ret);
printf("\n");
return 0;
}
输出结果为:4
1.1.1 strlen实现
由此可知,我们遇到\0停止,我们在看看C语言是何如定义这个标准的。
这里用const的原因是更加安全可以保证不被修改,因为我们只需要长度。
#include<stdio.h>
size_t my_strlen(const char* str1)
{
int count=0;
while(*str1++!='\0')
count++;
return count;
}
int main()
{
char str1[]="work hard";
int ret=my_strlen(str1);
printf("%d\n",ret);
return 0;
}
二、长度不受限制的字符串函数
2.1 strcpy函数
用法:该函数可以把源字符串拷贝到目的地,并且会在目标字符串自动追加\0,引用头文件为<string.h>
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="workhard";
char str2[]="xxxx";
strcpy(str1,str2);
printf("%s",str1);
printf("\n");
return 0;
}
输出结果为:xxxx
我们通过调试可以更清楚的看到:
2.1.1 strcpy实现
由此可知,这里是把源字符串拷贝过去后,再加上\0,C语言是这样定义标准的:
这里我们的源字符串定义为const是保证源字符串不被修改。
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
//防止遇到空字符串
assert(dest && src);
char* tmp = dest;
while((*dest++=*src++)!='\0')
;
return tmp;
}
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "123";
char*p=my_strcpy(arr1,arr2);
printf("%s\n", p);
return 0;
}
2.2 strcat函数
用法:在字符串末尾追加字符串,引用头文件<string.h>
#include<stdio.h>
#include<string.h>
int main()
{
//这里记得给大小!要超出追加后的长度
char str1[30]="workhard";
char str2[]="xxxx";
strcat(str1,str2);
printf("%s",str1);
printf("\n");
return 0;
}
输出结果为:workhardxxxx
2.2.1 strcat实现
由此可知,我们是在目标字符串的末尾继续追加,那么我们首先就要找到目标字符串的的末尾,即\0,C语言是这样规定的:
用const修饰源字符串是为了保证不被修改。
#include<stdio.h>
#include<assert.h>
char* my_strcpy(char* dest, const char* src)
{
//避免为字符串为空
assert(dest && src);
char* tmp = dest;
while((*dest++=*src++)!='\0')
;
return tmp;
}
int main()
{
char arr1[10] = "abcdef";
char arr2[] = "123";
char*p=my_strcpy(arr1,arr2);
printf("%s\n", p);
return 0;
}
2.3 strcmp函数
用法:比较字符串的大小,如果大于返回>0的数,等于返回0,小于返回<0的数。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="work hard";
char str2[]="ab";
int ret=strcmp(str1,str2);
printf("%d",ret);
printf("\n");
return 0;
}
输出结果为:22(此结果依照不同编译器生成不同的结果,但是一定是>0的数字)
2.3.1 strcmp实现
由此可知,我们是选取字符串中每一个字符进行比较,C语言是这样定义的:
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* str1, const char* str2)
{
assert(str1&&str2);
while(*str1==*str2)
{
if(*str1=='\0')
{
return 0;
}
str1++;
str2++;
}
//直接返回大小,要么是0,要么是负数,要么大于0
return *str1-*str2;
}
int main()
{
char str1[] = "abcdef";
char str2[] = "abcg";
int ret=my_strcmp(arr1,arr2);
printf("%d\n", ret);
return 0;
}
三、长度受限制的字符串函数
3.1 strncpy函数
用法:和strcpy函数一样,但是可以加上想要复制的个数。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="work hard";
char str2[]="ab";
strncpy(str1,str2,2);
printf("%s",str1);
printf("\n");
return 0;
}
输出结果为:abrk hard
tips:该字符串可以用来拷贝自己,但是strcpy不可以!
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="work hard";
strncpy(str1,str1+5,4);
printf("%s",str1);
printf("\n");
return 0;
}
输出结果为:hard hard
3.2 strncat函数
用法:和strcmp函数一样,不过可以选择比较的个数。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[20]="workhard";
char str2[]="hard";
strncat(str1,str2,3);
printf("%s",str1);
printf("\n");
return 0;
}
输出结果为:workhardhar
3.3 strncmp函数
用法:和strcmp函数一样,不过可以选择比较的个数。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[20]="workhard";
char str2[]="ward";
int ret=strncmp(str1,str2,1);
printf("%d ",ret);
printf("\n");
return 0;
}
输出结果为:0
四、字符串查找
4.1 strstr函数
用法:寻找匹配的字符串,返回找到的第一个地址。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[20]="workhard";
char str2[]="har";
char* ret=strstr(str1,str2);
printf("%s",ret);
printf("\n");
return 0;
}
输出结果为:hard
4.1.1 strstr实现
这里我们采用bf方法,因为这个是偏向入入门的教程,想了解kmp方法请看我之前的博客。
【超详细】kmp算法,直击本质_努力敲代码的小王的博客-优快云博客
我们先来看看C语言是如何规定这个函数的:
#include<stdio.h>
#include<string.h>
char* my_strstr(const char* str1,const char* str2)
{
const char* s1=str1;
const char* s2=str2;
const char* p=str1;
while(*p)
{
//不想等的时候p会往下走,当*s1=*s2时,p会记录第一个想等的位置
s1=p;
s2=str2;
//如果相等就一直往下走
while(*s1!='\0'&&*s2!='\0'&&*s1==*s2)
{
s1++;
s2++;
}
if(*s2=='\0')
{
return (char*)p;
}
p++;
}
return NULL;
}
int main()
{
char str1[20]="workhard";
char str2[]="har";
char* ret=my_strstr(str1,str2);
printf("%s",ret);
printf("\n");
return 0;
}
4.2 strtok函数
用法:可以分割字符串,该用法比较难以解释,直接看例子会比较好。
#include<stdio.h>
#include<string.h>
int main()
{
char str1[]="xiaowang@163.com";
char str2[]="@.";
//strtok函数的第一个参数不为NULL
char* ret=strtok(str1,str2);
printf("%s",ret);
printf("\n");
//strtok函数中有静态变量会保存下一个位置,所以这次用NULL指针
ret=strtok(NULL,str2);
printf("%s",ret);
printf("\n");
ret=strtok(NULL,str2);
printf("%s",ret);
printf("\n");
return 0;
}
输出结果为:xiaowang
163
com
五、错误信息报告
5.1 strerror函数
用法:可以报告错误,需要结合printf来打印错误信息。
#include<stdio.h>
#include<string.h>
//必须包含的头文件
#include<errno.h>
int main()
{
FILE* pfile;
pfile=fopen("abc.txt","r");
if(pfile==NULL)
{
printf("%s",strerror(errno));
}
return 0;
}
输出结果为:No such file or directory
5.2 perror函数
用法:相当于printf+strerror
#include<stdio.h>
#include<string.h>
//必须包含的头文件
#include<errno.h>
int main()
{
FILE* pfile;
pfile=fopen("abc.txt","r");
if(pfile==NULL)
{
perror("error");
//printf("%s",strerror(errno));
}
return 0;
}
输出结果为:error:No such file or directory
六、内存操作函数
6.1 memcpy函数
用法:其实就是strncpy函数,只不过它可以接受任意类型,不限于char类型。
我们可以从C语言定义的标准中看出来:
这里是void*类型,void*类型可以接受任意类型。
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[]={1,2,3,4,5};
int arr2[]={6,7,8,9,10};
memcpy(arr1,arr2,8);
int i=0;
for(i=0;i<5;i++)
{
printf("%d ",arr1[i]);
}
}
输出结果为:6,7,3,4,5,1
6.1.1 memcpy实现
要实现这个函数并不难,我们首先要知道一个概念,char*类型一次走一个字节!!!学会指针这个应该不难理解,所以我们需要把void*类型强制转化问char*类型,保证了不管什么类型传过来,我们都走一个字节。
#include<stdio.h>
#include<string.h>
void* my_memcpy(void* dest,const void* src,size_t num)
{
void* ret=dest;
//如果目标地址在后面,src需要从后向前赋值
if(dest>src)
{
while(num--)
{
*((char*)dest+num)= *((char*)src+num);
}
}
//如果目标地址在前面,或者不重叠,src从前向后赋值
else
{
while(num--)
{
*(char*)dest=*(char*)src;
dest=(char*)dest+1;
src=(char*)src+1;
}
}
return ret;
}
int main()
{
int arr1[]={1,2,3,4,5,6};
int arr2[10]={0};
my_memcpy(arr1+2,arr1,12);
int i=0;
for(i=0;i<6;i++)
printf("%d ",arr1[i]);
printf("\n");
return 0;
}
6.2 memmove函数
用法:memcpy函数有一个缺点,就是不能自己复制自己,但是memmove函数可以,不过我们用的编译器把memmove函数干的事情也集成到了memcpy函数中,这里只说用法,实现就是memcpy函数。
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[]={1,2,3,4,5,6,8};
int arr2[]={6,7,8,9,10};
memmove(arr1,arr1+2,16);
int i=0;
for(i=0;i<7;i++)
{
printf("%d ",arr1[i]);
}
}
输出结果为:3 4 5 6 5 6 8
6.3 memcmp函数
用法:用法和strncmp函数一样,不过它可以接受任意类型!
#include<stdio.h>
#include<string.h>
int main()
{
int arr1[]={1,2,3,4,5,6,8};
int arr2[]={1,2,8,9,10};
int ret=memcmp(arr1,arr2,8);
printf("%d ",ret);
}
输出结果为:0
到这里就介绍完了,有些函数的实现没有写,是因为整体做法差不多,我只列举了比较难实现的一些函数,如果错误希望指正!