在C语言的学习实践中, 对于字符串的操作是非常常见的. 下面我将介绍几种常用的字符串函数, 写明函数作用以及如何使用如何模拟.
目录
strlen函数:
函数用途:strlen函数用于计算字符串的长度(不包括'\0').
#include <stdio.h> #include <string.h> int main() { char arr[] = "abcd"; printf("%d\n", strlen(arr)); return 0; }
输出的结果为4.
strlen的返回值是size_t, 接受一个const char *型的指针(不可修改的字符串).
本质上是识别一个一个字符直到'\0'出现就返回对应的值.
自己模拟strlen函数:
#include <stdio.h> size_t mystrlen(const char* s) { if (s == NULL) return 0; int res = 0; while (*s != '\0' && ++s && ++res) ; return res; } int main() { char arr[] = "abcdef"; printf("%d\n", mystrlen(arr)); return 0; }
注意: 如果传入的数组没有'\0'将会导致数组访问越界算出错误的随机答案.
strcpy函数:
函数用途:strcpy函数可以将一个字符串的内容拷贝到另一个字符串中.
#include <stdio.h> #include <string.h> int main() { char arr[20]; const char* copy = "abcdefg"; printf("%s\n", strcpy(arr, copy)); return 0; }
输出结果是abcdefg.
strcpy函数返回一个char*指针指向复制完的字符串的开头, strcpy函数接收一个待被复制的char*的指针和准备复制过去的const char*指针(将后者拷贝至前者处), 以'\0'为结尾拷贝复制每个字符.
自己模拟strcpy函数:
#include <stdio.h> #include <assert.h> char* mystrcpy(char* destination, const char* source) { assert(destination != NULL && source != NULL); // 断言防止传入NULL指针, 增强代码安全性. char* res = destination; // 记录首元素地址. while (*source != '\0') { *destination++ = *source++; // 复制字符. } *destination = *source; // 复制斜杠0. return res; } int main() { char arr[20]; const char* copy = "abcdefg"; printf("%s\n", mystrcpy(arr, copy)); return 0; }
输出结果是abcdefg.
注意: 如果传入的数组没有'\0'将会导致数组访问越界.
strcmp函数:
函数用途: 比较两个字符串的大小.
#include <stdio.h> #include <string.h> int main() { char arr1[] = "abcdea"; char arr2[] = "abcdgr"; int res = strcmp(arr1, arr2); if (res > 0) printf("大于\n"); else if (res < 0) printf("小于\n"); else printf("等于\n"); return 0; }
输出结果为小于.
strcmp函数接收两个char*指针, 比较每个字符的大小, 一有不相同就返回对应的值, 如果完全相同返回0, 前者大于后者返回值大于0, 前者小于后者返回值小于0.
自己模拟strcmp函数:
#include <stdio.h> #include <assert.h> int mystrcmp(const char* arr1, const char* arr2) { assert(arr1 != NULL && arr2 != NULL); while (*arr1 == *arr2) { if (*arr1 == '\0' || *arr2 == '\0') break; // 有一个字符串到了结尾就退出. ++arr1; ++arr2; } return *arr1 - *arr2; // 返回当前字符的差值, 大于0则arr1大否则arr2大. } int main() { char arr1[] = "abcdea"; char arr2[] = "abcdgr"; int res = mystrcmp(arr1, arr2); if (res > 0) printf("大于\n"); else if (res < 0) printf("小于\n"); else printf("等于\n"); return 0; }
结果同样是小于.
注意: 传入的char*指针指向的字符串要有'\0', 不能传入NULL指针.
strcat函数:
函数用途: 将一个字符串追加到另一个字符串后面.
#include <stdio.h> #include <string.h> int main() { char arr[20] = "Hello "; const char* s = "world!"; printf("%s\n", strcat(arr, s)); return 0; }
运行结果是: Hello world!
strcat函数接收一个char*指针和一个const char*指针, 将后者指向的字符串追加到前者后面, 以'\0'为终止符, 返回追加完毕之后的字符串的首元素地址.
自己模拟strcat函数:
#include <stdio.h> #include <assert.h> char* mystrcat(char* destination, const char* source) { assert(destination != NULL && source != NULL); char* res = destination; // 记录首元素地址. while (*destination != '\0') ++destination; // 找到字符串结尾. while (*destination++ = *source++) ; // 从字符串结尾开始追加. return res; } int main() { char arr[20] = "Hello "; const char* s = "world!"; printf("%s\n", mystrcat(arr, s)); return 0; }
注意: 传入的char*指针指向的字符串要有'\0', 不能传入NULL指针.
strstr函数:
函数用途: 判断一个字符串是否是另一个字符串的子串(包含于的关系).
#include <stdio.h> #include <string.h> int main() { char arr[] = "abcdefg"; const char* s = "cde"; char* res = strstr(arr, s); if (res != NULL) { printf("%s\n", res); } else { printf("找不到!\n"); } return 0; }
输出结果为:cdefg.
strstr函数接收两个字符串, 前者为主串, 后者为子串, 用于判断后者是否出现在前者中, 如果出现则返回出现的第一个字符的地址, 否则返回NULL.
自己模拟strstr函数:
#include <stdio.h> #include <assert.h> char* mystrstr(const char* arr1, const char* arr2) { assert(arr1 != NULL && arr2 != NULL); if (*arr2 == '\0') return NULL; while (*arr1) { const char* h = arr1; const char* n = arr2; while (*h && *n && *h == *n) { ++h; ++n; } if (*n == '\0') return (char*)arr1; // 如果 arr2 完全匹配,返回匹配位置的指针. ++arr1; // 如果不匹配,则 arr1 后移一位,继续尝试. } return NULL; // 如果没有匹配到,返回 NULL. } int main() { char arr[] = "abcdefg"; const char* s = "cde"; char* res = mystrstr(arr, s); if (res != NULL) { printf("%s\n", res); } else { printf("找不到!\n"); } return 0; }
strtok函数:
函数用途: 函数用于切割字符串中指定的字符.
有点抽象, 具体看下面代码自行体会:
#include <stdio.h> #include <string.h> int main() { char arr[] = "abc,,dd.er;;;ggg"; printf("%s\n", strtok(arr, ",.;")); printf("%s\n", strtok(NULL, ",.;")); printf("%s\n", strtok(NULL, ",.;")); printf("%s\n", strtok(NULL, ",.;")); printf("%s\n", strtok(NULL, ",.;")); return 0; }
每次传入NULL系统会从上次截取的地方继续往下截图, 运行结果截图如下: