这篇文章和大家分享一下字符函数和字符串函数。
在C语言中有一系列函数专门做字符分类的,也就是一个字符是属于什么类型的字符,这些字符都需要一个头文件 ctype.h。
函数 | 它的参数符合下列条件就返回真 |
|---|---|
iscntrl | 任何控制符 |
isspace | 空白字符:空格' ',换页'\f',换行'\n',回车'\r',制表符'\t'或者垂直制表符'\v' |
isdigit | 十进制0-9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a-f,大写字母A-F |
islower | 小写字母a-f |
isupper | 大写字母A-F |
islpha | 字母a-z或A-Z |
isalnum | 字母或者数字,0-9,a-z,A-Z |
ispunct | 标点符号,任何属于数字或者字母的图形字符 |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
这些函数的使用方法非常相似,这里我们以其中一个函数的讲解为例:
int islower(int c);islower是可以判断参数部分c是否是小写字母。我们可以通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,就返回0。
上实战:写一个代码将字符串中的小写字母换成大写字母,其他的不变。
#include<stdio.h>
#include<ctype.h>
int main()
{
int i=0;
char arr[]="Asdfghjkl";
char c;
while(arr[i])
{
c=arr[i];
if(islower(c))
c-=32;
putchar(c);
i++;
}
return 0;
}
c语言提供了两个字符转换函数分别是:
int tolower(int c);//将参数里面的大写字母转换成小写字母
int toupper(int c);//将参数里面的小写字母转换成大写字母上面的代码,我们将小写转换成大写,是-32完成的效果,有了转换函数,我们就可以使用toupper来实现这种效果。
#include<stdio.h>
#include<ctype.h>
int main()
{
int i=0;
char arr[]="asdfghjkl";
char c;
while(arr[i])
{
c=arr[i];
if(islower(c))
c=toupper(c);
putchar(c);
i++;
}
return 0;
}
size_t strlen(const char * str);字符串以'\0'作为结尾标识,strlen函数返回的是字符串中'\0'之前出现的字符个数(不包含\0),参数指向的字符串必须要以’\0‘作为结尾标识,注意函数的返回值是size_t,是无符号的,下面是strlen的模拟实现(仿照strlen函数的参数,返回类型,功能写一个相似的函数):
方式1:
//计算器方式
int my_strlen(const char* str)
{
int count=0;
assert(str);
while(*str)
{
count++;
str++;
}
return count;
}方式2:
//不创建临时变量计算器
int my_strlen(const *char)
{
assert(*str);
if(*str==''\0)
return 0;
else
return 1+my_strlen(str+1);
}方法3:
//指针-指针形式
int my_strlen
{
assert(str);
char *p=s;
while(*p!='\0')
p++;
return p-s;
}char *strcpy(char *destination,const char *source);我们看一下C++官网对strcpy的介绍:

strcpy函数的功能:拷贝字符串。
注意事项:1. 源字符串中必须包含'\0',同时'\0'也会被拷贝到目标空间。
2.必须要保证目标空间足够大,能放得下拷贝来的数据。
3.保证目标空间可修改
模拟实现strcpy函数:
#include<stdio.h>
void my_strcpy(char *dest,char *src)
{
while(*src!='\0')
{
*dest=*src;
dest++;
src++;
}
*dest=*src;
}
int main()
{
char arr1[]="qwertyuiop";
char arr2[20]={0};
my_strcpy(arr2,arr1);
printf("%s\n",arr2);
return 0;
}
char *strcat (char *destination,const char *source);我们看一下C++官网对strcat函数的介绍:

