写点什么

C 语言字符串与内存库函数的介绍与模拟实现

作者:未见花闻
  • 2022 年 6 月 22 日
  • 本文字数:10182 字

    阅读完需:约 33 分钟

🍃1.C 语言字符库函数

所在头文件:string.h模拟实现预处理编码:


#include <stdio.h>#include <assert.h>typedef unsigned int size_t;
复制代码

🍂1.1 字符串长度计算函数——strlen

🌿1.1.1 介绍

size_t strlen( const char *string );
复制代码


字符串已经 '\0' 作为结束标志,strlen 函数返回的是在字符串中 '\0' 前面出现的字符个数(不包含 '\0' )。注意:


  1. 传入的字符串一定要包含\0,不然可能会出现结果错误。

  2. 返回值为size_t,为无符号整型。


针对第 2 点的一个易错坑题:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ const char* str1 = "wjhwef"; const char* str2 = "abc"; if (strlen(str2) - strlen(str1) > 0) { printf("str2>str1\n"); } else { printf("srt1>str2\n"); } return 0;}
复制代码


这相信很多同学会这么想,strlen(str2) = 3 , strlen(str1) = 6strlen(str2) - strlen(str1) = -3 < 0,程序输出str1 > str2,那我们来看看究竟是不是这样!运行结果:


str2>str1
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 27476)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


结果不对,程序输出的结果是str2>str1,这是因为函数strlen返回的类型是无符号整型,两个无符号整型进行加减运算还是无符号整型,而无符号整型的范围是大于0的,所以程序会输出str2>str1

🌿1.1.2 模拟实现

这个函数模拟很简单,根据\0为结束标志,计算字符个数即可。


size_t my_strlen(const char* str){  assert(str);//传入指针不能为空
size_t len = 0; while (*str++) { len++; } return len;}
复制代码


以上面那道坑题来测试一下我们模拟实现的函数对不对:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ const char* str1 = "wjhwef"; const char* str2 = "abc"; if (my_strlen(str2) - my_strlen(str1) > 0) { printf("str2>str1\n"); } else { printf("srt1>str2\n"); } return 0;}
复制代码


str2>str1
D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 2468)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


bingo!

🍂1.2 字符串拷贝函数——strcpy,strncpy

🌿1.2.1 介绍

char *strcpy( char *strDestination, const char *strSource );char *strncpy( char *strDest, const char *strSource, size_t count );
复制代码


这两个函数都能实现字符串的拷贝,只不过strncpy多了一个参数count,用来控制拷贝字符串的个数,count是多少字符串就拷贝多少,当然如果超过了源字符串的个数就会在源字符串拷贝完后直接补0直到数量为count个。这两个函数都有两个字符指针,前者是目的地,也就是拷贝存放的地方(目标字符串),后者就是发源地,也就是需要被拷贝的字符串(源字符串)。注意:


  1. 源字符串必须含有\0

  2. 源字符串中的\0会被拷贝到目标字符串。

  3. 目标字符串空间要够大或可变。


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[] = "This is a code!"; char str2[100] = { 0 }; char str3[100] = { 0 }; strcpy(str2, str1); strncpy(str3, str1, 2); printf("%s\n", str2); printf("%s\n", str3); return 0;}
复制代码


This is a code!Th
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 47800)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码

🌿1.2.2 模拟实现

strcpy模拟实现思路:利用结束标志\0,对源字符串遍历,遍历一个就拷贝一个到目标字符串,直到遇到\0,结束遍历,拷贝完成!strncpy模拟实现思路:如果count的值不大于源字符串的字符个数(包括\0),则和strcpy拷贝思路是一样的,但是count大于源字符串个数,源字符串中字符拷贝完后,还得在目标字符串补0


char* my_strcpy(char* des, const char* str){  assert(des);  assert(str);
char* ret = des; while (*des++ = *str++) { ; } return ret;}char* my_strncpy(char* des, const char* str, size_t n){ assert(des && str); char* ret = des; size_t i = 0; for (i = 0; i < n; i++) { if (*str) { *des++ = *str++; } else { *des++ = '\0'; } } *des = '\0'; return ret;}
复制代码


老规矩,测试程序与前面测试库函数的程序一致:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[] = "This is a code!"; char str2[100] = { 0 }; char str3[100] = { 0 }; my_strcpy(str2, str1); my_strncpy(str3, str1, 2); printf("%s\n", str2); printf("%s\n", str3); return 0;}
复制代码


