>str开头的函数只能用于字符数据的操作,遇到NULL'\0'会停止。
>mem开头的函数用于操作内存内容,可以处理NULL.操作的基本单位是字节操作
1.str和mem对比实例:
例如:strcpy和memcpy操作:
>模拟strcpy:
#include<stdio.h> #include<assert.h> #include<windows.h> char *my_strcpy(char *dest, const char *str) { assert(dest); assert(str); while (*dest = *str){ dest++; str++; } return dest; } int main (){ char *p="abcdefg"; char q[20]; //这里q是可变char数组,不能定义为char *类型 my_strcpy(q,p); printf("%s",q); system("pause"); return 0; }
>模拟memcpy:
方法一:通过ascll码表的位置,进行字符的差运算。
#include<stdio.h> #include<Windows.h> void my_memcpy(void *str1,const void *str2,size_t size) { //void类型不能定义变量,void是无类型,不能确定内存的大小,但是void*可以定义,因为指针大小为4,但不能解引用,因为引用后为void void *ret = str1; while (size--){ *(char *)str1 = *(char *)str2; str1=(char *)str1+1; str2=(char *)str2+1; } } int main(){ char c[50] = "abcdefgh"; int size = 3; my_memcpy(c+1, c, size); printf("%s", c); system("pause"); return 0; }
这里会出现内存重叠问题,比如上例中本来的预期结果是:aabcefgh可是运行结果为:aaaaefgh。
对于memcpy总结下面四种出现的情况:以字符串为例。
void my_memcpy(void *dest,const void *src,size_t size)//src要拷贝的字符串,dest目的字符串
在上面四种情况中:(1),(2),(3)拷贝的时候从前往后拷,不会出现覆盖问题。(4)情况拷贝的时候必须从后往前拷,如果从前往后会出现从开始的那个字符其,到要拷贝的长度这段字符串会一直被覆盖。
下面是针对第四种情况:
#include<stdio.h> #include<Windows.h> void my_memcpy(void *dest,const void *src,size_t size) { void *ret = dest; if (dest<=src||(char *)dest>=((char *)src+size)){ while (size--){ *(char *)dest = *(char *)src; dest = (char *)dest + 1; src = (char *)src + 1; } } else{ dest = (char *)dest+size - 1; src = (char *)src+size - 1; while (size--){ *(char *)dest = *(char *)src; dest = (char *)dest - 1; src = (char *)src -1; } } } int main(){ char c[50] = "abcdefgh"; int size = 3; my_memcpy(c+1, c, size); printf("%s", c); system("pause"); return 0; }
那么运行结果就是:aabcdefgh。
总结strcpy和memcpy的区别:
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。 2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。 3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
2.模拟实现strlen:
>直接用计数器实现:
#include<stdio.h> #include<Windows.h> int my_strlen(const char *str) { int count = 0; while (*str){ count++; str++; } return count; } int main(){ char *p= "abcdef"; int ret = my_strlen(p); printf("%d\n", ret); system("pause"); return 0; }
>不创建临时变量的计数器:通过递归
#include<stdio.h> #include<Windows.h> int my_strlen(const char *str) { if (*str=='\0'){ return 0; } else return 1 + my_strlen(str + 1); } int main(){ char *p= "abcdef"; int ret = my_strlen(p); printf("%d\n", ret); system("pause"); return 0; }
>指针-指针:
#include<stdio.h> #include<Windows.h> int my_strlen(const char *str) { char *p = str; //p指向首元素 while (*p != '\0'){ p++; } return p - str; } int main(){ char *p= "abcdef"; int ret = my_strlen(p); printf("%d\n", ret); system("pause"); return 0;
>不用if等判断语句和循环语句;
#include<stdio.h> #include<Windows.h> int my_strlen(const char *str) { return *str ? (1 + my_strlen(str + 1)) : 0; } int main(){ char *p = "abcdef"; int ret = my_strlen(p); printf("%d\n", ret); system("pause"); return 0; }
3.模拟实现strcat:
思路:先使被拼接的字符串(dest)指向'\0',然后将要拼接的字符串(str)依次拷贝到dest后
#include<stdio.h> #include<Windows.h> #include<assert.h> char *my_strcat(char *dest, const char *str) { char *ret =dest; assert(dest); assert(str); while (*dest){ dest++; } while (*dest = *str){ dest++; str++; } return ret; } int main(){ char *str = "abcdef"; char p[30] = "xyz"; char *ret=my_strcat(p, str); printf("%s", ret); system("pause"); return 0; }
4.模拟实现strstr:
思路:在str1中查找str2并返回,str1中str2所在字符串之后的所有字符串。定义一个指针变量s指向str1,然后s与str2中的字符进行比较,如果一直比较到'\0'那么就返回str1,如果比较遇到不相等,则s指向str1的第二个字符重新开始比较。
#include<stdio.h> #include<windows.h> #include<assert.h> char *my_strstr(char *str1, const char *str2) { assert(str1); assert(str2); char *p = (char*)str1; char *q = (char *)str2; char *s = NULL; while (*p){ s = p; q = str2; while (*s&&*q && (*s == *q)){ s++; q++; } if (*q == '\0') return p; p++; } return 0; } int main(){ char *str1 = "abcdefg"; char *str2 = "de"; char *p = my_strstr(str1, str2); printf("%s", p); system("pause"); return 0; }
运行结果:defg
5.模拟实现strcpy:
思路:通过字符在ASCLL表中的位置序号进行差运算比较。
比较的是ASCLL中的位置:如abcg小于abcz
#include<stdio.h> #include<Windows.h> int my_strcmp(const char *str1,const char *str2) { int ret = 0; while ((!(ret = *(unsigned char*)str1 - *(unsigned char*)str2)&&str1)) //一相等为基础 { str1++; str2++; } if (ret > 0) ret = 1; else if (ret<0) ret = -1; return (ret); } int main(){ char *str1 = "abcd"; char *str2 = "abcdg"; int ret = 0; ret = my_strcmp(str1, str2); if (ret==1) printf("str1大于str2\n"); if (ret==-1) printf("str1小于str2\n"); if (ret==0) printf("str1等于str2\n"); system("pause"); return 0; }