>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.模拟实现strcmp:
思路:通过字符在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;
}
6.模拟实现strchr:
Strchr:查找字符串中首次出现字符c的位置。如果字符出现多次,以第一次找到的位置为主
#include<stdio.h>
#include<Windows.h>
#include<assert.h>
char *my_strchr(const char*str, int c)
{
assert(str);
while (*str){
if (*str == (char)c){
return (char*)str;
}
str++;
}
return 0;
}
int main(){
char *str1 = "abcdef";
char c = 'd';
char *ret = my_strchr(str1,c); //返回的是当前字符的位置
printf("%d\n", ret-str1+1); //找到字符的位置减去首元素的位置加1就是当前字符在字符串中的位置
system("pause");
return 0;
}