本篇主讲字符串函数,其中包括strlen、strcpy、strcat、strcmp、strncpy、从、strncat、strncmp、strstr函数,使用这些函数都需要使用头文件<string.h>,以下会讲这些函数的使用方法,还会模拟实现部分函数。
1.strlen
1.1strlen的使用
首先需要知道strlen这个库函数的原理,下面给出cplusplus网站的解释:
https://cplusplus.com/ https://cplusplus.com/
这个函数传入一个字符串地址,然后返回字符串的长度,返回类型为size_t,即无符号整型。这个库函数计算的是'\0'前的字符个数,遇到'\0'就停止计数,如下:
所以strlen计算的字符串长度,计算的是'\0'前的字符个数,但是这里需要注意的是,返回类型为size_t是易错的返回类型,如下所示:
因为,size_t返回的类型为无符号整数,计算机使用补码计算,计算出来的值也是无符号整数,所以计算出来的值一定是正数。
1.1strlen模拟实现
以下将模拟实现strlen这个函数:
#include <stdio.h>
#include <assert.h>
//计数器方法实现
size_t my_strlen1(const char* str) {
size_t count = 0;
assert(str); //断言,判断字符串是否为空,为空则停止运行
while (*str) {
count++;
str++;
}
return count;
}
//函数递归
size_t my_strlen2(const char* str) {
assert(str);
if (*str == '\0') {
return 0;
}
else {
return 1 + my_strlen2(str + 1);
}
}
//指针-指针
int my_strlen3(const char* ptr1) {
assert(ptr1);
char* ptr2 = ptr1;
while (*ptr2 != '\0') {
ptr2++;
}
return ptr2 - ptr1;
}
测试结果:
2.strcpy
2.1strcpy的使用
在cplusplus网站中的strcpy函数的解释:
这个函数的作用是,将source指向的字符串拷贝一份到destination所指向的地址中,然后返回目标字符串的地址,有着以下几个需要注意的点:
1.源字符串必须以’\0'结束。
2.会将源字符串中的'\0'拷贝到目标空间。
3.目标空间必须足够大,以确保存放源字符串。
4.目标空间必须可修改,不能为常量字符串。
以下是用法:
这样的用法中,因为strcpy返回的值为目标字符串的地址,所以不用接收也可以。直接通过目标字符串打印也可以。现在假如我们将目标字符串换为常量字符串,看是否能够拷贝:
没有输出任何值,常量字符串的值不能被修改。
2.2strcpy的模拟实现
以下为strcpy的模拟实现:
#include <stdio.h>
#include <assert.h>
char* my_strcpy1(char* destination,const char* source) {
assert(destination && source);
char* ret = destination;
while (*source != '\0') {
*destination = *source;
destination++;
source++;
}
*destination = *source;
return ret;
}
char* my_strcpy2(char* destination, const char* source) {
assert(destination && source);
char* ret = destination;
while (*destination++= *source++) {
;
}
return ret;
}
以下为测试结果:
3.strcat
3.1strcat的使用
先通过cplusplus网站查看strcat的使用用法:
strcat的作用是在一个字符串的后面在追加一个字符串,函数的返回类型同样为目标字符串的地址,但同时需要注意以下几点:
1.源字符串必须以’\0'结束
2.目标字符串中也得有’\0',否则不知道从哪里开始追加。
3.目标空间必须足够大,以确保存放源字符串。
4.目标空间必须可修改,不能为常量字符串。
以下为strcat的使用用法:
3.2strcat的模拟实现
以下为strcat的模拟实现:
#include <stdio.h>
#include <assert.h>
char* my_strcat(char* destination, const char* source) {
assert(destination && source);
char* ret = destination;
//先找到目标字符串的\0处
while (*destination) {
destination++;
}
while (*destination++=*source++){
;
}
return ret;
}
以下为测试结果:
4.strcmp
4.1strcmp函数的使用
以下是cplusplus官网中对于strcmp的解释:
通过以上的解释,我们可以得知,stcmp是比较两个字符串的大小,但是并非比较两个字符串的长度,而是一个字符一个字符对应的比较,返回的值为一个整型,返回值的规定如下:
1.第⼀个字符串⼤于第⼆个字符串,则返回⼤于0的数字。
2.第⼀个字符串等于第⼆个字符串,则返回0。
3.第⼀个字符串⼩于第⼆个字符串,则返回⼩于0的数字。
4.⽐较两个字符串中对应位置上字符ASCII码值的⼤⼩。
以下为strcmp的函数使用:
其中对于ret返回的值,在vs2022中,只要小于都是返回-1,只要大于都是返回1,但是在其他的编译环境中,返回的值不固定。
4.2strcmp的模拟实现
以下为strcmp的模拟实现:
#include <stdio.h>
#include <assert.h>
int my_strcmp(const char* p1, const char* p2) {
assert(p1 && p2);
while (*p1==*p2){
if (*p1 == '\0') {
return 0;
}
p1++;
p2++;
}
return *p1 - *p2;
}
测试结果:
5.strstr
5.1strstr的使用
以下是cplusplus网站的对于strstr的解释 :
strstr这个库函数是寻找一个字符串的子字符串,也就是查找一个字符串中,是否包含另一个字符串,返回值为一个const修饰的指针,即返回的为函数子字符串在目标字符串中的位置,如果该目标字符串中,没有该字符串,那么返回NULL。
以下为该函数的用法:
5.2strstr的模拟实现
以下为strstr的模拟实现:
#include <stdio.h>
#include <assert.h>
char* my_strstr(const char* str1, const char* str2) {
assert(str1);
char* current = (char*)str1;
char* p1 = NULL;
char* p2 = NULL;
//空字符串直接属于子串
if (*str2 == NULL) {
return (char*)str1;
}
while (*current) {
p1 = current;
p2 = (char*)str2;
while (*p1 && *p2&& * p1 == *p2) {
p1++;
p2++;
}
if (*p2 == '\0') {
return current;
}
current++;
}
return NULL;
}
以下为测试结果:
6.strncat/strncmp/strncpy的使用
6.1strncpy的使用
先给出strncpy的定义,来源cplusplus:
通过以上的解释,我们可以得出该函数是从源字符串中拷贝num个字符给目标字符串,如果出现源字符串的长度小于num,则拷贝完之后,在目标字符串的后面加'\0'。但同样还是应该遵循,目标函数的内存空间足够大,是可以修改的字符串,不能是常量字符串。以下给出该函数的用法:
当我只拷贝三个字符时,也仅仅只会拷贝三个字符。
当我拷贝的长度超过源字符串的长度时:
超过源字符串长度时,会在后面加上'\0'。
6.2strncmp的使用
先看strncmp的定义,从cpluscplus网站
该函数的作用是,比较两个字符串的前num的字符如果相等就继续往后⽐较,最多⽐较num个字⺟,如果提前发现不⼀样,就提前结束。如果num个字符都相等,就是相等返回0。以下是该函数使用的举例:
通过以上的操作可知,前四个字符相等,后面的字符则不相等。
6.3strncat的使用
先给出strncat的模拟解释,来源:cplusplus
将source中的前num个字符追加到destination指向的字符串末尾 ,然后在追加一个'\0',如果source指向的字符串的⻓度⼩于num的时候,只会将字符串中到\0的内容追加到destination指向的字符串末尾,以下是应用举例:
当num小于源字符串时:
当num大于源字符串时:
我在目标字符串的中间增加了一个\0,当函数识别到这个\0时,就开始在这后面追加,追加完后,继续进行追加,不过追加的是\0。