库函数
函数介绍及模拟实现
1.1strlen
1.2strcpy
1.3strcat
1.4strcmp
1.5strncpy
1.6strncat
1.7strncmp
1.8strstr
1.9strtok
1.10strerror
1.11memcpy
1.12memmove
1.13memcmp
小结
本章重点:
重点介绍处理字符串和字符串的库函数的使用和注意事项
size_t strlen ( const char * str );
示例>
#include
int main()
{
const char*str1 = "abcdef";
const char*str2 = "bbb";
if(strlen(str2)-strlen(str1)>0)
{
printf("str2>str1\n");
}
else
{
printf("srt1>str2\n");
}
return 0;
}
运行结果>
strlen函数实现有三种方式:
模拟实现>
/*模拟实现strlen*/
//常规
size_t my_strlen1(char* str)
{assert(str);size_t count = 0;while (*str){str++;count++;}return count;
}
//指针运算
size_t my_strlen2(char* str)
{assert(str);char* strat = str;while (*str){str++;}return str - strat;
}
//递归实现
size_t my_strlen3(char* str)
{assert(str);if (*str)return 1 + my_strlen3(str + 1);elsereturn 0;
}int main()
{char arr[] = "abcdef";size_t ret = my_strlen1(arr);printf("%d\n", ret);ret = my_strlen2(arr);printf("%d\n", ret);ret = my_strlen3(arr);printf("%d\n", ret);return 0;
}
这里的assert函数是判断传递过来的指针是否为空,如果为空直接终止程序报告错误。
运行结果>
char * strcpy ( char * destination, const char * source );
int main()
{char str[20] = "";char* p = "hello world!";strcpy(str, p);printf("%s", str);return 0;
}
模拟实现>
/*模拟实现strcpy*/
char* my_strcpy( char* str1,const char* str2)
{char* ret = str1;assert(str1 && str2);while (*str1++ = *str2++){;}return ret;
}int main()
{char str[20] = "";char* p = "hello world!";my_strcpy(str, p);printf("%s", str);return 0;
}
结果跟上面例子相同。
char * strcat ( char * destination, const char * source );
模拟实现>
/*模拟实现strcat*/char* my_strcat(char* str1, const char* str2)
{assert(str1 && str2);char* ret = str1;while (*str1){str1++;}while (*str1++ = *str2++){;}return ret;
}int main()
{char arr[20] = "hello";char* p = " world!";my_strcat(arr, p);printf("%s", arr);return 0;
}
运行结果 >
那自己追加自己会发生什么呢?
我们来写代码演示演示(这里还是用我们的my_strcat)>
char* my_strcat(char* str1, const char* str2)
{assert(str1 && str2);char* ret = str1;while (*str1){str1++;}while (*str1++ = *str2++){;}return ret;
}int main()
{char arr[20] = "hello";my_strcat(arr, arr);printf("%s", arr);return 0;
}
我们可以看到程序挂掉了,那为什么会挂掉呢?
我们来画图解释一下>
int strcmp ( const char * str1, const char * str2 );
模拟实现>
/*模拟实现strcmp*/int my_strcmp(const char* str1, const char* str2)
{assert(str1 && str2);while (*str1 == *str2){if (*str1=='\0')return 0;str1++;str2++;}if (*str1 > *str2){return 1;}else{return -1;}}int main()
{char arr1[] = "abr";char arr2[] = "abqde";int ret = my_strcmp(arr1, arr2);if (ret == 0)printf("相同\n");else if (ret > 0)printf("arr1>arr2\n");elseprintf("arr1
运行结果>
当然我们目前学习了strcpy、strcat、strcmp,这些都是不太安全的,一次性全部拷贝完、一次性全部追加完、一次性全部比较完,这些都不是很安全,那么接下来我们要学习一些相对于上面那三个比较安全一点的。strncpy、strncat、strncmp,这三个函数的功能和上面的一样,不同的是参数多了一个n,来确定每次拷贝几个字符、每次追加几个字符、每次比较几个字符。接下来我们来模拟实现一下这三个函数。
char * strncpy ( char * destination, const char * source, size_t num );
模拟实现>
char* my_strncpy(char* dest, const char* src, size_t num)
{assert(dest && src);char* ret = dest;size_t i = 0;for (i = 0; i < num; i++){*dest = *src;dest++;src++;}return ret;
}int main()
{char str1[] = "abcdefg";char str2[20] = { 0 };my_strncpy(str2, str1, 5);printf(str2);return 0;
}
运行结果>
char * strncat ( char * destination, const char * source, size_t num );
模拟实现>
char* my_strncat(char* dest, const char* src, size_t num)
{assert(dest && src);char* ret = dest;while (*dest){dest++;}size_t i = 0;for (i = 0; i < num; i++){*dest = *src;dest++;src++;}return ret;
}int main()
{char str1[20] = "abcd";char str2[20] = "efghigk";my_strncat(str1, str2, 4);printf(str1);return 0;
}
运行结果>
int strncmp ( const char * str1, const char * str2, size_t num );
模拟实现>
int my_strcmp(const char* str1, const char* str2,size_t num)
{assert(str1 && str2);size_t i = 0;for (i = 0; i < num; i++){if (*str1 > *str2)return 1;else if (*str1 < *str2)return -1;str1++;str2++;}if (*str1 == *str2)return 0;}int main()
{char arr1[] = "abqsg";char arr2[] = "abqde";int ret = my_strcmp(arr1, arr2,4);if (ret == 0)printf("相同\n");else if (ret > 0)printf("arr1>arr2\n");elseprintf("arr1
运行结果>
const char * strstr ( const char * str1, const char * str2 );
模拟实现(暴力算法)>
/*模拟实现strstr*/char* my_strstr(const char* str1, const char* str2)
{assert(str1 && str2);if (*str2 == '\0')return (char*)str1;const char* s1 = NULL;const char* s2 = NULL;const char* cp = str1;while (*cp){s1 = cp;s2 = str2;while (*s1 != '\0' && *s2 != '\0' && *s1 == *s2){s1++;s2++;}if (*s2 == '\0'){return (char*)cp;}cp++;}return NULL;
}int main()
{char* str1 = "acdbbbcdefa";char* str2 = "bbc";char* ret = my_strstr(str1, str2);if (ret == NULL)printf("没找着\n");else{printf("%s", ret);}return 0;
}
运行结果>
char * strtok ( char * str, const char * delimiters );
代码演示>
int main()
{char arr[] = "192#168.120.85";char* p = "#.";char buf[20] = { 0 };strcpy(buf, arr); char* ret = strtok(buf, p);printf("%s\n", ret);ret = strtok(NULL, p);printf("%s\n", ret);ret = strtok(NULL, p);printf("%s\n", ret);ret = strtok(NULL, p);printf("%s\n", ret);return 0;
}
也可以使用for循环>
int main()
{char arr[] = "192#168.120.85";char* p = "#.";char buf[20] = { 0 };strcpy(buf, arr);char* ret = NULL;for (ret = strtok(buf, p); ret != NULL; ret=strtok(NULL, p)){printf("%s\n", ret);}return 0;
}
结果和上面相同。
char * strerror ( int errnum );
返回错误码,所对应的错误信息
字符分类函数>
函数 | 如果他的参数符合下列条件就返回真 |
iscntrl | 任何控制字符 |
isspace | 空白字符:空格‘ ’,换页‘\f’,换行'\n',回车‘\r’,制表符'\t'或者垂直制表符'\v' |
isdigit | 十进制数字 0~9 |
isxdigit | 十六进制数字,包括所有十进制数字,小写字母a~f,大写字母A~F |
islower | 小写字母a~z |
isupper | 大写字母A~Z |
isalpha | 字母a~z或A~Z |
isalnum | 字母或者数字,a~z,A~Z,0~9 |
ispunct | 标点符号,任何不属于数字或者字母的图形字符(可打印) |
isgraph | 任何图形字符 |
isprint | 任何可打印字符,包括图形字符和空白字符 |
字符转换>
int tolower ( int c );
int toupper ( int c );
void * memcpy ( void * destination, const void * source, size_t num );
模拟实现>
void* my_memcpy(void* dest, const void* src, size_t num)
{void* ret = dest;assert(dest && src);while (num--){*(char*)dest = *(char*)src;dest=(char*)dest+1;src=(char*)src+1;}return ret;
}int main()
{char arr[] = {"hello world!"};int arr1[20] = {0};my_memcpy(arr1, arr, 12);printf("%s", arr1);return 0;
}
void * memmove ( void * destination, const void * source, size_t num );
模拟实现>
void* my_memmove(void* dest, const void* src, size_t num)
{void* ret = dest;assert(dest && src);if (dest < src){while (num--){*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{while (num--){*((char*)dest + num) = *((char*)src + num);}}return ret;
}int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9 };my_memmove(arr+2, arr, 16);int i = 0;for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++){printf("%d ", arr[i]);}return 0;
}
int memcmp ( const void * ptr1, const void * ptr2, size_t num );
代码演示>
int main()
{char buffer1[] = "DWgaOtP12df0";char buffer2[] = "DWGAOTP12DF0";int n;n = memcmp(buffer1, buffer2, sizeof(buffer1));if (n > 0)printf("'%s' is greater than '%s'.\n", buffer1, buffer2);else if (n < 0)printf("'%s' is less than '%s'.\n", buffer1, buffer2);elseprintf("'%s' is the same as '%s'.\n", buffer1, buffer2);return 0;
}
今天我们学习了字符串操作函数(库函数)的理解、实现、模拟,相信大家看完有一定的收获。
种一棵树的最好时间是十年前,其次是现在! 把握好当下,合理利用时间努力奋斗,相信大家一定会实现自己的目标!加油!创作不易,辛苦各位小伙伴们动动小手,三连一波💕💕~~~,本文中也有不足之处,欢迎各位随时私信点评指正!
本节课的代码已上传gitee仓库
下一篇:octomap