目录字符分类函数字符转换函数基础函数使用strlen 使用和模拟与实现strcpy 使用和模拟与实现strcat 使用和模拟与实现strcmp 使用和模拟与实现进阶函数使用strncpy 函数的使用strncat 函数的使用strncmp 函数的使用strstr 使用和模拟实现strtok 函数使用strerror 函数使用perror 函数使用C语言内存函数memcpy 使用和模拟实现memmove 使用和模拟实现memset 函数的使用memcmp 函数的使用字符分类函数C语言中有一系列的函数是专门做字符分类的也就是一个字符是属于什么类型的字符的。这些函数的使用都需要包含一个头文件是ctype .h这写函数其实都比较类似就只介绍一个int islower ( int c );当识别到数值为a~z的小字母就会返回非0 数值如果不是就返回0数值。字符转换函数C语言提供了2个字符转换函数int tolower ( int c ); //将参数传进去的大写字母转小写 int toupper ( int c ); //将参数传进去的小写字母转大写函数使用#include stdio .h #include ctype .h int main () { int i 0; char str [] Test String.\n; char c; while (str[i]) { c str [i]; if (islower(c)) c toupper(c); putchar(c); i; } return 0; }但其实这中其实可以通过加减32来通过改变字符英文字母大小就可以这个函数也只是作为一个了解即可。string.h介绍string.h 的库函数里面有strcpy、strcat、strcmp、strncpy、strncat、strncmp、strstr、strtok、strerror、memcmp等等的函数那我们来一 一介绍。基础string.h函数使用strlen 使用和模拟与实现strlen 的介绍strlen 是用来计算字符串的首地址到达‘\0’位置之间又多少个字符的函数补充准确来说strlen 不是string.h 函数里面的没有string.h 的库函数也可以使用。size_t strlen(char* str)放回类型size_t (非负数的整形类型传参 char* 字符指针模拟实现strlen_my 函数来实现代码方法1利用循环来实习strlen的代码实现原理通过循环计算当代码执行到‘\0’的时候就停止计算。size_t strlen_my1(char* str) { size_t i 0; for (i 0; *(str i) ! \0; i); return i; }方法2利用递归的方式来实现代码原理通过执行代码如果不是‘\0’就进行1strlen(str1)如果遇到‘\0就停止计算返回值为0。size_t strlen_my2(char* str) { if (*str) { return 1 strlen_my2(str 1); } return 0; }strcpy 使用和模拟与实现strcpy 的介绍strcpy 是一个cpy 有关的函数通过cpy 就是拷贝的功能可以将一个数组的内容考培到了一个数组里面。char* strcpy(char* str1,char const* str2)返回值char* 返回str1 的首元素地址传参char* 第一个值是载体要被同化对象。char const * 第二个就是内容从const *可以从不能对*str2不能修改内容就可以看出。模拟实现strcpy_my 函数来实现strcpy 函数代码实现原理传参不能为空地址循环来实现代码遇到‘\0’循环也可以直接结束在代码最开始的标记好首元素地址循环执行完也也有直接返回地址。char* my_strcpy(char* str1, char const* str2) { char* tmp str1; assert(str1 ! NULL); assert(str2 ! NULL); while (*str1 *str2); return tmp; }strcat 使用和模拟与实现strcat 的介绍strcat 的函数与strcpy 类似也是跟拷贝有关但是它与strcpy拷贝不同strcat 是在str1的字符串最后‘\0‘位置进行拷贝char * strcat ( char * destination , const char * source );返回值char* destination的最开始位置传参destination指针指向目的地空间source指针指向源头数据、模拟实现my_strcat 实现代码原理就还是与strcpy 保持一致就在拷贝之前先进行移位操作。char* my_strcat(char* str1, char const* str2) { char* tmp str1; assert(str1 ! NULL); assert(str2 ! NULL); while (*str1) str1; while (*str1 *str2); return tmp; }strcmp 使用和模拟与实现strcmp 的介绍strcmp 是用来比较的函数比较标准是通过ASCII 的数值大小来比较的。int strcmp ( const char * str1 , const char * str2 );返回值标准规定第一个字符串大于第二个字符串则返回大于0的数字第一个字符串等于第二个字符串则返回0第一个字符串小于第二个字符串则返回小于0的数字模拟实现my_strcmp来实现代码:原理int my_strcmp(const char* str1, const char* str2) { while (*str1 *str2) { if (*str1 \0) return 0; str1; str2; } if (*str1 *str2) return 1; else return -1; }进阶string.h函数使用strncpy 函数的使用strncpy 的介绍strncpy 函数与strcpy 函数功能类似多了一个传参值char * strncpy ( char * destination , const char * source , size_t num );函数的多了一个可以可控制拷贝多少的控制size_t num当如果str参数destination指针指向目的地空间source指针指向源头数据num从source指向的字符串中最多拷贝的字符个数返回值strncpy函数返回的目标空间的起始地址函数的使用#include stdio.h #include string.h int main() { char str1[20] hello world.; char str2[20] world; strncpy(str1, str2,5); printf(%s, str1); return 0; }以为world 要我去拷贝数量应该输入的6而输入的是5 少拷贝了一个‘\0’的字符strncat 函数的使用strncat 的介绍同理strncat 函数与strcat 函数也是多一个可控制的拷贝数量int strncmp ( const char * str1 , const char * str2 , size_t num );功能字符串比较比较str1和str2指向的两个字符串的内容最多比较num字符。参数str1指针指向一个比较的字符串str2指针指向另外一个比较的字符串num最多比较的字符个数函数的使用int main() { char str1[20] hello; char str2[20] world.\0 I love me; strncat(str1, str2,10); printf(%s, str1); return 0; }可以看到如果拷贝对象值中间有一个‘\0’那么只拷‘\0’的位置就停止就不会在往后拷贝了。strncmp 函数的使用strncmp 的介绍同理strncmp也是多一个比较数量int strncmp ( const char * str1 , const char * str2 , size_t num );参数str1指针指向一个比较的字符串str2指针指向另外一个比较的字符串num最多比较的字符个数返回值•标准规定◦第一个字符串大于第二个字符串则返回大于0的数字◦第一个字符串等于第二个字符串则返回0◦第一个字符串小于第二个字符串则返回小于0的数字函数使用int main() { char str1[20] abcdef; char str2[20] abcde; int istrncmp(str1, str2,5); printf(%d, i); return 0; }原理解释以为比较的长度只有5那么比较str1 和str2 的长度5的内容一致那么就直接返回0。strstr 使用和模拟实现strstr 的介绍strstr 的功能是查找str2指向的字符串在str1指向的字符串中第一次出现的位置。简而言之就是找东西的函数参数str1指针指向了被查找的字符串str2指针指向了要查找的字符串返回值•如果str 1指向的字符串中存在str2指向的字符串那么返回第一次出现位置的指针•如果str 1指向的字符串中不存在str2指向的字符串那么返回NULL函数的使用int main() { char str1[20] hello world abcde; char str2[20] abcde; int* pstrstr(str1, str2); if (p) printf(%p, p); return 0; }模拟实现my_strstr 函数实现char* my_strstr(char const* str1, char const* str2) { assert(str1 ! NULL); assert(str2 ! NULL); const char* const ret str2;//标记好str2 的初始位置 char* tmp str1; int input 0;//设置查找标记 while (*str1) { tmp str1;//标记好初始位置 str2 ret; while (*str1 *str2) { if (!*str2)//所有的数值查找到‘\0’就标记好查找结束 { input 1;//标记查找到的证明 break; } } if (input) return tmp;//返回标记1位置 tmp; str1 tmp; } return NULL; } int main() { char str1[20] hello world abcde ; char str2[20] world; int* pmy_strstr(str1, str2); if (p) printf(%p, p); return 0; }strtok 函数使用strtok 的介绍strtok 的函数的功能是分割字符串的功能char *strtok(char *str , const char *delim);参数1.str首次调用时传入待分割的字符串后续调用传入NULL表示继续分割同一个字符串。2.delim包含所有可能分隔符的字符串每个字符均视为独立的分隔符。返回值•成功时返回指向当前子字符串的指针。•没有更多子字符串时返回NULL。使用步骤1.首次调用传入待分割字符串和分隔符。2.后续调用传入NULL和相同的分隔符继续分割。3.结束条件当返回NULL时表示分割完成。注意strtok 具有一定的破坏性会把原先的数组改的面目全非为了防止代码对于原先字符串的破坏要进行一个拷贝操作strcpy 。函数的运用展示1:int main() { char str1[20] 2026 5 10 21 28; char str2[] ; char cpy[30] {0}; strcpy(cpy, str1); for (char* str strtok(cpy, str2); str ! NULL; str strtok(NULL, str2)) { printf(%s\n, str); } return 0; }展示2int main() { char str1[50] https://hello.world.com/;//分割内容 char str2[] :./;//分割标准 char cpy[30] {0}; strcpy(cpy, str1); for (char* str strtok(cpy, str2); str ! NULL; str strtok(NULL, str2)) { printf(%s\n, str); } return 0; }strerror 函数使用strerror的介绍strerror 函数就像名字一样error 是跟报错有关的代码char* strerror ( int errnum );传参int 对应的数值输出对应的报错for (int i 0; i 10; i) { printf(%s\n, strerror(errno)); }//0 : No error 无错误//1 : Operation not permitted 操作不被允许//2 : No such file or directory 没有该文件或目录//3 : No such process 没有给进度//4 : Interrupted function call 函数调用中断//5 : Input / output error 输入/输出错误//6 : No such device or address 没有该设备或地址//7 : Arg list too long 参数列数表过长//8 : Exec format error 可执行格式错误//9 : Bad file descriptor 错误的文件描述符//10 : No child processes 没有子进度怎么多的数值我们也不可能一个一个去记住所有就有errno.h这个库函数来辅助程序员当代码发生对应的错误的时候就会把对应代码报错信息就会存进errno这个数值里面。函数使用#include stdio.h #include errno.h #include stdlib.h int main() { int* arr (int*)malloc(sizeof(int) * INT_MAX); if (arr NULL) { printf(error:%s\n, strerror(errno)); return 1; } return 0; }这里也报错输出了内存空间不足的报错信息。那有点人还是说太麻烦了那么有没有更加方便的函数呢当然还有一个更加方便的函数。perror 函数使用他就是strerror 和errno 的结合体可以不需要string.h和errno.h库函数就可以使用没有任何限制就可以直接使用。所以这个函数就是程序员最常用的报错代码之一了。int main() { int* arr (int*)malloc(sizeof(int) * INT_MAX); if (arr NULL) { perror(error); return 1; } return 0; }其实就等价于刚才这段代码printf(error:%s\n, strerror(errno));注意perror 会自动多加有一个 : 冒号在里面。C语言内存函数 string.hmemcpy 使用和模拟实现memcpy 的介绍memcpy 的函数其实还是与cpy 拷贝有关类似于strncpy的功能但是这个函数的传参第三个值的意义就有所不同了。void * memcpy (void * destination , const void * source , size_t num );功能•memcpy是完成内存块拷贝的不关注内存中存放的数据是啥•函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存位置。•如果source和destination有任何的重叠复制的结果都是未定义的。◦内存重叠的情况使用memmove就行参数destination指针指向目标空间拷贝的数据存放在这里source指针指向源空间要拷贝的数据从这里来num要拷贝的数据占据的字节数返回值拷贝完成后返回目标空间的起始地址函数使用展示1int main() { int arr1[10] { 1,2,3,4,5,6,7,8,9,0 }; int arr2[10] { 0,9,8,7,6,5,4,3,2,1 }; memcpy(arr2, arr1, 24); for (int i 0; i 10; i) { printf(%d , arr2[i]); } return 0; }可看到arr2 对前面6个整形int 类型进性修改数值而且刚好他的修改数值24是6*424个字节的大小那么其实修改数量的就是字节位置修改数值。模拟实现void* my_memcpy(void* str1, void const* str2, size_t size) { void* tmp str1; assert(str1); assert(str2); while (size--) { *(char*)str1 *(char*)str2; str1 (char*)str1 1; str2 (char*)str2 1; } return tmp; } int main() { int arr1[10] { 1,2,3,4,5,6,7,8,9,0 }; int arr2[10] { 0 }; my_memcpy(arr2, arr1, 24); for (int i 0; i 10; i) { printf(%d , arr2[i]); } return 0; }memmove 使用和模拟实现memmove 的介绍memmove 函数其实就是strncat 的翻版但是以为无需考虑\0的问题就其实功能还是与memcpy 一致 他们本质区别在于memmove可以处理内存地址重叠问题但你如果真的去使用的话两个都是可以处理这类问题但还是记住一些memmove 可以处理重叠问题就可以。void * memmove ( void * destination, const void * source, size_t num );函数使用展示1#include stdlib.h int main() { int arr1[10] { 1,2,3,4,5,6,7,8,9,0 }; memmove(arr12, arr1, 24); for (int i 0; i 10; i) { printf(%d , arr1[i]); } return 0; }展示2int main() { int arr1[10] { 1,2,3,4,5,6,7,8,9,0 }; memmove(arr1, arr12, 24); for (int i 0; i 10; i) { printf(%d , arr1[i]); } return 0; }模拟实现my_memmove 代码展示void* my_memmove(void* str1, void const* str2, size_t size) { void* tmp str1; assert(str1); assert(str2); if (str1 str2) { //从前往后走 while (size--) { *(char*)str1 *(char*)str2; str1 (char*)str1 1; str2 (char*)str2 1; } } else if(str1 str2) { //从后往前走 int size_my size; while (--size) { str1 (char*)str1 1; str2 (char*)str2 1; } size size_my; while (size--) { *(char*)str1 *(char*)str2; str1 (char*)str1 - 1; str2 (char*)str2 - 1; } } else { return tmp; } return tmp; } int main() { int arr1[10] { 1,2,3,4,5,6,7,8,9,0 }; my_memmove(arr12, arr1, 24); for (int i 0; i 10; i) { printf(%d , arr1[i]); } return 0; }为什么需要花费大费周章的去搞是从前往后走还是从后往前走的情况呢以为如果不去细分的话就发生数据混乱的情况。宏观模拟实现:当str2在绿色位置的时候就是不会发生内存地址重叠的情况该情况无论是从头往前走还是从尾后往走都不会发生冲的情况所以str2在红色区域的时候就是需要从后往前走的情况而黄色区域的是需要从前往后走的情况。从前往后走从后往前走memset 函数的使用memset 的介绍void * memset (void * ptr , int value , size_t num );功能•memset函数是用来设置内存块的内容的将内存中指定长度的空间设置为特定的内容。•memset的使用需要包含参数ptr指针指向要设置的内存空间也就是存放了要设置的内存空间的起始地址。value要设置的值函数将会把value值转换成unsigned char的数据进行设置的。也就是以字节为单位来设置内存块的。num要设置的内存长度单位是字节。返回值返回的是要设置的内存空间的起始地址。函数使用int main() { int arr1[10] { 1,2,3,4,5,6,7,8,9,0 }; memset(arr1, 0x12, 4); //12121212 for (int i 0; i 10; i) { printf(%d , arr1[i]); } return 0; }可以看出该函数是针对的是一个字节为的进行一个一个的修改内容四个字节每一个字节位置都附上十六进制的0x12 0x12121212 的对应的十进制数量就是3 0317 4162。memcmp 函数的使用memcmp 的介绍memcmp 就是cmp针对一个字节位的比较功能还是与其他的cmp 都是一样的。int memcmp ( const void * ptr1 , const void * ptr2 , size_t num );功能比较指定的两块内存块的内容比较从ptr 1和ptr2指针指向的位置开始向后的num个字节memcmp的使用需要包含参数ptr1指针指向一块待比较的内存块ptr2指针指向另外一块待比较的内存块num指定的比较长度单位是字节函数使用int main() { int arr1[10] { 1,2,3,4,5 }; int arr2[10] { 1,2,3,4,4 }; printf(%d, memcmp(arr1, arr2, 16)); return 0; }int main() { int arr1[10] { 1,2,3,4,5 }; int arr2[10] { 1,2,3,4,4 }; printf(%d, memcmp(arr1, arr2, 20)); return 0; }当然string.h 的介绍也不仅如此做一个简单的介绍我的介绍结束感谢观看。悠仁さん