目录
(一)、strlen:求字符串长度
1.函数的作用:
2.函数声明:
3.函数注意事项:
4.函数使用实例:
5.strlen函数的模拟实现:(三种方法)
(1).计数器法
(2).指针 - 指针
(3)递归方法
(二)、strcpy:字符串拷贝
1.函数声明:
2.函数的作用:
3.函数注意事项:
4.函数使用实例:
5.strcpy函数的模拟实现:
源代码:
解释:
(三)、strcat:字符串追加
1.函数声明:
2.函数的作用:
3:函数注意事项:
4:函数使用实例:
5:strcat函数的模拟实现:
源代码:
解释:
(四)、strcmp:字符串比较
1.函数声明:
2.函数的作用:
3.函数使用实例:
4.strcmp函数的模拟实现:
源代码:
解释:
(五)、strstr:字符串中找子串
1.函数声明:
2.函数的作用:
3.使用实例:
4.strstr函数的模拟实现:
(六)、strtok:字符串切割
用于求取一段字符串的长度。
size_t strlen ( const char * str );
解释:
(1).函数形参为一个char*指针str,用于接收待求字符串的首地址,const的作用是防止指针str发生改变。
(2).函数返回值为str所指向的字符串的长度,遇见'\0'结束统计,返回值类型为size_t(无符号整型)。
(1).我们知道,字符串以‘\0’作为结束标志,strlen函数返回的就是字符串中'\0'之前的出现的字符个数。
(2).参数str指向的字符串必须以'\0'结束,否则会出现难以预料的结果。
(3).该函数包含在头文件
中。
如下图:
前面三个都还好理解,数组大小为6字节,但前三种初始化,末尾会自动添加‘\0’,所以需要一字节空间存储'\0',所以字符串长度为5。而第四种初始化方式,字符串末尾不会自动添加'\0',所以strlen会一直统计下去,知道遇到'\0',才停止,所以会算出随机值的情况
源代码如下:
//计数器模拟实现strlen
#include
#include
size_t my_strlen(const char* str)
{
assert(str);
size_t count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
size_t sz = my_strlen("abcdef");
printf("该字符串长度为:%zu\n", sz);
return 0;
}
解释:
①:既然是模拟实现,所以参数与返回值类型都应该相同。
②:根据strlen函数统计原理,遇见'\0'停止,所以我们只需要创建一个变量(计数器),用一个while循环,当指针str所指向的值不等于'\0'时,计数器就+1,然后指针+1判断下一个字符,直到str所指向的值等于'\0',循环结束。最后返回计数器的值即可。
③:有的小伙伴可能不认识assert这个函数,其实这个函数只是用来检验指针str是否为空,感兴趣的小伙伴可以自行了解,不敢兴趣的伙伴可以不管。
源代码如下:
//指针-指针实现strlen
#include
#include
size_t my_strlen(const char* str)
{
assert(str);
const char* end = str;
while (*end != '\0')
{
end++;
}
return end - str;
}
int main()
{
size_t sz = my_strlen("abcdef");
printf("该字符串长度为:%zu\n", sz);
return 0;
}
解释:
①:首先我们需要明白一点,指针 - 指针得到的是什么呐?
答:指针 - 指针得到的是两指针之间的元素个数
②:所以根据上述,我们可以在创建一个与str同类型的指针end,并将str赋值给end,然后通过while循环,将end所指向的值指向该字符串中的'\0',如上,通过++操作即可达到目的。
③:最后返回end - str即可,即'\0'与首地址处之间的元素个数,示意图如下:
源代码如下:
//递归实现strlen
size_t my_strlen(const char* str)
{
if (*str != '\0')
{
str++;
return 1 + my_strlen(str);
}
return 0;
}
int main()
{
size_t sz = my_strlen("abcdef");
printf("该字符串长度为:%zu\n", sz);
return 0;
}
解释:
因为递归太抽象,所以我们画图理解,如下图:
char * strcpy ( char * destination, const char * source );
解释:
①:函数有两个形参:
第一个形参为char*指针,即为目标空间;
第二个形参const char*指针,即为源字符串。
我们就是要把source指针指向的源字符串拷贝到目标空间里面去。
②:返回值为目标空间的首地址(方便用于函数的链式访问)。
③:该函数包含在头文件
中。
参考函数声明,就是将形参source指向的源字符串拷贝到形参destination所指向的目标空间里面去,包含'\0'。
①:源字符串必须以'\0'结束。
②:会把源字符串的'\0'也拷贝到目标空间里面去。
③:目标空间必须足够大,以确保能够存放源字符串。
④:目标空间必须可变,所以没有用const修饰。
1.正常使用:
源代码如下:
#include
#include int main() { char arr1[] = { 'a','b','c','\0' }; char arr[10] = " "; strcpy(arr, arr1); printf("%s\n", arr); return 0; } 运行结果:
2.若目标空间不够大的情况:
3.目标空间不可变的情况:
源代码:
//模拟实现strcpy #include
#include char* my_strcpy(char* dest, const char* sour) { assert(dest && sour); char* tmp = dest; while (*dest++ = *sour++) { ; } return tmp; } int main() { char arr[] = "abcdef"; char dest[10] =" "; my_strcpy(dest,arr); printf("%s\n", dest); return 0; } 解释:
①:既然是模拟实现,所以返回类型,参数都应该相同。
②:思路:是一个字符一个字符的拷贝,直到遇见'\0'结束。
③:因为我们需要返回目标空间的起始地址,所以开头先创建一个指针变量tmp保存目标空间的起始地址。
④:接着我们用一个while循环用于一个字符一个字符的拷贝,将sour指向的值赋给dest指向的空间,接着判断sour指向的值是否等于'\0',若不等于,则sour和dest都+1,拷贝下一个字符;若等于'\0',将'\0'拷贝后循环结束,所以'\0'的ASCII值等于0。
⑤:最后返回目标空间首地址tmp。
char * strcat ( char * destination, const char * source );
解释:
①:函数有两个形参:
第一个形参为char*指针,即待追加字符串(目标空间),所以不用const修饰。第二个形参为const char*指针,即源字符串,源字符串不能改变,所以用const修饰。
该函数就是把source指向的源字符串追加到destination指向的待追加字符串的末尾。
②:函数返回值为待追加字符串的首地址。
③:该函数包含在头文件
中。
参考函数声明,即把source指向的源字符串追加到destination指向的待追加字符串的尾部。
1.源字符串source必须以'\0'结束。
2.目标空间必须足够大,能够容纳下源字符串。
3.目标空间必须可修改。
4.尽量别自己给自己追加。
源代码如下:
#include
int main() { char arr[] = "world"; char dest[20] = "hello "; strcat(dest, arr); printf("%s\n", dest); return 0; } 运行结果:
源代码:
//模拟实现strcat #include
#include char* my_strcat(char* destination, const char* source) { assert(destination && source); //存目标空间首地址 char* tmp = destination; //找到目标空间'\0'的位置; while (*destination) { destination++; } //从目标空间'\0'位置开始,将源字符串的字符一个个的拷贝进来,与strcpy类似 while (*destination++ = *source++) { ; } return tmp; } int main() { char arr[] = "world"; char dest[20] = "hello "; my_strcat(dest, arr); printf("%s\n", dest); return 0; } 解释:
①:因为是模拟实现,所以返回值,参数都应该相同。
②:思路:先找到目标空间的'\0'位置处,然后从此位置开始,将源字符串的内容一个字符一个字符的拷贝过来,直到拷贝到源字符串的'\0'结束。
③:因为返回值是目标空间的首地址,所以开始先将首地址保存在变量tmp中。
④:然后用一个while循环,将指针destination指向目标空间的'\0'位置处。
⑤:从此位置开始,用strcpy函数模拟实现的方法,将源字符串的内容一个一个字符拷贝过来,直到拷贝到源字符串的'\0'后循环结束。
⑥:最后返回目标空间首地址tmp。
⑦:该模拟实现有一个缺点,就是不能自己给自己追加。
int strcmp ( const char * str1, const char * str2 );
解释:
1.该函数有两个参数,参数类型一样,因为只需要进行比较,不能改变原字符串内容,所以用const修饰。
2.该函数返回类型为int,返回值根据下述标准适用。
3.该函数包含在头文件
中。
该函数是用于两段字符串的比较,
比较方法:
将两字符串对应位置处的字符拿出来一个一个的比较ASCII码值,若第一个字符相同,即ASCII码值相同,则比较第二个字符的ASCII码值。
比较规则:
源代码:
//模拟实现strcmp #include
#include int my_strcmp(const char* str1, const char* str2) { assert(str1 && str2); while (*str1 == *str2) { if (*str1 == '\0' && *str2 == '\0') return 0; str1++; str2++; } return *str1 - *str2; } int main() { printf("%d\n", my_strcmp("abc", "azc")); return 0; } 解释:
①:因为是模拟实现,因为返回值,参数都应该相同。
②:首先一个while循环判断两字符串是否相等,一个字符一个字符的判断,若都相等,则判断到'\0'处就返回0;若比较到某个字符不相等,则出循环,然后返回*str1 - *str2,因为我们是根据ASCII码值来比较的,所以如果*str1大于*str2,则两者相减返回的是一个大于0的数,如果*str1小于*str2,则两者相减返回的是一个小于0的数,这与标准刚好吻合。
const char * strstr ( const char * str1, const char * str2 );
char * strstr ( char * str1, const char * str2 );
解释:
1.该函数有两个参数,就是在主串str1中查找看是否存在子串str2。
2.返回值:
若主串str1中找不到子串str2,则返回NULL(空指针)。
若找到了,则返回子串str2在主串str1中第一次出现的首地址。
即在主串str1中找子串str2:
找不到,返回NULL。
找到了,返回子串str2在主串str1中首次出现的首地址。
//模拟实现strstr
#include
char* my_strstr(char* str1, char* str2)
{
assert(str1 && str2);
char* cp = str1;
char* s1 = cp;
char* s2 = str2;
while (*cp)
{
//开始匹配
s1 = cp;
s2 = str2;
while (*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}
if (*s2 == '\0')
{
return cp;
}
cp++;
}
return NULL;
}
int main()
{
char arr1[] = "abbbcdef";
char arr2[] = "bbc";
char* ret = my_strstr(arr1, arr2);
if (ret != NULL)
printf("%s\n", ret);
else
printf("找不到\n");
return 0;
}
因为该函数很少使用,所以只做以下说明;
函数使用实例:
本次知识到此结束,希望对你有所帮助!