运行结果:


This is a code!Th
D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 43656)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


bingo!

🍂1.3 字符串拼接函数——strcat,strncat

🌿1.3.1 介绍

char *strcat( char *strDestination, const char *strSource );char *strncat( char *strDest, const char *strSource, size_t count );
复制代码


这两个函数的区别和上面说到的strcpystrncpy区别是一样滴!后者多了个参数count,用来控制拼接字符个数,通俗说就是需要拼接多少个字符,你要我拼接几个,我就拼接几个。这里同样有两个字符指针参数,前者是目的地(目标字符串),后者是发源地(源字符串),作用就是将源字符串拼接到目标字符串后面(从目标字符串的\0位置开始拼接)。注意:


  1. 目标字符串和源字符串都必须含有\0

  2. 目标空间必须足够大或可变。

  3. 对于strncat函数,如果参数count大于源字符串个数,只拼接到源字符串的\0


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[100] = "hello!"; char str2[100] = "hello!"; char str3[] = "This is my code!"; strcat(str1, str3); strncat(str2, str3, 4); printf("%s\n", str1); printf("%s\n", str2); return 0;}
复制代码


hello!This is my code!hello!This
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 46248)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码

🌿1.3.2 模拟实现

strcat模拟实现思路:先遍历目标字符串至\0,然后从\0开始将源字符串内容复制到目标字符串!strncat模拟实现思路:同样,先需要遍历到目标字符串\0处,从此处开始拷贝源字符串中前n个字符(最多拷贝整个源字符串,包含\0)。


char* my_strcat(char* des, const char* str){  assert(des && str);  char* ret = des;  //1.找到des最后一个字符  while (*des)  {    des++;  }
//2.将str中字符串拷贝至des末尾 while (*des++ = *str++) { ; } return 0;}
char* my_strncat(char* des, const char* str, size_t n){ assert(des && str); char* ret = des; //1.find end while (*des) { des++; } //2.add size_t i = 0; for (i = 0; i < n && *str; i++) { *des++ = *str++; } *des = '\0'; return ret;}
复制代码


同一个栗子,同一个测试:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[100] = "hello!"; char str2[100] = "hello!"; char str3[] = "This is my code!"; my_strcat(str1, str3); my_strncat(str2, str3, 4); printf("%s\n", str1); printf("%s\n", str2); return 0;}
复制代码


运行结果:


hello!This is my code!hello!This
D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 46452)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


bingo!

🍂1.4 字符串比较函数——strcmp,strncmp

🌿1.4.1 介绍

int strcmp( const char *string1, const char *string2 );int strncmp( const char *string1, const char *string2, size_t count );
复制代码


这两个函数都能比较字符串大小,原理是对应比较每个字符的 ASCII 码大小,如果相同则比较下一个,不同则比较两个字符的 ASCII 码,如果string1大于string2返回正值,string1小于string2返回负值,如果两个字符串每个字符都相等则字符串相等。strncmp相比于strcmp就是控制了比较字符数量多少,count是多少就比较多少个字符,比较字符个数不超过两字符串个数(含\0)较少者。注意:


  1. 第一个字符串大于第二个字符串,则返回大于 0 的数字。

  2. 第一个字符串等于第二个字符串,则返回 0。

  3. 第一个字符串小于第二个字符串,则返回小于 0 的数字。

  4. 比较字符串大小不能直接使用==,需要使用该库函数。


void str_cmp(int ret){  if (ret < 0)  {    printf("前者字符串大!\n");  }  else if (ret == 0)  {    printf("两者字符串相等!\n");  }  else  {    printf("前者字符串小!\n");  }}
复制代码


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[] = "wjhw"; char str2[] = "csdn"; char str3[] = "wjhw"; int ret1 = strcmp(str1, str2); int ret2 = strcmp(str1, str3); int ret3 = strncmp(str1, str2, 2); int ret4 = strncmp(str1, str3, 2); str_cmp(ret1); str_cmp(ret2); str_cmp(ret3); str_cmp(ret4); return 0;}
复制代码


前者字符串小!两者字符串相等!前者字符串小!两者字符串相等!
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 45136)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码

🌿1.4.2 模拟实现

strcmp模拟实现思路:分别从两个字符串第一个字符开始同时遍历两个字符串中的字符,如果字符相等就比较下一个,中间如果存在两字符不相等,结束遍历。最终结果返回两者 ASCII 码差值(前者减后者)。strncmp模拟实现思路:相比于strcmp的模拟实现,该函数多了个比较字符个数n,比较的思路是一样的,但是需要控制字符比较字符的个数,n为几就在第几个字符处返回两者 ASCII 码差值(前者减后者),如果n比两个字符串长度较小者大(含\0)其实和strcmp实现是一样的。


int my_strcmp(const char* str1, const char* str2){  assert(str1 && str2);
while (*str1 && *str2 && *str1 == *str2) { str1++; str2++; }
return (*str1 - *str2);}
int my_strncmp(const char* str1, const char* str2, size_t n){ assert(*str1 && *str2);
size_t i = 0; for (i = 0; i < n - 1 && *str1 && *str2; i++) { if (*str1 != *str2) break; str1++; str2++; }
return (*str1 - *str2);}
复制代码


还是使用同一个测试:


void str_cmp(int ret){  if (ret < 0)  {    printf("前者字符串大!\n");  }  else if (ret == 0)  {    printf("两者字符串相等!\n");  }  else  {    printf("前者字符串小!\n");  }}
复制代码


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[] = "wjhw"; char str2[] = "csdn"; char str3[] = "wjhw"; int ret1 = my_strcmp(str1, str2); int ret2 = my_strcmp(str1, str3); int ret3 = my_strncmp(str1, str2, 2); int ret4 = my_strncmp(str1, str3, 2); str_cmp(ret1); str_cmp(ret2); str_cmp(ret3); str_cmp(ret4); return 0;}
复制代码


运行结果:


前者字符串小!两者字符串相等!前者字符串小!两者字符串相等!
D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 44948)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


bingo!

🍂1.5 字符串查找函数——strstr

🌿1.5.1 介绍

char *strstr( const char *string, const char *strCharSet );
复制代码


这个函数能够实现字符串的查找,如果字符串strCharSetstring出现,则返回string中第一次出现该字符串的首地址,否则返回NULL


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[] = "This is my code!"; char str2[] = "codee"; char str3[] = "code"; char* ret1 = strstr(str1, str2); char* ret2 = strstr(str1, str3); if (ret1) printf("%s\n", ret1); else printf("没找到!\n"); if (ret2) printf("%s\n", ret2); else printf("没找到!\n"); return 0;}
复制代码


没找到!code!
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 49140)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码

🌿1.5.2 模拟实现

strstr模拟实现思路:要在字符串str1中找到str2字符串,首先得在str1中找到与str2首字符相同的字符,找到这个字符之后,就是对str2后面的字符进行逐个比较,如果在后续逐个比较过程中出现了不同的字符,这时候就需要str1返回到之前刚开始对字符比较的地方,str2需要返回到首字符,然后重复执行该操作。当然如果在后续逐个比较过程中,str2指向的字符为\0这就代表在str1中找到了str2这个字符串,这时候就可以返回str2首字符对应于str1所在的地址。还有一种情况后续遍历过程中str1指向的字符为\0,这就表示在str1中找不到str2这个字符串,直接返回NULL即可。




char* my_strstr(const char* str1, const char* str2){  assert(str1 && str2);  if (*str2 == '\0')    return (char*)str1;//如果str2位\0,返回str1首地址  const char* s1;  const char* s2;  const char* p = str1;  while (*p)  {    s1 = p;    s2 = str2;
while (*s1 && *s2 && *s1 == *s2) { s1++; s2++; }
if (*s2 == '\0') { return (char*)p; } if (*s1 == '\0') { return NULL; } p++; } return NULL;}
复制代码


同一个测试用例:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ char str1[] = "This is my code!"; char str2[] = "codee"; char str3[] = "code"; char* ret1 = my_strstr(str1, str2); char* ret2 = my_strstr(str1, str3); if (ret1) printf("%s\n", ret1); else printf("没找到!\n"); if (ret2) printf("%s\n", ret2); else printf("没找到!\n"); return 0;}
复制代码


运行结果:


没找到!code!
D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 45952)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


bingo!

🍂1.6 了解字符串函数 strtok,strerror

char *strtok( char *strToken, const char *strDelimit );char *strerror( int errnum );
复制代码


