strlen函数 strlen函数是用来求字符串长度的,且包含 ‘ \\0 ’,它的参数是一个char* 类型的指针,返回值是一个int类型的整数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <stdio.h> int My_strlen (const char * a) { int szie = 0 ; while (*a != '\0' ) { a++; szie++; } return szie; } int main () { char a[25 ] = { 0 }; scanf ("%s" , &a); printf ("%d 个字符(不包括休止符)\n" , My_strlen(a)); return 0 ; }
模拟函数思路是,指针(a)指向的内容不为 ‘ \\0 ’的时候,计数变量(size)自加,指针(a)自加指向下一个元素,直到遇到 ‘ \\0 ’,返回此时计数变量(szie)的值。
除了以上写法,还有一种递归写法,但是不经常使用,故不做过多介绍。
1 2 3 4 5 6 7 int My_strlen (const char * a) { if (*a != '\0' ) return (1 + My_strlen(a + 1 )); else return 0 ; }
strcpy函数 strcpy是字符串拷贝函数,拷贝当前字符串的内容至目标字符串,它的参数分别是两个char*类型的指针,其中一个为了安全起见使用const修饰,它指向字符串(被拷贝的字符串)的首元素地址,另一个则指向拷贝的字符串首元素地址,该函数的返回值类型是一个char *指针。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 char * My_strcpy (const char * a, char * b) { if (a == NULL || b == NULL ) return NULL ; int i = 0 ; while (a[i] != '\0' ) { b[i] = a[i]; i++; } b[i] = '\0' ; return b; } int main () { char a[20 ] = { 0 }; char b[20 ] = { 0 }; scanf ("%s" , &a); My_strcpy(a, b); printf ("a : %s\n" , a); printf ("b : %s\n" , b); return 0 ; }
这个函数的模拟实现思路也比较简单,利用 [ ]取下标的方式循环进行逐个赋值,最后给拷贝出的字符串手动添加休止符即可。
strcat函数 字符串拼接函数,将两个字符串拼接起来的函数,它有两个参数,char*类型的指向被拼接字符串首元素地址的指针,和使用const修饰的char *类型的指向要拼接字符串首元素地址的指针。返回值是一个char *类型的指向拼接好的字符串首地址的指针。在使用的时候需要注意被拼接的字符串需要足够大的空间来存放拼接好的字符串。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 char * My_strcat (char * a,const char * b) { if (a == NULL || b == NULL ) return NULL ; int end = 0 ; while (a[end] != '\0' ) end++; int i = 0 ; while (b[i] != '\0' ) { a[end + i] = b[i]; i++; } a[end + i] = '\0' ; return a; } int main () { char a[100 ] = { 0 }; char b[100 ] = { 0 }; scanf ("%s" , &a); scanf ("%s" , &b); My_strcat(a, b); printf ("%s\0" , a); return 0 ; }
它的实现思路是,先找到被拼接函数的休止符,并从此开始逐个将拼接字符串的值赋值进去,最后在末尾手动添加休止符。
strcmp函数 字符串比较函数,比较两个字符串的内容(按照字典序),参数是两个由const修饰的char*类型的分别指向两个字符串首地址的指针,返回值是一个int类型的整数。 如果两个字符串内容完全相同,则返回0 如果第一个字符串大于第二个字符串,返回一个大于0的整数,反之返回一个小于0的整数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 int My_strcmp (const char * str1, const char * str2) { assert(str1 != NULL && str2 != NULL ); while (*str1 != '\0' && *str2 != '\0' ) { if (*str1 > *str2) return 1 ; else if (*str1 < *str2) return -1 ; else { str1++; str2++; } } if (*str1 > *str2) return 1 ; else if (*str1 < *str2) return -1 ; else return 0 ; } int main () { char str1[20 ] = { 0 }; char str2[20 ] = { 0 }; scanf ("%s" , &str1); scanf ("%s" , &str2); int ret = My_strcmp(str1, str2); if (ret == 0 ) printf ("str1 = str2\n" ); else if (ret > 0 ) printf ("str1 > str2\n" ); else printf ("str1 < str2\n" ); return 0 ; }
该函数的模拟思路在注释中写出。
strstr函数 这个函数(strstr(str1,str2))用于判断字符串str2是否为str1的子串,如果是则返回一个指向str2在str1中首次出现的指针,如果不是则返回NULL。由于仅仅是判断,所以两个char *类型的参数和char *类型的返回值均使用const修饰。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 const char * My_strstr (const char * str1, const char * str2) { assert(str1 != NULL && str2 != NULL ); if (*str2 == '\0' ) { return NULL ; } const char * black = str1; while (*black != '\0' ) { const char * red = black; const char * sub = str2; while (*red != '\0' && *sub != '\0' && (*red == *sub)) { red++; sub++; } if (*sub == '\0' ) return black; if (*red == '\0' ) return NULL ; black++; } return NULL ; } int main () { char str1[20 ] = { 0 }; char str2[20 ] = { 0 }; scanf ("%s" , &str1); scanf ("%s" , &str2); const char * ret = My_strstr(str1, str2); printf ("%p , %p" , str1, ret); return 0 ; }
该函数的模拟思路是:创建三个指针变量,black、red和sub 其中,black用来记录当前匹配的起始位置,red和sub用来匹配字符串1和字符串2是否相等,如果匹配成功则返回black,未成功则匹配起始位置后移,直到匹配成功或字符串1结束,返回NULL,具体细节在注释中写出。
memcpy函数 内存拷贝函数,将源内存(src)中的内容拷贝到目标内存(dest)中,为了考虑到函数的普适性,此处的dest,src以及返回值均使用void*类型的指针,只指向地址,不考虑所指向元素的大小,还要一个无符号整形的整数作为参数,来表示需要拷贝多少个字节。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 void * My_memcpy (void * dest, void * src, size_t num) { assert(dest != NULL && src != NULL ); size_t i = 0 ; void * ret = dest; for (i = 0 ; i < num; i++) { *(char *)dest = *(char *)src; dest = (char *)dest + 1 ; src = (char *)src + 1 ; } return ret; } int main () { int a[5 ] = { 1 , 2 , 3 , 4 , 5 }; int b[4 ] = { 0 }; My_memcpy(b, a, 16 ); for (int i = 0 ; i < 4 ; i++) printf ("%d " , b[i]); printf ("\n" ); return 0 ; }
具体模拟思路在注释中给出,需要注意的是,它不能处理内存重叠的情况
memmove函数 内存移动函数,将源内存(src)中的内容移动到目标内存(dest),它的功能同memcpy函数相同,但是它可以处理内存重叠的情况(从后往前拷贝)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 void * My_memcpy (void * dest, void * src, size_t num) { assert(dest != NULL && src != NULL ); size_t i = 0 ; void * ret = dest; for (i = 0 ; i < num; i++) { *(char *)dest = *(char *)src; dest = (char *)dest + 1 ; src = (char *)src + 1 ; } return ret; } void * My_memmove (void * dest, void * src,size_t num) { assert(dest != NULL && src != NULL ); char * cdest = (char *)dest; char * csrc = (char *)src; if (csrc < cdest && cdest < csrc + num) { char * pdest = cdest + num - 1 ; char * psrc = csrc + num - 1 ; for (size_t i = 0 ; i < num; i++) { *pdest = *psrc; pdest--; psrc++; } } else { My_memcpy(dest, src, num); } return dest; } int main () { int a[5 ] = { 1 , 2 , 3 , 4 , 5 }; int b[4 ] = { 0 }; My_memmove(b, a, 16 ); for (int i = 0 ; i < 4 ; i++) printf ("%d " , b[i]); printf ("\n" ); return 0 ; }
具体的模拟思路在注释中写出。