在编程的过程中,我们经常会遇到需要处理字符和字符串的情况,为了方便操作字符和字符串,C语言标准库中提供了一系列库函数,接下来我们就学习一下这些函数。
目录
1. 字符分类函数
2. 字母转换函数
3. strlen函数的使用和模拟实现
4. strcpy函数的使用和模拟实现
5. strcat函数的使用和模拟实现
1. 字符分类函数
C语言中有一系列的函数是专门做字符分类的,也就是⼀个字符是属于什么类型的字符的。 这些函数的使用都需要包含一个头文件是<ctype.h>
一共有下面这些函数,当这些函数处理的字符满足条件时返回值就为真:
iscntrl:任何控制字符
isspace:空白字符:空格' ',换页符'\f',换行符'\n',回车'\r',制表符'\t'或者垂直制表符'\v'
isdigit:十进制字符'0'~'9'
isxdigit:十六进制字符:包括十进制所有字符,小写字母a ~ f,大写字母A~F
islower:小写字母a~z
isupper:大写字母A~Z
isalpha:字母a~z或A~Z
isalnum:字母或数字,a~z,A~Z,0~9
ispunct:标点字符,任何不属于数字或者字母的(可打印)字符
isgraph:任何图形字符
isprint:任何可打印字符,包括图形字符和空白字符
这些函数的使用方法非常相似,我们就只列举一个函数的使用方法:
int islower(int c);
通过返回值来说明是否是小写字母,如果是小写字母就返回非0的整数,如果不是小写字母,则返回0。
例如:将字符串中的小写字母转换为大写字母
#include <ctype.h>
#include <stdio.h>
int main()
{int i = 0;char s[] = "Hello World";while(s[i]){if(islower(s[i]))s[i] -= 32;i++;}printf("%s\n",s);return 0;
}
HELLO WORLD
当返回值为非0值时,将字符的数值减去32,将小写字母转换为对应的大写字母,最后将修改后的字符串打印出来,查看结果是否符合预期。
2. 字母转换函数
C语言提供了2个字符转换函数:
int tolower ( int c ); //将参数传进去的⼤写字⺟转⼩写
int toupper ( int c ); //将参数传进去的⼩写字⺟转⼤写
上面的代码中,我们是利用islower函数来判断字符是否为小写字母,若是,则让其减去32,实现小写字母转化为大写字母的效果。而现在,我们可以直接使用toupper函数将小写字母转化为大写字母,例如:
#include <ctype.h>
#include <stdio.h>
int main()
{int i = 0;char s[] = "Hello World";while(s[i]){if(islower(s[i]))s[i] = toupper(s[i]);i++;}printf("%s\n",s);return 0;
}
3. strlen函数的使用和模拟实现
strlen函数原型为:
size_t strlen ( const char * str );
字符串以字符'\0'为结束标志,strlenm函数返回的值是字符串中字符'\0'前的字符个数(不包括'\0')
参数指向的字符串必须要以'\0'结束
注意函数的返回值类型为size_t,是无符号的
strlen的使用需要包含头文件<string.h>
#include <string.h>
#include <stdio.h>
int main()
{char s[] = "Hello World";printf("%d\n", strlen(s));return 0;
}
11
我们在前面指针的内容中就已经讲解过怎么模拟实现strlen函数,这里不再重复:
因为会使用到指针,这里加上assert,防止使用空指针
#include <assert.h>
size_t my_strlen(char* s)
{assert(s);size_t len = 0;while(*s++){len++;}return len;
}
这里再给处一种不创建临时变量的方法:
int my_strlen(const char * str)
{assert(str);if(*str == '\0')return 0;elsereturn 1+my_strlen(str+1);
}
利用递归与指针的方式,在不创建临时变量的情况下,模拟实现strlen函数,不过这种方法的运行效率比较低,运行会上面的代码慢
4. strcpy函数的使用和模拟实现
strcpy函数的原型为:
char* strcpy(char * destination, const char * source );
Copies the C string pointed by source into the array pointed by destination, including the terminating null character (and stopping at that point).
简单来说就是将一个字符串的内容复制到另一个字符串中,进行这个操作要满足这些条件:
源字符串必须以'\0'结尾。
会将源字符串中的'\0'拷贝到目标空间。
目标空间必须足够大,以确保能存放源字符串。
目标空间必须可修改。
了解这些后,我们可以尝试将一个字符串的内容复制到另一个字符串中:
#include <string.h>
#include <stdio.h>
int main()
{char s1[20] = "Hello World";char s2[] = "Good morning";printf("%s\n", strcpy(s1,s2));printf("%s\n",s1);return 0;
}
Good morning
Good morning
了解了使用方法后,我们现在来思考如何模拟实现strcpy函数:
由于C语言自带的strcpy函数无法检测目标字符串大小是否能够放下源字符串内容,我们在模拟实现时加上这一步判断。
首先,我们要让函数接收目标字符串dest和源字符串src的地址。
接着,我们要保证传递的两个字符串的地址是有效的,我们要使用assert函数;而且,也要保证字符串dest足够放下字符串src中的内容,那就需要比较两个字符串的大小。考虑到目标字符串中可能出现'\0'提前出现的情况,我们不能使用strlen来计算目标字符串的大小,因此,我们需要用sizeof来计算目标字符串大小;相对地,源字符串不需要考虑这个问题,但是字符'\0'也是需要占据空间地,因此在比较时需要让其+1。但是,由于字符数组dest地址在传递给函数时会转化为数组首元素的地址,在函数内部中使用时只能找到该元素而无法找到整个字符数组,因此在传递参数时我们还有额外传递参数size_dest,用于比较大小。
然后,我们就需要考虑如何将一个字符串的内容复制到另一个字符串中。
这里我们就要使用指针方法逐个访问字符串dest和src中的内容,并将src中的内容赋值给dest,直到访问到src中的'\0'。
最后,返回目标字符串的地址,但是现在有个问题,那就是指针dest指向的地址在我们复制操作结束后已经不是指向dest首字符的地址了。因此,我们需要在赋值前创建一个指针变量来存储该地址,用于最后返回。
分析完毕,代码形式如下:
char* my_cpy(char* dest,const char* src,size_t size_dest)
{assert(dest && src);if(size_dest < strlen(src) + 1){printf("目标字符串空间大小不足");return NULL;}char* origin_dest = dest;while((*dest++ = *src++));return origin_dest;
}
我们尝试使用一下函数my_cpy:
int main()
{char s1[20] = "Hello World";char s2[] = "Good morning";printf("%s\n", my_cpy(s1,s2, sizeof(s1)));printf("%s\n",s1);return 0;
}
Good morning
Good morning
我们可以发现,打印结果符合我们预期,代码成功模拟实现了strcpy函数的效果。
5. strcat函数的使用和模拟实现
函数strcat原型如下:
char *strcat(char *dest, const char *src);
Appends a copy of the source string to the destination string.
The terminating null character in destination is overwritten by the first character of source,
and a null-character is included at the
end of the new string formed by the concatenation of both in destination
简单来说就是,将一个字符串的内容追加到另一个字符串的末尾,进行这个操作要满足这些条件:
源字符串必须以'\0'结束
目标字符串中也得有'\0',否则无法知道从哪里开始追加
目标空间必须有足够的大,能容纳下源字符串的内容。
目标空间必须可修改。
了解这些后,我们可以尝试使用一下strcat函数:
#include <string.h>
#include <stdio.h>
int main()
{char s1[20] = "Hello ";char s2[] = "World";printf("%s\n", strcat(s1,s2));printf("%s\n",s1);return 0;
}
Hello World
Hello World
我们可以看到,strcat函数成功将字符串s2的内容追加到了字符串s1末尾。
现在,我们来思考一下如何模拟实现strcat函数:
同样的,由于C语言自带的strcat函数无法检测目标字符串大小是否能够放下源字符串内容,我们在模拟实现时加上这一步判断。
首先,我们需要函数接收两个字符串dest和src的地址,以及字符串dest的大小size_dest。
接着,就是相同的操作,检验指针的有效性以及字符串dest的空间是否符合要求。若是条件都满足,创建一个指针变量来存储dest的地址。
然后,就是追加的操作,这一步和上面my_cpy的操作一样。只不过我们需要先找到dest中第一个'\0'的位置,然后再开始追加操作。
最后,返回dest的地址。
代码形式如下:
char* my_cat(char* dest,const char* src,size_t size_dest)
{assert(dest && src);size_t need = strlen(dest) + strlen(src) + 1;if(size_dest < need){printf("目标空间不足,实际需要空间为%zd\n",need);return NULL;}char* origin_dest = dest;while(*dest) dest++;while((*dest++ = *src++));return origin_dest;
}
我们尝试使用一下函数my_cat:
int main()
{char s1[20] = "Hello ";char s2[] = "World";printf("%s\n", my_cat(s1,s2, sizeof(s1)));printf("%s\n",s1);return 0;
}
Hello World
Hello World
我们可以发现,打印结果符合我们预期,代码成功模拟实现了strcat函数的效果。