C语言 |
您所在的位置:网站首页 › c语言包含字符串寻找字符串 › C语言 |
目录
strtok
strerror
perror
字符分类函数
memcpy
memcpy的模拟实现
memcpy的局限性
memmove
memmove的模拟实现
memcmp
memset
本篇文章我们将继续学习相关字符串函数以及内存函数
strtok
我们先来看strtok库函数的书写格式 char * strtok ( char * str, const char * sep ); //其中str是要被分隔的字符串,sep是一个若干个分隔符组成的字符集合。strtok的具体用法如下: 第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记 strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注:strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改。) strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记, strtok函数将保存它在字符串中的位置 strtok函数的第一个参数为 NULL ,函数将 在同一个字符串中被保存的位置开始,查找下一个标记 如果字符串中不存在更多的标记,则返回 NULL 指针.可能只看抽象的用法解释比较难理解,我们用具体的几个例子来搞清楚这个函数具体怎么使用的和效果如何, int main() { char arr[] = "192.168.3.212"; char buf[30] = { 0}; strcpy(buf, arr); const char* p = "."; char* str = strtok(buf, p);// printf("%s\n", str); str = strtok(NULL, p);// printf("%s\n", str); str = strtok(NULL, p);// printf("%s\n", str); str = strtok(NULL, p);// printf("%s\n", str); return 0; }运行结果如图1 但是我们发现,如果只有几个分隔符还好,如果有成千上万个分隔符的时候,难道我们要写几千几万次重复的内容吗?很显然不可能,所以我们可以用一个巧妙的for循环来解决这个问题。 看下面这段代码: int main() { char arr[] = "[email protected]"; char buf[30] = { 0 }; strcpy(buf, arr); const char* p = "@."; char* str = NULL; for (str = strtok(buf, p); str != NULL; str=strtok(NULL, p)) { printf("%s\n", str); } return 0; }运行结果如图3 由于这个函数的使用范围比较小,所以本篇文章就不对其进行模拟实现了。 strerror我们先来看strerror库函数的书写格式 char * strerror ( int errnum );strerror返回的是一个错误码,每个错误码对应不同的错误信息并将其打印出来 注意,要使用这个库函数需要引用头文件#include 看下面这段代码 int main() { char* p = strerror(0); printf("%s\n", p); p = strerror(1); printf("%s\n", p); p = strerror(2); printf("%s\n", p); p = strerror(3); printf("%s\n", p); return 0; }运行结果如图4 运行结果如图5 根据注释内容,由于我的电脑上并没有这个test.txt文件,所以打开失败,返回NULL,并且error的值就为3(看整形3对应的错误信息) perror这个库函数实际意义上就是prinf+strerror int main() { //打开文件 //打开文件的时候,如果文件的打开方式是"r" //文件存在则打开成功,文件不存在打开失败 //打开文件失败的话,会返回NULL FILE* pf = fopen("test.txt", "r"); if (pf == NULL) { perror("打开文件失败"); //printf + strerror return ; } //读写文件 //... //关闭文件 fclose(pf); pf = NULL; return 0; }运行结果和图5一样,如图6 我们来看一些字符分类函数 打印结果如图 运行结果如下 讲到这里,我们回过去思考一个问题,我们前面学的内容都是对char类型字符串进行相关操作,那么如果是一个整型数组,浮点型数组又该怎么办呢?貌似用str为前缀的相关函数就行不通了,所以为了操作这些类型的数组,我们引入了使用范围更为广泛的内存函数 memcpy我们还是先来看memcpy库函数的书写格式 void * memcpy ( void * destination, const void * source, size_t num );具体的使用方法如下 函数memcpy从source的位置开始向后复制num个字节的数据到destination的内存位置 这个函数在遇到 ‘\0’ 的时候并不会停下来 如果source和destination有任何的重叠,复制的结果都是未定义的(这个后面和memmove比较再来讲) 我们 先来以复制一个整型数组为例,看下面这段代码 void test1() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[8] = { 0 }; //把arr1中的前5个数据拷贝到arr2中 memcpy(arr2, arr1, 20); }这里要特别注意! 这个size_t num是无符号整型,单位是字节!!! 因为这个函数并不知道我们传递的参数是什么类型,所以如果我们传递的是整型数组,整型是4个字节,所以如果要拷贝五个数据,就应该输入4*5=20. memcpy的模拟实现我们现在来模拟实现一下memcpy库函数的相关功能,看下面这段代码: 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; }因为memcpy的创建者并不知道我们这些使用者将来会用memcpy来操作什么类型的数据,所以用void*来书写,由于size_t num的单位是字节,为了方便循环次数对的上,我们就将dest和src指针都强制类型转换为char类型。 memcpy的局限性我们发现,当用memcpy来拷贝同一数组的元素时可能会出现bug,我们通过图来分析 memmove库函数在memcpy函数的基础上又有优势,和memcpy的差别就是memmove函数处理的源内存块和目标内存块是可以重叠的。如果源空间和目标空间出现重叠,就得使用memmove函数处理。 比如下面这段代码 void test2() { int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 }; memmove(arr1+2, arr1, 20); for (int i = 0; i //前->后 while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; } } else { //后->前 while (num--) { *((char*)dest + num) = *((char*)src + num); //num越来越小,从后向前拷贝 } } return ret; }所以我们来总结一下 1. C语言中,memcpy拷贝不重叠内存 2. 重叠的就交给memmove 3. 在功能性上memmove>memcpy。 memcmp类比strcmp,memcmp就是一个可以实现比较任意类型数据是否相等功能的库函数 举个例子 void test5() { int arr1[] = { 1,2,3,4,7};//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 07 00 00 00 int arr2[] = { 1,2,3,4,6};//01 00 00 00 02 00 00 00 03 00 00 00 04 00 00 00 06 00 00 00 int ret = memcmp(arr1, arr2, 16); printf("%d\n", ret); }如果比较的是16个字节,那么就是相等的,但如果比较的是17个字节 07是大于06的,所以返回值是大于0的(类比strcmp的返回值) memset我们还是先来看书写格式 void *memset(void *s, int c, unsigned long n);其中s是指向要操作的数组或字符串的首元素地址,c是要修改的值,n是要修改的字节长度。 看下面这段代码 void test6() { char arr[] = "hello world"; memset(arr, 'x', 5); printf("%s\n", arr); }打印结果如图9 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |