前言:
C语言的标准库中有许多字符函数与字符串函数,其存在能够大大减轻许多编程压力,因此,充分了解并能够熟练运用字符函数与字符串函数是很有必要的,在本文中,我们将对于其进行深入了解
正文开始:
一.字符分类函数:
C语言中有一类函数专门用于字符分类,使用时需要包含一个头文件<ctype.h>
函数参数符合条件就返回真(非0)
具体函数如下:
1.iscntrl—任何控制字符
2.isspace—空白字符
3.isdigit—十进制数字
4.isxdigit—十六进制数字
5.islower—小写字母a-z
6.isupper—大写字母A-Z
7.isalpha—字母a-z或者A-Z
8.isalnum—字母或者数字
9.ispunct—标点符号,非任意字母(图形)或者数字
10.isgraph—任何图形字符
11.isprint—任何可打印字符,包括图形与空白字符
示例:
1.
#include<ctype.h>intmain(){intr=isdigit('a');//r=0;printf("%d\n",r);if(r){printf("是十进制字符\n");}else{printf("不是十进制字符\n");}return0;}输出结果为:
不是十进制字符intmain(){intr=islower('a');//r=2;printf("%d\n",r);if(r){printf("是小写字符\n");}else{printf("不是小写字符\n");}return0;}输出结果为:
是小写字符intmain(){//小写字符转大写chararr[]="I am a Chinese";inti=0;for(i=0;arr[i]!='\0';i++){intr=islower(arr[i]);if(r){arr[i]-=32;//'a'-'A'=32}printf("%c",arr[i]);}return0;}输出结果为:
I AM A CHINESE二.字符转化函数
注:仅适用于字母
大写转小写:tolower
小写转大写:toupper
1次只能够转1个
示例:
intmain(){//小写字符转大写chararr[]="I am a Chinese";inti=0;for(i=0;arr[i]!='\0';i++){intr=islower(arr[i]);if(r){arr[i]=toupper(arr[i]);}printf("%c",arr[i]);}return0;}输出结果为:
I AM A CHINESE字符转换函数的模拟实现:
以toupper函数为例:
charmy_toupper(charx){if(x>='a'&&x<='z'){x-=32;}returnx;}intmain(){//小写字符转大写chararr[]="i am a chinese";inti=0;for(i=0;arr[i]!='\0';i++){intr=islower(arr[i]);if(r){arr[i]=my_toupper(arr[i]);}printf("%c",arr[i]);}return0;}该函数也能够行使字符转换功能
三.strlen函数
前面已讲,详情请看指针–习题练习
注:返回类型:size_t–无符号整型–必定大于等于0
示例:
intmain(){if((strlen("abc")-strlen("abcdef"))>0){printf(">\n");}else{printf("<=\n");}return0;}输出结果为
>证明返回数字大于0,即为无符号整型
strlen函数的另一种模拟实现(第一种在指针–习题练习):
size_tmy_strlen(constchar*str){if(*str!='\0'){return1+my_strlen(str+1);}else{return0;}}四:字符串函数
1.strcpy
功能:字符串拷贝,拷贝到字符串中的\0为止
参数:两字符串的首元素地址
注:1.以\0结束
2.\0也会被拷贝
3.目标空间必须足够大
4.目标空间必须可被修改(即arr2初始化时不能是常量字符串)
示例:
i
ntmain(){chararr1[]="Hello world!";chararr2[]={0};//arr2 = arr1;//错误!arr2代表地址,不可修改//数组名为地址,地址是一个编号,但地址是常量,无法修改char*ret=strcpy(arr2,arr1);printf("%s\n",arr2);printf("%s\n",ret);return0;}输出结果为:
Hello world!Hello world!strcpy函数的模拟实现:
两个条件:
1.能够将y代表数组的内容拷贝到x中
2.能够返回y数组的首元素地址
#include<assert.h>char*my_strcpy(char*x,constchar*y){//x---指针,指向目的空间 //y--指针,指向源头数据char*ret=x;assert(y&&x);//两者均不能为空指针while(*x++=*y++){;}returnret;}intmain(){chararr1[]="Hello world!";chararr2[20]="xxxxxxxxx";my_strcpy(arr2,arr1);printf("%s\n",arr2);return0;}2.strcat–字符串追加
char* strcat(charx,const chary)
x----指针,指向目的空间
y–指针,指向源头数据
返回目标空间起始地址
注:
1.源字符串(x)必须以\0结束
2.目标字符串中也应有\0(从\0开始追加)
3.目标字符串应足够大,能够容纳源字符串内容
4.目标字符串可修改
示例:
intmain(){chararr1[20]="hello \0xxxxxxxx";chararr2[]="world!";char*r=strcat(arr1,arr2);printf("%s\n",arr1);printf("%s\n",r);return0;}输出结果为:
hello world!strcat函数的模拟实现:
两个条件:
1.能够将y代表数组的内容追加到x中
2.能够返回x数组的首元素地址
#include<assert.h>char*my_strcat(char*x,char*y){assert(y&&x);//1.寻找\0char*r=x;while(*x!='\0'){x++;}while(*x++=*y++){;}returnr;}intmain(){chararr1[20]="hello \0xxxxxxxx";chararr2[]="world!";char*r=my_strcat(arr1,arr2);printf("%s\n",arr1);printf("%s\n",r);return0;}3.strcmp—字符串比较
主要内容前面已讲
功能:从两个字符串首字母开始比较ASCII码值,若相同则比较下一字母
参数:char* a,char* b
返回值:a>b 返回t>0 a<b 返回t<0
示例:
intmain(){chararr1[]="abcdef";chararr2[]="abq";intr=strcmp(arr1,arr2);printf("%d\n",r);if(r<0){printf("arr1<arr2\n");}return0;}输出结果为:
arr1<arr2strcmp函数的模拟实现:
intmy_strcmp(constchar*a,constchar*b){assert(a&&b);while(*a==*b){if(*a=='\0'){return0;//相等}a++;b++;}if(*a>*b){return1;}else{return-1;}}intmain(){chararr1[]="abcdef";chararr2[]="abq";intr=my_strcmp(arr1,arr2);printf("%d\n",r);if(r<0){printf("arr1<arr2\n");}return0;}输出结果一致!
另外:
介绍三个类似函数:
strncpy—strcpy
strncat—strcat
strncmp—strcmp
长度受限—长度不受限
前者相较于后者多出一个参数:size_t num,意义为限制拷贝的字符个数
主要优点:后者相较于前者更加灵活安全
示例:
intmain(){chararr1[]="abcdefg";//遇到\0提前结束chararr2[]="xxxxxxxxxxxx";//strncpy(arr2, arr1, 5);//最多拷贝5个字符//printf("%s", arr2);//strncat(arr2, arr1, 5);//最多追加5个字符//printf("%s", arr2);intr=strncmp(arr2,arr1,5);//最多比较5个字符printf("%s\n",arr2);printf("%d",r);//1---a>breturn0;}其余内容重复,不再讲解
4.strstr函数
功能:在一个字符串中寻找另一个字符串第一次出现位置
结果:找到:返回出现位置指针,找不到:返回NULL
示例:
intmain(){chararr1[]="heheabcdefgh";chararr2[]="def";char*p=strstr(arr1,arr2);if(p!=NULL){printf("找到了,%s\n",p);//打印找到位置后的字符串}else{printf("未找到\n");}return0;}strstr函数的模拟实现
两种:
1.
char*my_strstr(constchar*a,constchar*b){char*p1=a;while(*p1!=*b){p1++;}size_tlen=0;char*p2=b;while(*b!='\0'){b++;len++;}if(strncmp(p1,p2,len)==0){if(*p1!='\0'){returnp1;}else{returnNULL;}}else{returnmy_strstr(p1+1,b);}}自己写的
char*my_strstr(constchar*a,constchar*b){char*p=a;char*s1=NULL;char*s2=NULL;//特殊场景:if(*p=='\0'){returna;}while(*p){s1=p;s2=b;while(*s1&&*s2&&*s1==*s2){s1++;s2++;}if(*s2=='\0'){returnp;}p++;}returnNULL;}老师教的:暴力查找
其他方式:KMP
5.strtok函数
char * strtok(char * x,char * y)
功能:1.分割字符串;//根据y中的符号//调用一次分割一次
2.修改原始字符串,分割符号被修改为\0
3.返回首元素地址
示例:
intmain(){chararr[]="zpw@yeah.net";charsep[]="@.";charbuf[20]={0};strcpy(buf,arr);char*p=NULL;//1.for(p=strtok(buf,sep);p!=NULL;p=strtok(NULL,sep)){printf("%s\n",p);}//2.//char* p = strtok(buf, sep);//printf("%s\n", p);//zpw//p = strtok(NULL, sep);//yeah//printf("%s\n", p);//p = strtok(NULL, sep);//net//printf("%s\n", p);//p = strtok(NULL, sep);//NULL//printf("%s\n", p);return0;}6.strerror函数:
char*strerror(int errnum);
需要包含头文件<string.h>
C语言库函数在使用发生错误时会将一个错误码记录到errno的变量中
功能:
1.可以通过参数部分的errnum表示错误码,得到对应的错误信息,并返回错误信息字符串首字符地址
2.strerror函数只针对标准库中函数方式错误后设置错误码的转换
参数:errnum
示例:
intmain(){inti=0;for(i=0;i<10;i++){printf("%d:%s\n",i,strerror(i));}//strerror函数将错误码转化为错误信息return0;}转换形式:
0 : No error :无错误
1 : Operation not permitted:错误被拒绝
2 : No such file or directory :无该文件或文件夹
3 : No such process :没有进程
4 : Interrupted function call :函数调用被中断
5 : Input / output error :输入/输出错误
6 : No such device or address :无该设备或地址
7 : Arg list too long ……
8 : Exec format error
9 : Bad file descriptor
后面不再赘述
我们来看一个例子:
C语言可打开文件
该过程称为fopen
若以读的方式打开,则文件必须存在,若不存在,打开失败
open函数会将错误码放在errno中
同时函数返回NULL
如下:
intmain(){FILE*pf=fopen("data.txt","r");if(pf==NULL){printf("错误码为:\n%s\n",strerror(errno));printf("该文件不存在,打开失败\n");return1;}//读文件://………………//关闭文件:fclose(pf);pf=NULL;return0;}7.perror函数:
void perror(char*str);
功能:记录错误码+打印错误信息 一体化
perror(xxx) -->xxx:错误信息
缺点:不够灵活
优点:足够方便
具体功能前面已经分开介绍,故不再赘述
后记:
通过以上示例,我们对于字符与字符串函数有了一个较为系统的认识,通过不断进行练习,熟悉度也会提高,下一节我们将认识另一种新的C语言函数:内存函数。那么,本节内容到此结束,我们下节再见!