一,字符串处理函数
上述就是几个常见的字符串处理函数,我们来模拟实现的目的就是为了以后不能使用这种函数的时候能自己写,主要是学习方法。
一,strlen的三种形式
1.计数器
#define _CRT_SECURE_NO_WARNINGS 1 //计数器 #include<stdio.h> #include<assert.h> int my_strlen(const char* dest) { int count = 0; assert(dest); while (*dest++) { count++; } return count; } int main() { char arr[] = "hello"; printf("%d",my_strlen(arr)); return 0; }
2.递归
#define _CRT_SECURE_NO_WARNINGS 1 //递归 #include<stdio.h> #include<assert.h> int my_strlen(const char* dest) { assert(dest); if (!* dest) return 0; return 1 + my_strlen( dest + 1); } int main() { char arr[] = "hello"; printf("%d", my_strlen(arr)); return 0; }
3.指针-指针
#define _CRT_SECURE_NO_WARNINGS 1 //指针-指针 #include<stdio.h> #include<assert.h> int my_strlen(const char* dest) { assert(dest); const char* p = dest; while (*p) { p++; } return p - dest; } int main() { char arr[] = "hello"; printf("%d", my_strlen(arr)); return 0; }
二,strcmp模拟实现
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<assert.h> int my_strcmp(const char* arr1, const char* arr2) { assert(arr1 && arr2); while (*arr1 == *arr2 ) { arr1++; arr2++; if(*arr2=='\0') return 0; } return *arr1 - *arr2; } int main() { char arr1[20] = "hello "; char arr2[] = "world"; int ret=my_strcmp(arr1, arr2); if (ret == 0) { printf("arr1=arr2"); } if (ret < 0) { printf("arr1<arr2"); } if (ret > 0) { printf("arr1>arr2"); } return 0; }
三,strcat模拟实现
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<assert.h> char* my_strcat(char* dest, const char* res) { assert(dest && res); char* p = dest; while (*dest) { dest++; } while (*dest++=*res++) { ; } return p; } int main() { char arr1[20] = "hello "; char arr2[] = "world "; printf("%s\n", my_strcat(arr1, arr2)); return 0; }
四,strcpy模拟实现
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<assert.h> char* my_strcpy(char* dest,char * src) { assert(dest && src); char* p = dest; while (*dest++ = *src++); return p; } int main() { char arr1[20] = "hello "; char arr2[] = "world"; printf("%s\n",my_strcpy(arr1, arr2) ); return 0; }
五,strstr模拟实现
#define _CRT_SECURE_NO_WARNINGS 1 //模拟实现strstr函数 //在arr1中找是否包含arr2数组 #include<stdio.h> #include<assert.h> char* my_strstr(const char* str1, const char* str2) { assert(str1 && str2); const char* s1 = NULL; const char* s2 = NULL; //如果*str2=0;则需要返回str1的地址,所以str1的地址不能变 char* cp = str1; if (*str2 == '\0') { //由于我定义的是const类型的,所以返回时需要强制转换为char*类型 return (char*)str1; } while (*cp) { s1 = cp; s2 = str2; while (*s1 && *s2 && (*s1 == *s2)) { s1++; s2++; } //这里必定是由上面的while中跳出来的,因为上面已经筛选过了,当*s2结束,返回当前cp的地址 if (*s2 == '\0') return (char*)cp; cp++; } //要么是找不到,*s2为0,程序直接结束,要么也是找不到,直到*cp为0,返回空指针,要么因为*s1为0,返回空指针 return NULL; } int main() { char arr1[] = "abdjkhgio"; char arr2[] = "jk"; char* ret = my_strstr(arr1, arr2); if (ret == NULL) { printf("No found!"); } else { printf("%s", ret); } return 0; }
六,strtok实现
#define _CRT_SECURE_NO_WARNINGS 1 //strtok函数实现 #include<stdio.h> #include<string.h> int main() { char arr[] = "abc@woaini.dd"; char* p = "@."; char tmp[20] = {0}; strcpy(tmp, arr); char* ret = NULL; //strtok的返回值是遇到标志的地址,所以之后都是从null开始,函数将标志改为了\0 for (ret = strtok(tmp, p); ret; ret = strtok(NULL, p)) { printf("%s\n", ret); } return 0; }
二,内存处理函数
一,模拟实现memcpy
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<assert.h> //num指的是字节长度 void* my_memcpy(void* dest, const void* src, size_t num) { void* ret = dest; assert(dest && src); //这个函数是一个字节一个字节的传,为了能让多种数据都能使用该函数,强制转换为char*类型 while (num--) { *(char*)dest = *(char*)src; dest = (char*)dest + 1; src = (char*)src + 1; //*(char*)dest++=*(char*)src++; //这种方法是错的 ,解引用强制转换了之后,在进行++操作时,强制转换的作用已经不存在了 } return ret; } int main() { int arr1[] = { 1,2,3,4,5,6,7,8,9,10 }; int arr2[10] = { 0 }; //arr2要够长,不然容易栈溢出。 my_memcpy(arr2, arr1, 20); for(int i=0;i<5;i++) printf("%d\n", *(arr2+i)); return 0; }
二,模拟实现memmove
#define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<assert.h> 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 }; my_memmove(arr1 + 2, arr1, 20); return 0; }
注意事项:
memcpy函数应该拷贝不重叠的内存
memmove函数可以处理内存重叠的情况。
memcpy按C语言的要求只能实现拷贝不重叠的内存,但是VS中可以实现拷贝重叠的内存。