引言:对于字符串来说,我们通常想要对其完成各种各样的目的,不管是排序还是查找都是最普遍的功能,而我们的C语言中也包含着一系列函数是为了实现对字符串的一些功能,今天我们就来介绍他们。
strlen函数:
求字符串的长度(也就是求一个字符串的'\0'前面有多少个字符)
#include<stdio.h> #include<string.h> int main(){ char* str = "abcdef"; int b = strlen(str); printf("%d\n", b); return 0; }
这个就是strlen最常用的,用来求一个字符串的长度,那么我们是否可以不用库函数,自己模拟一个strlen呢🤔
#include<stdio.h> #include<string.h> //方法一:计数法 size_t my_strlen1(char* str) { int count = 0; while (*str) { count++; str++; } return count; } int main(){ char* str = "abcdef"; int c = my_strlen1(str); printf("%d\n", c); return0; }
方法一:计数法,利用for循环,用count计数,当str遇到'\0'的时候循环结束,跳出循环,返回count的值。
#include<stdio.h> #include<string.h> //方法二:递归法 size_t my_strlen2(char* str) { if (*str == '\0') return 0; else return 1+my_strlen2(str+1); } int main() { char* str = "abcdef"; int d = my_strlen2(str); printf("%d\n", d); return 0; }
方法二:递归法,利用递归思想,当没有遇到'\0'的时候,就再次调用该函数,直到str遇到'\0',返回0,然后依次再重新返回,就计算出了字符串的长度。
#include<stdio.h> #include<string.h> //方法三:指针-指针 size_t my_strlen3(char* str) { char* p = str; while (*p != '\0') { p++; } return p - str; } int main(){ char* str = "abcdef"; int e = my_strlen3(str); printf("%d\n", e); return 0; }
方法三:指针-指针,我们先将字符串的首元素地址记为str,再将首元素地址传给p,利用while循环找到最后一个元素的地址,当(结束地址-首元素地址)即为字符串长度。
可以看我们四种方法的运行结果,都是可以正确的求出字符串‘acbdef的长度.
strcpy函数:
#include<stdio.h> #include<string.h> int main(){ char arr1[20] = { 0 }; char arr2[] = "Hello"; strcpy(arr1, arr2); printf("%s\n", arr1); return 0; }
这个函数的作用就是将arr2中的字符串拷贝到arr1中。那么我们该如何对他进行模拟实现呢🤔
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> char* my_strcpy(char* dest, const char* src) { char* ret = dest; while (*dest++ = *src++) { ; } return ret; } int main(){ char arr1[20] = { 0 }; char arr2[] = "Hello"; //strcpy(arr1, arr2); my_strcpy(arr1, arr2); printf("%s\n", arr1); return 0; }
我们先将两个数组的首元素地址传给函数,因为最终要返回起始地址,所以先将dest给ret,然后运用while循环将src的每一项解引用后赋给dest,然后后置++再寻找下一个元素,直到src元素找到了'\0',然后循环跳出,返回起始地址ret。
我们把arr1打印出来可以看到确实是成功拷贝。
strcmp函数:
比较的结果是:
如果str1>str2那么就返回一个>0的数
如果str1<str2那么就返回一个<0的数
如果str1=str2那么就返回0
#include<stdio.h> #include<string.h> int main() { char arr1[] = { "abc" }; char arr2[] = { "abdef" }; int a = strcmp(arr1, arr2); if (a > 0) printf(">="); else printf("<"); return 0; }
这是一个简单的例子,因为d的ASC的值比c的ASC的值大,所以arr1<arr2,所以返回的是一个小于0的数,所以 打印出来的就是小于号。
那么我们来模拟实现实现一下这个函数
#include<stdio.h> #include<string.h> int my_strcmp(const char* dest, const char* src){ while (*dest == *src) { if (*dest == 0) return 0; dest++; src++; } if (*dest > *src) return 1; else return -1; } int main() { char arr1[] = { "abc" }; char arr2[] = { "abdef" }; int a = my_strcmp(arr1, arr2); if (a > 0) printf(">="); else printf("<"); return 0; }
首先,还是一样,先传值然后依旧是运用我们的while循环来进行遍历以及交换,当其中一个已经遍历完之后,会跳出while循环,然后开始判断当前元素谁大谁小,然后根据大小返回大于零还是小于零的数。
strcat函数:
#include<stdio.h> #include<string.h> int main() { char arr1[20] = { "abc"}; char arr2[] = { "def" }; //库函数自带的strcat strcat(arr1, arr2); printf("%s\n", arr1); return 0; }
值得注意的是:
1、目标空间必须足够大,并且可以修改
2、目标空间中必须有\0,以便能够找到目标空间的末尾
3、源字符串中也得有\0,拷贝的时候要拷过去
那么我们如何对这个函数进行模拟实现呢🤔
#include<stdio.h> #include<assert.h> char* my_strcat(char* dest, char* src) { char* ret = dest; assert(dest && src); while (*dest != '\0') { dest++; } while (*dest++ = *src++) { ; } return ret; } int main() { char arr1[20] = { "abc"}; char arr2[] = { "def" }; my_strcat(arr1, arr2); printf("%s\n", arr1); return 0; }
依然是传参,然后用第一个while循环找到目标空间中的\0然后,跳出循环,此时dest指向目标函数的末尾,然后进入第二个循环,src开始给dest进行赋值,直到src遇到\0,跳出循环,返回目标函数的起始地址,完成追加。
strstr函数:
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> int main() { char arr1[] = { "abcdefghi" }; char arr2[] = { "def" }; char* ret = strstr(arr1, arr2); if (ret == NULL) { printf("找不到"); } else printf("%s", ret); return 0; }
strstr是字符串查找函数,我们给函数传两个字符串的时候,他会拿源函数去和目标函数进行匹配,如果目标函数中有原函数那么,就返回段函数的起始地址,如果找不到,那么就会返回NULL
那么我们该如何模拟实现这一函数呢🤔
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<string.h> #include<assert.h> const char* my_strstr(const char* str1, const char* str2) { const char* sp; const char* s1; const char* s2; assert(str1 && str2); if (*str2 == '\0') { return str1; } sp = str1; while (*sp) { s1 = sp; s2 = str2; while (*str1 && *str2 && *s1 == *s2) { s1++; s2++; } if (*s2 == '\0') return sp; sp++; } return NULL; } int main() { char arr1[] = { "abcdefghi" }; char arr2[] = { "def" }; char* ret = my_strstr(arr1, arr2); if (ret == NULL) { printf("找不到"); } else printf("%s", ret); return 0; }
可以看到,我们模拟实现的函数成功的查找到了目标函数中的def,并且返回了找到它的起始位置。那么具体的实现我来详细的讲解一下。
如图,我们用s1和s2进行比较,
1️⃣如果两个相同就各自+1比较下一个,那么按照这样进行下去,当str2为0的时候,就证明已经找到了,如果str1已经为0,str2还没有为0那么就证明,str1里找不到str2。
2️⃣如果两个不同就sp++,然后sp再赋值给s1,这样就不会使得s1一直向前++而找不到原来的位置了,s2也是一样,当sp赋值给s1的时候,str2也同时赋值给s2,让s2能回到起始位置。
这样一直对比下去,直到s1或s2指向0,函数结束。那我们这个函数的模拟就算实现了,但是其实这是个笨方法,效率不高,如果大家感兴趣的话,可以去了解了解kmp算法。
strerror函数:
是用来打印错误码的函数
strtok函数:
是用来将一段字符串进行分割的函数
#include<stdio.h> #include<string.h> int main() { char arr[] = "haohao@xuexi@tiantian.xiangshang"; char* p = "@."; char* s = NULL; for (s = strtok(arr, p); s != NULL; s = strtok(NULL, p)) { printf("%s\n",s); } return 0; }
我们这里可以看到,strtok将arr里的字符串给分隔开了,这个函数可以把指定参数替换成'\0',这样就可以将那些干扰的字符给去掉,并将其一一打印出来了。
好了,今天我就给大家分享到这里,感谢大家的观看!!!