strtok函数可以对字符串进行切分。字符串strToken是被切分对象,字符串strDelimit中包含分隔符号。


  1. strDelimit参数是个字符串,定义了用作分隔符的字符集合。

  2. 第一个参数指定一个字符串,它包含了 0 个或者多个由strDelimit字符串中一个或者多个分隔符分割的标记。

  3. strtok函数找到strToken中的首个分隔符,并将其用\0替代,返回分隔符前一个字符串的地址。(注:strtok 函数会改变被操作的字符串,所以在使用 strtok 函数切分的字符串一般都是临时拷贝的内容并且可修改。)

  4. strtok函数的第一个参数不为 NULL ,函数将找到strToken中首个分隔符,strtok函数会记忆该分隔符后一个字符的位置。

  5. strtok函数的第一个参数为NULL,函数将在同一个字符串中被记忆的位置开始,查找下一个分隔符。

  6. 如果字符串中不存在更多的标记,则返回 NULL 指针。


#include <stdio.h>#include <string.h>int main(){  char str[] = "- This, a sample string.";  char* pch;  printf("Splitting string \"%s\" into tokens:\n", str);  pch = strtok(str, " ,.-");  while (pch != NULL)  {    printf("%s\n", pch);    pch = strtok(NULL, " ,.-");  }  return 0;}
复制代码


运行结果:


Splitting string "- This, a sample string." into tokens:Thisasamplestring
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 10704)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


#include <stdio.h>#include <string.h>int main(){  char* p = "weijianhuawen@163.com";  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);  }}
复制代码


运行结果:


weijianhuawen163com
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 5032)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


strerror函数从内部数组中搜索错误号 errnum,并返回一个指向错误消息字符串的指针。strerror 生成的错误字符串取决于开发平台和编译器。


#include <stdio.h>#include <string.h>#include <errno.h>//必须包含的头文件int main(){  FILE* pFile;  pFile = fopen("unexist.ent", "r");  if (pFile == NULL)    printf("Error opening file unexist.ent: %s\n", strerror(errno));  //errno: Last error number  return 0;}
复制代码


运行结果:


Error opening file unexist.ent: No such file or directory
D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 12960)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码

🍃2.C 语言内存库函数

🍂2.1 内存拷贝函数——memcpy

🌿2.1.1 介绍

void *memcpy( void *dest, const void *src, size_t count );
复制代码


该函数与字符串拷贝函数strncpy非常的相似,唯一的区别就是strncpy只能拷贝字符串,memcpy函数能够拷贝任何数据类型,它进行的是内存的拷贝,是将源内存src储存的内容拷贝到目标内存dest中。


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ int arr1[10] = { 22,33,44,55,66,77,88,99,86,28 }; int arr2[5] = { 0 }; memcpy(arr2, arr1, 12); int i = 0; int size = sizeof(arr2) / sizeof(arr2[0]); for (i = 0; i < size; i++) { printf("%d ", arr2[i]); } return 0;}
复制代码


22 33 44 0 0D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 17588)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码

🌿2.1.2 模拟实现

memcpy模拟实现思路:将传入的两个指针参数强制转换为char*类型进行拷贝操作,操作过程与strncpy是一模一样的。要注意的是,memcpy函数在 C 标准中并没有要求能够实现含重复地址的拷贝,因为如果出现含重复的地址,拷贝过程中可能会将需要的数据被覆盖的情况,如果需要完成该任务,需要靠memmove函数实现,下面的内容会介绍该函数。


void* my_memcpy(void* des, const void* src, size_t n){  assert(des && src);
void* ret = des;
while (n--) { *(char*)des = *(char*)src; (char*)des = (char*)des + 1; (char*)src = (char*)src + 1; } return ret;}
复制代码


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ int arr1[10] = { 22,33,44,55,66,77,88,99,86,28 }; int arr2[5] = { 0 }; my_memcpy(arr2, arr1, 12); int i = 0; int size = sizeof(arr2) / sizeof(arr2[0]); for (i = 0; i < size; i++) { printf("%d ", arr2[i]); } return 0;}
复制代码


运行结果:


22 33 44 0 0D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 17244)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


bingo!

🍂2.2 内存移动函数——memmove

🌿2.2.1 介绍

void *memmove( void *dest, const void *src, size_t count );
复制代码


memmove函数相比于memcpy函数能够很好的实现重复地址拷贝,因为该函数考虑了在含有重复地址情况下,可用数据被覆盖的问题,并针对此问题作出了解决方案,在模拟实现该函数时我将会介绍该方案。


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ int arr1[10] = { 22,33,44,55,66,77,88,99,86,28 }; int arr2[3] = { 0 }; memmove(arr1 + 2, arr1, 16); int i = 0; int size = sizeof(arr1) / sizeof(arr1[0]); for (i = 0; i < size; i++) { printf("%d ", arr1[i]); } return 0;}
复制代码


