各位csdn的友友们好,上次阿博给大家讲了一些简单的字符串函数的功能和模拟实现,今天就和阿博一起再上一个台阶继续拿捏它们
文章目录
- 1.strstr的功能介绍
- 2.strstr函数的模拟实现
- 3.strtok的功能介绍
- 4.strerror和perror的功能介绍
- 5.memcpy的功能介绍
- 6.memcpy函数的模拟实现
- 7.内存重叠
- 8.memmove的功能介绍
- 9.memmove函数的模拟实现
- 10.memcmp的功能介绍
- 11.memcmp函数的模拟实现
- 12.memset的功能介绍
1.strstr的功能介绍
2.strstr函数的模拟实现
3.strtok的功能介绍
4.strerror和perror的功能介绍
5.memcpy的功能介绍
6.memcpy函数的模拟实现
7.内存重叠
8.memmove的功能介绍
9.memmove函数的模拟实现
10.memcmp的功能介绍
11.memcmp函数的模拟实现
12.memset的功能介绍
1.strstr的功能介绍
它的功能就是在str1中找str2,而且是第一次出现的位置,如果没有找到,则返回的是空指针,如果找到了str2,并且找到多次,它只返回第一次出现的地址
代码测试
#include#includeintmain(){char arr1[] = "abcdebcdf";char arr2[] = "bcd";//char arr2[]="bcq";char*p= strstr(arr1, arr2);if (p == NULL){printf("找不到\n");}elseprintf("%s\n", p);return0;}
这就是strstr相关的功能了,如果找到了,友友们一定要切记返回的是第一次出现的地址.
这里阿博再给友友们拓展一些相类似的函数
1.strchr
这个函数的功能是在一个字符串中找字符第一次出现的位置.
2.strrchr
这个函数的功能是找一个字符在字符串中最后一次出现的位置.
2.strstr函数的模拟实现
逻辑分析
代码实现
#include#include#includechar* my_strstr(const char* str1, const char* str2){assert(str1 && str2);char* s1 = NULL;char* s2 = NULL;char* cp = (char*)str1;while (*cp){s1 = cp;s2 = (char*)str2;while (*s1 && *s2 && *s1 == *s2){s1++;s2++;}if (*s2 == '\0'){returncp;}cp++;}returnNULL;}intmain(){char arr1[] = "abcdebcdf";//char arr2[] = "bcd";char arr2[]="bcd";char*p= my_strstr(arr1, arr2);if (p == NULL){printf("找不到\n");}elseprintf("%s\n", p);return0;}
3.strtok的功能介绍
这里阿博给友友们传输一些内功
1.delimiters参数是个字符串,定义了用作分隔符的字符集合
2.第一个参数指定一个字符串,它包含了0个或者多个由sep字符串中一个或者多个分隔符分割的标记.
3.strtok函数找到str中的下一个标记,并将其用 \0 结尾,返回一个指向这个标记的指针。(注strtok函数会改变被操作的字符串,所以在使用strtok函数切分的字符串一般都是临时拷贝的内容并且可修改
4.strtok函数的第一个参数不为 NULL ,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置.
5.strtok函数的第一个参数为 NULL ,函数将在同一个字符串中被保存的位置开始,查找下一个标记。如果字符串中不存在更多的标记,则返回 NULL 指针.
代码测试1
//strtok的功能介绍int main(){char arr[] = "i@love.you";char buf[30] = { 0 };strcpy(buf, arr);//这里是在buf文件里面操作,防止原文件被改变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);return0;}
这种写法没有错,但是如果分隔符比较多的话,我们需要写很多行代码,所以我们换一种方法.
代码测试2
int main(){char arr[] = "i@love.you";char buf[30] = { 0 };strcpy(buf, arr);//这里是在buf文件里面操作,防止原文件被改变const char* p = "@.";char* str = NULL;for (str = strtok(buf, p); str != NULL; str = strtok(NULL, p))//第一次我们传buf的地址,然后第二次,第三次,第四次......我们都传空指针的地址,到最后没有分割符了,str为空,跳出循环.{printf("%s\n", str);}return0;}
4.strerror和perror的功能介绍
strerror
代码测试
intmain(){FILE* pf = fopen("text.txt", "r");if (pf == NULL){printf("打开文件失败,原因是:%s\n", strerror(errno));return 1;}fclose(pf);pf = NULL;return0;}
这里阿博给友友们解答一下疑惑,其实c语言的库函数在调用失败的时候,会将一个错误码存放在一个叫:errno的变量中,当我们想知道调用库函数的时候产生了什么错误信息,就可以将errno中的错误码翻译成错误信息.
友友们注意,我们一定要把这个文件扩展名给打开,这样我们就可以完整的看到文件名了.
perror
代码测试
intmain(){FILE* pf = fopen("text.txt", "r");if (pf == NULL){perror("打开文件失败"); //其实就可以把perror抽象的理解成printf+serrorreturn 1;}fclose(pf);pf = NULL;return0;}
5.memcpy的功能介绍
代码测试
void test1(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };memcpy(arr2, arr1, 20); //注意这里是字节个数,不是元素个数int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}}void test2(){float arr1[] = { 1.0f,2.0f,3.0f,4.0f,5.0f };float arr2[10] = { 0 };memcpy(arr2, arr1, 12);int i = 0;for (i = 0; i < 10; i++)//注意这里是字节个数{printf("%f ", arr2[i]);}}intmain(){//test1();test2();return0;}
6.memcpy函数的模拟实现
代码实现
#includevoid* my_memcpy(void* dest, const void* src, size_t num){assert(dest && src);void* ret = dest;while (num--){//*dest = *src;//dest++;//src++; //err*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;}void test1(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };int arr2[10] = { 0 };my_memcpy(arr2, arr1, 20); //注意这里是字节个数,不是元素个数int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr2[i]);}}
️️️友友们注意虽然void*的指针可以接收任意类型的数据,但是这种指针不能直接解引用和加减运算.️️️
7.内存重叠
代码测试
#includevoid* my_memcpy(void* dest, const void* src, size_t num){assert(dest && src);void* ret = dest;while (num--){//*dest = *src;//dest++;//src++; //err*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}return ret;}void test1(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };// 1,2,1,2,3,4,5,8,9,10 我们期待的结果my_memcpy(arr1+2, arr1, 20); //注意这里是字节个数,不是元素个数int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}}
8.memmove的功能介绍
代码测试
void test1(){int arr1[] = { 1,2,3,4,5,6,7,8,9,10 };// 1,2,1,2,3,4,5,8,9,10 我们期待的结果memmove(arr1+2, arr1, 20); //注意这里是字节个数,不是元素个数int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr1[i]);}}
9.memmove函数的模拟实现
逻辑分析
代码实现
#includevoid* my_memmove(void* dest, const void* src, size_t num){assert(dest && src);void* ret = dest;if (dest < src){while (num--){//*dest = *src;//dest++;//src++; //err*(char*)dest = *(char*)src;dest = (char*)dest + 1;src = (char*)src + 1;}}else{while (num--){*((char*)dest + num) = *((char*)src + num); //这里的num已经是19了}}return ret;}
10.memcmp的功能介绍
代码测试
void test3(){int arr1[] = { 1,2,3,4,7 };int arr2[] = { 1,2,3,4,6 };int ret = memcmp(arr1, arr2, 17);printf("%d\n", ret);}
11.memcmp函数的模拟实现
代码实现
#includeint my_memcmp(const void* str1, const void* str2,size_t num){assert(str1 && str2);while (num--){if(*(char*)str1!=*(char*)str2)return*(char*)str1 - *(char*)str2;str1 = (char*)str1 + 1;str2 = (char*)str2 + 1;}return 0;}void test3(){int arr1[] = { 1,2,3,4,7 };int arr2[] = { 1,2,3,4,6 };int ret = my_memcmp(arr1, arr2, 16);printf("%d\n", ret);}intmain(){//test1();//test2();test3();return0;}
12.memset的功能介绍
代码实现
voidtest4(){char arr[] = "hello world";memset(arr, 'x', 5);printf("%s\n", arr);}
友友们注意memset是以字节为单位设置的
错误示范
void test5(){int arr[10] = { 0 };memset(arr, 1, sizeof(arr));// 01010101,这种写法无法将每个元素设置为1int i = 0;for (i = 0; i < 10; i++){printf("%d ", arr[i]);}}
好了友友们,本期创作到这里就告一段落了,如果感觉有帮助的话,可以给阿博点个关注哦,后续会继续给友友们带来一些新的干货