由于C++官网是英文环境,将页面翻译成中文,strcat被翻译成了斯特卡特。
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[20]="hello";
char arr2[30]="world";
strcat(arr1,arr2);
printf("%s\n",arr1);
return 0;
}
strcat函数的功能:字符串追加。
注意事项:1. 目标空间中要有\0(从哪里开始追加),源字符串中也要有\0(追加到哪里结束)。
2.目标空间足够大,目标可以修改。
模拟实现strcat函数:
#include<stdio.h>
#include<assert.h>
char* my_strcat(char* dest,const char* src)
{
char* ret=dest;
assert(dest&&src);
//找到目标空间中的\0
while(*dest!='\0')
{
dest++;
}
//拷贝数据
while(*dest++=*src++)
{
;//这是空语句
}
return ret;
}
int main()
{
char arr1[30]="hello";
char arr2[30]="world";
printf("%s\n",my_strcat(arr1,arr2));
return 0;
}
int strcmp(const char* str1,const char* str2);我们看一下C++官网对strcmp函数的介绍:

#include<stdio.h>
#include<string.h>
int main()
{
int ret=strcmp("asd","asdf");//比较两个字符串
printf("%d\n",ret);
return 0;
}
strcmp函数的功能:比较两个字符串
strcmp函数规定标准:1.第⼀个字符串大于第⼆个字符串,则返回大于0的数字
2. 第⼀个字符串等于第⼆个字符串,则返回0
3.第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字
strcmp函数是怎么判断两个字符串的,它比较的是两个字符串中对应位置上的ASC||码值的大小。
模拟实现strcmp函数:
#include<stdio.h>
#include<assert.h>
int my_strcmp(const char* s1,const char* s2)
{
assert(s1!=NULL);
assert(s2!=NULL);
while(*s1==*s2)
{
if(s1=='\0')
return 0;
s1++;
s2++;
}
return *s1-*s2;
}
int main()
{
int ret=my_strcmp("asdf","asd");
printf("%d\n",ret);
return 0;
}
char* strcmpy(char* destination,const char* source,size_t num);我们来看一下C++官网对strncpy的介绍:

通过对strncpy函数的介绍,我们可以发现它和strcpy函数的功能相似,而且写法还很相似,strncpy函数需要三个参数,而strcpy函数是两个参数,size_t num 表示的是拷贝字符串时拷贝字符串的个数(下面的strncat函数和strncmp函数中的size_t num和这里的意义相同),下面我们通过代码及其运行结果来更深入的了解strncpy函数:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[30]="xxxxxxxxxx";
char arr2[]="abcdef";
strncpy(arr1,arr2,3);
printf("%s\n",arr1);
return 0;
}
那如果size_t num比arr2[]中存放的字符串的字符个数还要多会怎么样呢?多出来的部分会存放\0,那么我们一起通过下面的代码及其监视来了解吧:
#include<stdio.h>
#include<string.h>
int main()
{
char* arr1[30]="xxxxxxxxxx";
char* arr2[]="ab";
strncpy(arr1,arr2,5);
printf("%s\n",arr1);
return 0;
}
char* strncat(char* destination,const char* source,size_t num);我们看一下C++官网对strncat函数的介绍:

这里strncat函数被翻译成了斯特恩卡特(C++官网是英文环境,为了方便大家看懂进行了页面翻译),下面我们看一段代码及其运行结果来更深入的了解strncat函数:
#include<stdio.h>
#include<string.h>
int main()
{
char* arr1[30]="abc\0xxxxxxxx";//放\0的原因:追加时是在\0的位置开始追加字符
char* arr2[]="defghij";
strncat(arr1,arr2,5);
printf("%s\n",arr1);
return 0;
}
那如果size_t num 比arr2[]中存放的字符串个数还要多会怎么样呢?只会将arr2[]中的所有字符都追加(包括\0),我们看一下这段代码及其监视结果来了解这个知识点:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[30]="adc\0xxxxxxx";
char arr2[]="de";
strncat(arr1,arr2,5);
printf("%s\n",arr1);
return 0;
}
int strncmp(const char* str1,const char* str2,size_t num);我们看一下C++官网对strncpm函数的介绍:

这里size_t num的含义是:比较str1和str2的前num个字符,如果相等就继续往后比较,最多比较num个字母,如果提前发现不⼀ 样,就提前结束,⼤的字符所在的字符串大于另外⼀个。如果num个字符都相等,就是相等返回0,我们再看一下C++官网对strncmp函数返回值的描述:

