哪里有彩虹告诉我,能不能把我的愿望还给我..........................................................................
目录
前言
介绍有关C语言库函数相关的知识。
一、【操作字符串】
1.1【strlen函数】
函数介绍
1.字符串已经 '\0' 作为结束标志,strlen函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。
2.参数指向的字符串必须要以 '\0' 结束。
3.注意函数的返回值为size_t,是无符号的( 易错 )4.使用时,注意包含头文件——> <string.h>
参数介绍
1.const char * str是字符串首字符的地址,从它开始,向后统计字符个数,直到遇到‘\0’停下
2.size_t是库函数的返回类型,因为长度并没有负数,所以是无符号整数。
使用示例
#include <string.h> int main() { char arr[] = "abcdef"; size_t ret=strlen(arr); printf("%u\n", ret); return 0; }
注意事项
1.由于返回类型为size_t看下面的代码:
#include <string.h> int main() { const char* str1 = "abcdef"; const char* str2 = "bbb"; if (strlen(str2) - strlen(str1) > 0) { printf(">\n"); } else { printf("<=\n"); } return 0; }
模拟实现
计数器形式:
//计数器方式 int my_strlen(const char * str) { int count = 0; while(*str) { count++; str++; } return count; }
递归形式:
int my_strlen(const char * str) { if(*str == '\0') return 0; else return 1+my_strlen(str+1); }
指针-指针:
int my_strlen(char *s) { char *p = s; while(*p != ‘\0’ ) p++; return p-s; }
1.2【strcpy函数】
函数介绍
会将源字符串的内容拷贝到目标字符串的空间当中。
参数介绍
char * 是返回类型,返回的是,目标空间的起始地址
char *destination 是目标空间的起始地址,char * source 是源字符串的起始地址
使用示例
int main() { char arr1[] = "abcdef"; char arr2[20] = { 0 }; strcpy(arr2, arr1); printf("%s\n", arr2); return 0; }
注意事项
1.源字符串必须以 '\0' 结束。
2.会将源字符串中的 '\0' 拷贝到目标空间。
3.目标空间必须足够大,以确保能存放源字符串。
4.目标空间必须可变。5.当源字符串和目标空间指向同一块空间时
模拟实现:
#include <assert.h> char* my_strcpy( char* dest,const char* src) { char* ret = dest; assert(dest!=NULL && src!=NULL); while (*src) { *dest = *src; dest++; src++; } return ret; } int main() { char arr1[] = "abcdef"; char arr2[20] = { 0 }; char* p = my_strcpy(arr2, arr1); printf("%s\n", p); return 0; }
【strncpy的介绍】
相较于strcpy多了一个参数 size_t num单位是字节,表示指定拷贝的字节数。
注意
当源空间的大小小于所指定的需要拷贝的大小时,会用'\0'来补充
举例
1.3【strcat函数】
函数介绍
追加源字符串到目的地字符串。目的地中的终止字符‘\0'被源字符串的第一个字符覆盖,并且在由两个字符串串联形成的新字符串的末尾包括一个空字符’\0' .
参数介绍char * 是返回类型,返回的是,目标空间的起始地址
char *destination 是目标空间的起始地址,char * source 是源字符串的起始地址
注意事项
1.目的地和来源不得重叠
就是字符串自己对自己追加,会出现以下问题。
2.源字符串必须以 '\0' 结束。
3.目标空间必须有足够的大,能容纳下源字符串的内容。
4.目标空间必须可修改。使用示例
int main() { char arr1[20] = "hello "; char arr2[] = "world"; strcat(arr1, arr2); printf("%s\n", arr1); }
模拟实现
char* my_strcat(char* dest, const char* src) { char* ret = dest; assert(dest != NULL); assert(src != NULL); while (*dest) { dest++; } while (*src) { *dest = *src; dest++; src++; } return ret; } int main() { char arr1[20] = "hello "; char arr2[] = "world"; my_strcat(arr1, arr2); printf("%s\n", arr1); }
【strncat的介绍】
同strncpy,最后一个参数,用来指定操作的字节数。追加完成后会在字符串末尾补上'\0',不同的是,当源头的内容长度小于指定的字节数时,并不会,用'\0‘进行填充,而是将源头追加完成后就停止了。
举例
1.4【strcmp函数】
函数介绍
比较字符串,字符串1和字符串2 .
此函数开始比较每个字符串的第一个字符。如果它们彼此相等,则继续比较,直到字符不同或到达终止的'\0'。此函数用于对字符进行二进制比较。本质上比较的是字符的ASCII值参数介绍
1.int 是返回类型,
标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字2.const char* str1,const char *str2是参与比较的两个字符串的首字符地址。
注意事项
使用示例
int main() { char arr1[] = "abc"; char arr2[] = "cde"; int ret=strcmp(arr1, arr2); if (ret > 0) { printf(">\n"); } else if (ret < 0) { printf("<\n"); } else printf("==\n"); return 0; }
模拟实现
int my_strcmp(const char* str1, const char* str2) { assert(str1 && str2); while (*str1 == *str2) { if (*str1 == '\0') { return 0; } str1++; str2++; } return (*str1 - *str2); } int main() { char arr1[] = "abc"; char arr2[] = "cde"; int ret=my_strcmp(arr1, arr2); if (ret > 0) { printf(">\n"); } else if (ret < 0) { printf("<\n"); } else printf("==\n"); return 0; }
【strncmp的介绍】
多的参数用来指定比较字节的个数
注意
当指定比较字节数,比两字符串的长度都要大时,只会按照最小字符串的长度,进行比较
举例
1.5【strstr函数】
函数介绍
在str1这个字符串中找str2这个字符串第一次出现的位置,找到了就返回第一次出现的地址,找不到,返回空指针。
参数介绍
返回类型是char *,
str1表示在str1中寻找,str2表示寻找的对象。
使用示例
模拟实现
char* my_strstr(const char* str1, const char* str2) { char* s1 = NULL; char* s2 = NULL; char* cp = str1; 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[] = "abcdef"; char arr2[] = "bcd"; char* p = my_strstr(arr1, arr2); if (p == NULL) { printf("找不到\n"); } else printf("找到了\n"); return 0; }
1.6【strtok函数】
函数介绍
例如这种字符串:
zhangsan1234@qq.com
192.168.32.8
这种带有分隔符(@,.)的字符串,想要提取不带分隔符的部分,就可以使用strtok函数
参数介绍
delimiters参数是个字符串,定义了用作分隔符的字符集合
第一个参数指定一个字符串,它包含了0个或者多个由delimiters字符串中一个或者多个分隔符分割的标记。注意事项
strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。)
strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。
strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。
如果字符串中不存在更多的标记,则返回 NULL 指针。使用示例
int main() { char* p = "zhangsan@123.tech"; const char* sep = ".@"; char arr[30]; char* str = NULL; strcpy(arr, p);//将数据拷贝一份,处理arr数组的内容 for (str = strtok(arr, sep); str != NULL; str = strtok(NULL, sep)) { printf("%s\n", str); } }
1.7【strerror函数】
函数介绍
返回错误码,所对应的错误信息。
参数介绍
返回类型 char* 错误信息首字符的地址
int errnum 错误码
注意事项
其实C语言的库函数,在调用失败时,会将一个错误码存放在一个叫:errno的变量当中,当我们调用过程中发生了什么错误信息,就可以将,errno中的错误码翻译为错误信息。
perror相当于printf+strerror.以后介绍。
1.8【字符分类函数】
二、【操作内存数据】
2.1【memcpy函数】
函数介绍
把num字节大小的数据从source指向的空间拷贝到destion所指向的空间
参数介绍
返回类型是void* ,可以接受任意类型数据的地址。
void* destinaion表示目标空间
void* source表示源头空间
size_t num表示指定拷贝的字节数
使用示例
int main() { int arr1[] = { 1,2,3,4,5,6 }; int arr2[30] = { 0 }; memcpy(arr2, arr1, 20); for (int i = 0; i < 5; i++) { printf("%d", arr2[i]); } }
模拟实现
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() { int arr1[] = { 1,2,3,4,5,6 }; int arr2[30] = { 0 }; my_memcpy(arr2, arr1, 20); for (int i = 0; i < 5; i++) { printf("%d", arr2[i]); } }
注意
这里的arr1和arr2是两块不同的空间,如果是对自身的拷贝比如
1,2,3,4,5拷贝到3,4,5,6,7的位置上
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() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[30] = { 0 }; my_memcpy(arr1+2, arr1, 20); for (int i = 0; i < 10; i++) { printf("%d", arr1[i]); } }
所以在内存重叠时使用memmove来操作。
2.2【memmove函数】
memmove,是升级版的memcpy,跟memcpy很相似,不再过多介绍。
模拟实现
思路
代码:
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 arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[30] = { 0 }; my_memmove(arr1 + 2, arr1, 20); for (int i = 0; i < 10; i++) { printf("%d ", arr1[i]); } }
2.3【memcmp】
函数介绍
用来比较两块空间的大小。
参数介绍
返回类型是int
ptr1,ptr2是参与比较的两块空间的地址,num是指定参与比较的字节数
使用示例
int main() { int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 1,2,3,4,5,6 }; int ret = memcmp(arr1, arr2, 20); printf("%d\n", ret); }
2.4【memset】
函数介绍:
该函数用来将指定空间内容进行替换
参数介绍
void* 是返回类型,返回的是,未替换之前空间的地址
ptr 参与替换的空间的地址
value 想要替换的值
num 参与替换的字节个数。
使用实例
int main() { char arr[] = "hello world"; memset(arr, 'x', 5); printf("%s\n", arr); return 0; }
注意事项
int main() { int arr[10] = { 0 }; memset(arr, 1, 40); for (int i = 0; i < 10; i++) { printf("%p ", arr[i]); } return 0; }
总结
库函数的介绍,就到这里,感谢观看!
.....................................................................................................................当作我最后才明白
————《彩虹》