本篇文章重点:
重点介绍处理字符和字符串的库函数的使用和注意事项
求字符串长度
strlen
长度不受限制的字符串函数
strcpy
strcat
strcmp
长度受限制的字符串函数介绍
strncpy
strncat
strncmp
字符串查找
strstr
strtok
错误信息报告
strerror
前言
C语言中对字符和字符串的处理很是频繁,但是C语言本身是没有字符串类型的,字符串通常放在常量字符串中 或者 字符数组中。 字符串常量适用于那些对他它不做修改的字符串函数。
函数介绍
strlen
模拟strlen函数:
#include<stdio.h>
#include<assert.h>
int my_strlen(const char *str)//加入const是函数更健壮
{
int count=0;//计数器
assert(str!=NULL);//字符串数组进来要被解引用,所以要断言是否为空指针
while(*str!='\0')
{
count++;
str++;
}
return count;
}
int main()
{
char *arr[]="abc";
int len=my_strlen(arr);
printf("%s",arr);
return 0;
}
函数的返回类型为size_t(无符号整型)
eg:
输入的为>
(因为strlen返回的为无符号类型,无符号类型-无符号类型=无符号类型 只有正数所以输出>)
strcpy
返回类型为char* 参数都为char *,源数据不可修改,目标数据可修改
strca:字符串追加
把源字符串追加的目标字符串中
返回值为char*,为目标字符串
int main()
{char ar1[20]="hello ";//
char ar2[]="world";
strcat(ar1,ar2);//把world追加到hello 后面。
printf("%s\n",ar1);//输出hello world
return 0;}
从'\0'开始追加,覆盖'\0';
ar2中也要有'\0',并且ar1要有足够空间
eg:
追加的时候ar2也会把自己的'\0'追加过去
模拟函数:
#include<stdio.h>
#include<assert.h>
char* my_strcat(char *dest,const char*src)
{char *ret=dest;//先保存dest,返回值直接返回ret,因为函数结束后dest已经换了位置。
assert(dest && src)
//1.找到目标字符串中的\0
while(*dest)
{
dest++;
}
//跳出while此时dest指向\0
//2.追加源字符串
while(*dest++==*src++)//当都等于\0是停止循环
{
;
}
}return ret;//返回目标空间的起始位置
int main()
{
char ar1[20]="hello ";
char ar2[]="world"
printf("%s",my_strcat(char *dest,const char*src));
return 0;
}
找到目标字符串中的\0
源数据追加过去,包含\0
strcat不能追加自己(\0被覆盖了进入死循环)
解析:
开始将自身的a追加覆盖在'\0'上然后再依次追加后面的元素,追加完d后,追加的str数组知道不到结束字符'\0',所以就会继续追加,a再往后覆盖,后面的元素依次往后覆盖。因此,最终进入一个死循环
找不带\0所以一直重复着覆盖
strcmp//字符串比较函数
返回值为整型,两个参数都不能被改变所以加const1
比较时时第一个字符串的第一个元素和第二个字符串的第一个元素比较,如果相等则再比较两个字符串的第二个元素eg:
ar1:"acc" ar2:"abb",(第一个元素都相等第二元素中数组一c大于数组2b所以返回值为大于0的数)
函数比较简单我们直接看模拟函数
#include<stdio.h>
int my_strcmp(const char*ar1, const char*ar2)
{
assert(ar1 && ar2)
while(*ar1==*ar2)
{
if(ar1=='\0') //当两个数都为'\0'时说明两个字符串比较到最后了结果全为相等所以直接返回零
{ return 0;}
ar1++;
ar2++;
}
return *ar1-*ar2;//直接返回两元素相减
}
int main()
{
char ar1[]="";
char ar2[]="";
printf("%d",my_strcmp(const char*ar1, const char*ar2));
return 0;
}
strcpy,strcat,strcmp(长度不受限制的字符串函数)
strncpy
第三个参数为要拷贝的字符个数
若n超过arr2的长度补'\0'
eg:拷贝过去qwer后,后两个补充为'\0'
strncat
追加num个字符
eg://只追加过去wor
//如果追加的个数小于arr字符元素的个数,追加完在末尾会自动放个'\0'
strncmp
比较的个数由最后一个参数num来控制
strstr:在一个字符串中找另一个字符串
若找到了则返回第一次找到的字符串加后面的字符元素,若没找到则返回NULL空指针
eg:
模拟实现strstr函数☆☆:
#include<stdio.h>
#include <assert.h>
char* my_strstr(const char*str1,const char* str2)
{
assert(str1 && str2);
const char *s1=NULL;
const char *s2=NULL;
char *cp=str1;//当s1与s2相等的时候s1s2都会加加,但为了防止情况二的发生,
//需要定义cp来保留s1s2最初相等时s1的位置
while(*cp)
{
s1=str1;
s2=str2;
if(*str2=='\0')//str2一进来就是NULL
{return char* str1;}
while(*s1 && *s2&&(*s1==*s2))//当s1s2为\0时则不再进行循环
{
s1++;
s2++;
}
if(*s2=='\0')//意思为我找到了
{
return (char*)cp;
}
cp++;
}
return NULL;//最后找完了都没有找到则返回NULL
}
int main()
{
return 0;
}
//分析:
情况一:
开始一个指针指向s1,另一个指针指向s2。s1往后移直到知道到数组2的首元素,然后s1,s2依次往后比较如果s1后面的元素都等于s2的元素则代表在s1中找到了s2
情况二
//起初s1的第一个b与s2的第一个b相等然后s1s2依次++,但加dao第二次时s1为b s2为c不相等,因此要重新比较,此时s1要回到上次比较的下一个位置再进行重新比较(上次位置为1,因此下次比较s1要指向2,所以定义了cp来保留最初比较的位置,如果比较没通过,则cp++,s1来到下一个位置再进行比较)
strtok//切割字符串
参考代码:
#include<stio.h>
#include<string.h>
int main()
{
char arr[]="zpw@bitedu.tech";
char *p="@."//分隔符的集合,当从arr中遇到*p里面的字符时就会进行切割,分割符会被替换成'\0'
char tmp[20]={0};//strtok会改变字符串,所以临时定义一个字符串把要切割的拷贝过去,用来被切割
strcpy(tmp,arr);
char* ret=NULL;
//strtok每次切割只能切割依次分割符,
第一次切割的时候第一次参数为要切割函数,以后每次切割第一个参数都为NULL空指针
for(ret=strtok(tmp,p);ret!=NULL;ret=strtok(NULL,p))//strtok要进行多次切割,所以配合for循环更简洁方便.ret为存放的标记,若ret=NULL则终止循环
{
printf("%s\n",ret);
}
return 0;
}
//strtok会从上次切割的下一个位置开始,随意strtok具有记忆功能。
不能用\0来当作分隔符
strerror
在使用库函数的时候,在调用库函数失败的时候都会设置错误码
会把错误码存放到 int errnum
strerror会把错误码翻译成信息(具体数字对应的信息已经翻译好)
//strerror返回的是错误信息(字符串)的首元素地址。
若代码错误可直接把errno(全局错误码,头文件<errno.h>)传给strerror
字符函数笔记已经讲解完,如果有什么不对的地方或者疑问,可以给博主发私信或者评论博主会第一时间回复并进行改正,您的观点很重要!
perror:打印错误信息(一步完事)
头文件:<stdio.h>
eg:
perror("自定义字符串"):打印的时候先打印自定义字符串,再打印‘:’+‘ ’再打印错误信息。
字符分类函数:用来判断字符
<ctype.h>
返回值:如果符合自己判断的条件返回非0,如果不符合返回0
字符串换函数:
int toupper(int c)
int tolower(int c)
eg:
//输入一串字符串先判断是否为大写,若为大写则转换为小写,再打印出字符串。