我们通过下面这段代码来了解strncmp函数的知识点:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[30]="abcdefg";
char arr2[]="abcqwer";
int ret=strncmp(arr1,arr2,3);
printf("%d\n",ret);
return 0;
}
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[30]="abcdefg";
char arr2[]="abcqwer";
int ret=strncmp(arr1,arr2,4);
printf("%d\n",ret);
return 0;
}
char* strstr(const char* str1,const char* str2);我们看一下C++官网对strstr函数的介绍:

strstr函数的功能是:在一个字符串中找一个子字符串,返回str2在str1中第一次出现的位置,如果str2在str1中没有出现,就返回NULL。
我们通过下面这段代码来深入的理解这里的知识点:
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[]="abcdefabcdef";
char arr2[]="def";
char* ret=strstr(arr1,arr2);//arr1中出现了两次'def',返回的是第一次出现的位置('d'的位置)
printf("%s\n",ret);
return 0;
}
那么下面我们来模拟实现strstr函数:
#include<stdio.h>
#include<assert.h>
const char* my_strstr(const char* str1,const char* str2)
{
assert(str1);
assert(str2);
//cp记录可能找到匹配的字符串的起始位置
//s1遍历cp后面的字符串内容然后与s2(从str2首元素开始遍历的内容)进行比较
const char* cp=str1;
const char* s1=NULL;
const char* s2=NULL;
//如果字字符串是空字符串,直接返回str1
if(*str2=='\0')
return str1;
while(*cp)
{
s1=cp;
s2=str2;
//判断s1和s2是否相等,不相等的话直接跳出循环
while(*s1==*s2&&*s1&&*s2)
{
s1++;
s2++;
}
//判断s2是否等于\0,等于的话表示子字符串已经遍历结束,然后返回此时cp的位置
if(*s2=='\0')
return cp;
cp++;
}
return NULL;
}
int main()
{
char arr1[]="abbbcdef";
char arr2[]="bbc";
const char* ret=my_strstr(arr1,arr2);
if(ret!=NULL)
printf("%s\n",ret);
else
printf("找不到");
return 0;
}
这种方式是一种暴力求解方式,还有一种更好的方式:KMP算法,它的效率高,但是难度大,难以理解,这里就不和大家分享KMP算法了,感兴趣的可以去搜索一下。
char* strtok(char* str,const char* delimiters);我们看一下C++官网对strtok函数的介绍:

strtok函数和strcat函数一样页面翻译被翻译成了中文(斯特托克就是strtok函数),delimiters参数指向一个字符串,定义了⽤作分隔符的字符集合,第⼀个参数指定⼀个字符串,它包含了0个或者多个由delimiters字符串中⼀个或者多个分隔符分割的标记。strtok函数找到str中的下⼀个标记,并将其用\0 结尾,返回⼀个指向这个标记的指针。(注: strtok函数会改变被操作的字符串,所以在使⽤strtok函数切分的字符串⼀般都是临时拷贝的内容并且可修改。)strtok函数的第⼀个参数不为 NULL ,函数将找到str中第⼀个标记,strtok函数将保存它在字符串中的位置。strtok函数的第⼀个参数为 NULL ,函数将在同⼀个字符串中被保存的位置开始,查找下⼀个标记。如果字符串中不存在更多的标记,则返回 NULL 指针。那么我们通过下面这段代码来了解这些知识点吧:
#include<stdio.h>
#include<string.h>
int main()
{
char arr[]="3224349147@qq.com";//这里就以我的QQ邮箱为例子,这里的'@'和'.'就是分割符
const char* p="@.";
char* r=NULL;
for(r=strtok(arr,p);r!=NULL;r=strtok(NULL,p))
{
printf("%s\n",r);
}
return 0;
}
本篇博客就分享到这里了,大家有问题可以评论出来。