22 33 22 33 44 55 88 99 86 28D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 8980)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码

🌿2.2.2 模拟实现

在介绍该函数模拟实现之前我们来看看使用前面模拟的my_memcpy函数来运行上面测试memmove函数:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ int arr1[10] = { 22,33,44,55,66,77,88,99,86,28 }; int arr2[3] = { 0 }; my_memcpy(arr1 + 2, arr1, 16); int i = 0; int size = sizeof(arr1) / sizeof(arr1[0]); for (i = 0; i < size; i++) { printf("%d ", arr1[i]); } return 0;}
复制代码


运行结果:


22 33 22 33 22 33 88 99 86 28D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 18272)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


我们发现数据44 55这两个数据被22 33覆盖了,这不能说我们模拟实现的内存拷贝函数就错了,因为该函数的任务并不需要实现重复地址数据的拷贝,这个任务是memmove的任务!当然有部分编译器下memcpy函数能实现该任务,但是并不是所有编译器下的memcpy函数都能完成该任务。通过这个栗子,我们发现要实现memmove函数,就需要在memcpy的基础上解决数据覆盖的情况。memmove函数模拟实现:根据目的地与发源地的相对位置,采取不同的拷贝方案!







void* my_memmove(void* des, const void* src, size_t n){  assert(des && src);  void* ret = des;
if (des < src) { //前到后拷贝 while (n--) { *(char*)des = *(char*)src; (char*)des = (char*)des + 1; (char*)src = (char*)src + 1; } } else { //后到前拷贝
while (n--) { *((char*)des + n) = *((char*)src + n); } } return des;}
复制代码


同一个测试案例:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ int arr1[10] = { 22,33,44,55,66,77,88,99,86,28 }; int arr2[3] = { 0 }; my_memmove(arr1 + 2, arr1, 16); int i = 0; int size = sizeof(arr1) / sizeof(arr1[0]); for (i = 0; i < size; i++) { printf("%d ", arr1[i]); } return 0;}
复制代码


运行结果:


22 33 22 33 44 55 88 99 86 28D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 25284)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


bingo!

🍂2.3 内存比较函数——memcmp

🌿2.3.1 介绍

int memcmp( const void *buf1, const void *buf2, size_t count );
复制代码


memcmp函数和strncmp也非常相似,前者能比较所有的数据类型,通过内存中每个字节每个字节地比较,后者只能比较字符串。


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ int arr1[] = { 1, 3, 4, 6 ,9 }; int arr2[] = { 1, 3, 9, 8 ,0 }; int ret = memcmp(arr1, arr2, 16); printf("%d ", ret); return 0;}
复制代码


-1D:\gtee\C-learning-code-and-project\test_918\Debug\test_918.exe (进程 25456)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


程序输出的结果小于 0,表示第一个数组小于第二个数组。

🌿2.3.2 模拟实现

memcmp函数和strncmp也非常相似,前者能比较所有的数据类型,通过内存中每个字节每个字节地比较,后者只能比较字符串。将该函数传入的两个参数强制转换成char*,然后进行每字节比较,过程与strncmp模拟思路一模一样!


int my_memcmp(const void* src1, const void* src2, size_t n){  assert(src1 && src2);
while (--n) { if (*(char*)src1 != *(char*)src2) { break; } (char*)src1 = (char*)src1 + 1; (char*)src2 = (char*)src2 + 1; } return *(char*)src1 - *(char*)src2;}
复制代码


同一个测试用例:


#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>#include <string.h>int main(){ int arr1[] = { 1, 3, 4, 6 ,9 }; int arr2[] = { 1, 3, 9, 8 ,0 }; int ret = my_memcmp(arr1, arr2, 16); printf("%d ", ret); return 0;}
复制代码


运行结果:


-5D:\gtee\C-learning-code-and-project\imitate str and mem\Debug\imitate str and mem.exe (进程 24812)已退出,代码为 0。按任意键关闭此窗口. . .
复制代码


结果同样小于 0,表示第一个数组小于第二个数组。bingo!

发布于: 2022 年 06 月 22 日阅读数: 4
用户头像

未见花闻

关注

坚持+努力=诗+远方 2021.11.15 加入

一位热爱技术热爱分享的大学生!

评论

发布
暂无评论
C语言字符串与内存库函数的介绍与模拟实现_6月月更_未见花闻_InfoQ写作社区