模拟实现字符串操作函数(strcpy,strstr,strcat,strcmp,strlen)与内存操作函数(memcpy,memmove)
2016-04-14 08:55
1196 查看
一、字符串操作
strcpy(str1,str2) 复制字符串
strcat(str1,str2) 附加字符串
strlen(str) 取字符串长度
strcmp(str1,str2) 比较字符串
strstr(str1,str2) 查找字符串
1、strcpy
第二个字符串将覆盖掉第一个字符串的所有内容!
<span style="font-size:14px;">#include<stdio.h>
#include<assert.h>
char *my_strcpy(char *dest,char const *src)
{
assert(dest);
assert(src);
char *ret = dest;
while((*dest++ = *src++) != '\0')
{
;
}
return ret;
}
int main()
{
char str1[] = "abxde";
char str2[] = "sdsf";
my_strcpy(str1,str2);
printf("%s\n",str1);
return 0;
}</span>
注意:在定义数组时,字符数组1的字符串长度必须大于或等于字符串2的字符串长度。不能用赋值语句将一个字符串常量或字符数组直接赋给一个字符数组。
2、strcat(str1,str2)
功能:将字符串str2接到字符串str1的后面
将源串strSource添加到目标串strDestination后面, 并在得到的新串后面加上NULL结束符..源串strSource的字符会覆盖目标strDestination后面的结束符NULL. 在字符串的复制或添加过程中没有溢出检查, 所以要保证目标串空间足够大. 不能处理源串与目标串重叠的情况. 函数返回strDestination值.
<span style="font-size:14px;">//模拟实现strcat函数
#include<stdio.h>
#include<assert.h>
char *my_strcat(char *dest,char const *src)
{
assert(dest);
assert(src);
char *ret = dest;
while(*dest) //检测到“\0"
{
dest++;
}
while(*dest++ = *src++)//开始连接
{
;
}
return ret;
}
int main()
{
char arr1[] = "hello,";
char arr2[] = "world";
my_strcat(arr1,arr2);
printf("%s\n",arr1);
return 0;
} </span>
注意:在定义字符数组1的长度时应该考虑字符数组2的长度,因为连接后新字符串的长度为两个字符串长度之和。进行字符串连接后,字符串1的结尾符将自动被去掉,在结尾串末尾保留新字符串后面一个结尾符。
3、strlen(p) 取字符串长度
strlen函数的功能是计算字符串的实际长度,不包括'\0'在内。
实现:
<span style="font-size:14px;">/*strlen的三种求法
思路:1、字符中“\0"与数字0的ASCII码一致,所以可用0来代替字符串的结尾"\0",遍历一个字符,计数器+1
2、指针*str指的是字符数组的第一个元素的首地址,故第一个字符不为"\0"则开始下个元素
3、指针的算数运算中:当两个指针指向同一段空间的不同位置时:两个指针相减便是两个指针之间元素的个数
#include<stdio.h>
/*1、计数器*/
int my_strlen1(char arr[])
{
int count = 0;
int i = 0;
while(arr[i++])
{
count++;
}
return count;
}
/*2.递归*/
int my_strlen2(char const *str) //const保护该字符串内容不被改变
{
if(*str)
return 1 + my_strlen2(str +1);
else
return 0;
}
/*3.指针减指针*/
int my_strlen3(char const *str)
{
char const *start = str; //start为首元素的地址
while(*str)
{
str++; //str为字符末尾元素的地址
}
return str - start;
}
int main()
{
char ch[] = "12345asdff";
printf("ret1=%d\nret2=%d\nret3=%d\n", my_strlen1(ch),my_strlen2(ch),my_strlen3(ch));
return 0;
} </span>
4、strcmp(str1,str2) 比较字符串
返回值< 0, 表示str1小于str2;
返回值为0, 表示str1等于str2;
返回值> 0, 表示str1大于str2.
实现:
<span style="font-size:14px;">/*模拟strcmp函数(两字符串ASCII码值进行比较,大于的话返回大于0的数,小于0的话
返回小于0的数,等于返回0*/
#include<stdio.h>
#include<assert.h>
int my_strcmp(char const *str1,char const *str2)
{
assert(str1);
assert(str2);
while(*str1 == *str2) //相等时
{ if(str1 =='\0')
str1++;
str2++;
return 0;
}
return *str1 - *str2; //不等时
}
int main()
{
char str1[] = "adsadsfg";
char str2[] = "adsa";
int ret = my_strcmp(str1,str2);
printf("%d\n",ret);
return 0;
}</span>
5、strstr(str1,str2) 查找字符串
在字符串str1中查找tr2子串. (1).返回子串str2在str1中首次出现位置的指针. (2)如果没有找到子串str2, 则返回NULL. (3)如果子串str2为空串, 函数返回str1值.
实现:
总 结:上述函数只可应用于字符串,而且当字符串
出现多个0时无法应用,故为了解决这个问题momcpy,mommove,
momset内存函数可直接批量处理字符串或者其他类型*/
二、内存操作函数(故以一字节来操作,指针类型为char)
memcpy(dest,src)从src复制count字节的字符到dest.(两个不相关的内存)
memmove(dest,src)从src复制count字节的字符到dest
memcpy与memmove功能一样, 只是不能处理src和dest出现重叠. 返回dest的值.
他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确,即memcpy是memmove的子集。
1、memcpy
实现:
2、memmove
两种情况:
.
第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。
实现:
<span style="font-size:14px;">//mommove函数的模拟(数组自身也可它与momcpy均可实现moncpy的功能)
#include<stdio.h>
#include<assert.h>
void *my_memmove(void *dest,void const *src,int count)
{
char *pdest = (char*)dest ;
char const *psrc =(char *) src;
void *pret = dest;
assert(dest);
assert(src);
if(pdest > psrc && pdest > psrc + count)
{
while(count--)
{
*(pdest+count) = *(psrc+count);/*内存重叠时,随着count--则从后向前拷贝
}
}
else
{
while(count--)
{
*pdest++ = *psrc++; /*内存不重叠时,由前向后不会覆盖原先内容*/
}
}
}
int main()
{
int str[] = {1,2,3,4,5,6,7,8,9};
int i = 0;
my_memmove(str+3,str,5*sizeof(int));
for(i = 0; i < sizeof(str)/sizeof(str[0]);i++)
{
printf("%d ",str[i]);
}
return 0;
}
</span>
strcpy(str1,str2) 复制字符串
strcat(str1,str2) 附加字符串
strlen(str) 取字符串长度
strcmp(str1,str2) 比较字符串
strstr(str1,str2) 查找字符串
1、strcpy
第二个字符串将覆盖掉第一个字符串的所有内容!
<span style="font-size:14px;">#include<stdio.h>
#include<assert.h>
char *my_strcpy(char *dest,char const *src)
{
assert(dest);
assert(src);
char *ret = dest;
while((*dest++ = *src++) != '\0')
{
;
}
return ret;
}
int main()
{
char str1[] = "abxde";
char str2[] = "sdsf";
my_strcpy(str1,str2);
printf("%s\n",str1);
return 0;
}</span>
注意:在定义数组时,字符数组1的字符串长度必须大于或等于字符串2的字符串长度。不能用赋值语句将一个字符串常量或字符数组直接赋给一个字符数组。
2、strcat(str1,str2)
功能:将字符串str2接到字符串str1的后面
将源串strSource添加到目标串strDestination后面, 并在得到的新串后面加上NULL结束符..源串strSource的字符会覆盖目标strDestination后面的结束符NULL. 在字符串的复制或添加过程中没有溢出检查, 所以要保证目标串空间足够大. 不能处理源串与目标串重叠的情况. 函数返回strDestination值.
<span style="font-size:14px;">//模拟实现strcat函数
#include<stdio.h>
#include<assert.h>
char *my_strcat(char *dest,char const *src)
{
assert(dest);
assert(src);
char *ret = dest;
while(*dest) //检测到“\0"
{
dest++;
}
while(*dest++ = *src++)//开始连接
{
;
}
return ret;
}
int main()
{
char arr1[] = "hello,";
char arr2[] = "world";
my_strcat(arr1,arr2);
printf("%s\n",arr1);
return 0;
} </span>
注意:在定义字符数组1的长度时应该考虑字符数组2的长度,因为连接后新字符串的长度为两个字符串长度之和。进行字符串连接后,字符串1的结尾符将自动被去掉,在结尾串末尾保留新字符串后面一个结尾符。
3、strlen(p) 取字符串长度
strlen函数的功能是计算字符串的实际长度,不包括'\0'在内。
实现:
<span style="font-size:14px;">/*strlen的三种求法
思路:1、字符中“\0"与数字0的ASCII码一致,所以可用0来代替字符串的结尾"\0",遍历一个字符,计数器+1
2、指针*str指的是字符数组的第一个元素的首地址,故第一个字符不为"\0"则开始下个元素
3、指针的算数运算中:当两个指针指向同一段空间的不同位置时:两个指针相减便是两个指针之间元素的个数
#include<stdio.h>
/*1、计数器*/
int my_strlen1(char arr[])
{
int count = 0;
int i = 0;
while(arr[i++])
{
count++;
}
return count;
}
/*2.递归*/
int my_strlen2(char const *str) //const保护该字符串内容不被改变
{
if(*str)
return 1 + my_strlen2(str +1);
else
return 0;
}
/*3.指针减指针*/
int my_strlen3(char const *str)
{
char const *start = str; //start为首元素的地址
while(*str)
{
str++; //str为字符末尾元素的地址
}
return str - start;
}
int main()
{
char ch[] = "12345asdff";
printf("ret1=%d\nret2=%d\nret3=%d\n", my_strlen1(ch),my_strlen2(ch),my_strlen3(ch));
return 0;
} </span>
4、strcmp(str1,str2) 比较字符串
返回值< 0, 表示str1小于str2;
返回值为0, 表示str1等于str2;
返回值> 0, 表示str1大于str2.
实现:
<span style="font-size:14px;">/*模拟strcmp函数(两字符串ASCII码值进行比较,大于的话返回大于0的数,小于0的话
返回小于0的数,等于返回0*/
#include<stdio.h>
#include<assert.h>
int my_strcmp(char const *str1,char const *str2)
{
assert(str1);
assert(str2);
while(*str1 == *str2) //相等时
{ if(str1 =='\0')
str1++;
str2++;
return 0;
}
return *str1 - *str2; //不等时
}
int main()
{
char str1[] = "adsadsfg";
char str2[] = "adsa";
int ret = my_strcmp(str1,str2);
printf("%d\n",ret);
return 0;
}</span>
5、strstr(str1,str2) 查找字符串
在字符串str1中查找tr2子串. (1).返回子串str2在str1中首次出现位置的指针. (2)如果没有找到子串str2, 则返回NULL. (3)如果子串str2为空串, 函数返回str1值.
实现:
<span style="font-size:14px;">const char *my_strstr(char const *dest,char const *src) { char const *str1 = dest; char const *str2 = src; char const *start = NULL; assert(dest); assert(src); if(*str2 == '\0') //查找的字符串为0时返回被查找的字符串 return str1; while(*str1) //要查找的字符串存在时 { start = str1; while(*str1&&*str2&&(*str1==*str2)) { str1++; str2++; } if(*str2 == '\0') { return start; } str2 = src; str1 = start+1; } return NULL; //不存在返回NULL }</span>
总 结:上述函数只可应用于字符串,而且当字符串
出现多个0时无法应用,故为了解决这个问题momcpy,mommove,
momset内存函数可直接批量处理字符串或者其他类型*/
二、内存操作函数(故以一字节来操作,指针类型为char)
memcpy(dest,src)从src复制count字节的字符到dest.(两个不相关的内存)
memmove(dest,src)从src复制count字节的字符到dest
memcpy与memmove功能一样, 只是不能处理src和dest出现重叠. 返回dest的值.
他们的作用是一样的,唯一的区别是,当内存发生局部重叠的时候,memmove保证拷贝的结果是正确的,memcpy不保证拷贝的结果的正确,即memcpy是memmove的子集。
1、memcpy
实现:
<span style="font-size:14px;">//模拟实现memcpy函数(两个不相关的数组) #include<stdio.h> #include<assert.h> void *my_memcpy(void *dest,void const *src,int count) { char *pdest = dest; char const *pssrc = src; assert(dest); assert(src); while(count--) { *(char *)dest++ = *(char *)src++; //内存拷贝为一字节拷贝,故应该强制类型转换,以确保每次移动一个字节 } return dest; } int main() { int str[] = {1,2,3,4,5,6,7,8,9}; int i = 0; my_memcpy(str+3,str,5*sizeof(int)); for(i = 0; i < sizeof(str)/sizeof(str[0]);i++) { printf("%d ",str[i]); } return 0; }</span>
2、memmove
两种情况:
.
第一种情况下,拷贝重叠的区域不会出现问题,内容均可以正确的被拷贝。
第二种情况下,问题出现在右边的两个字节,这两个字节的原来的内容首先就被覆盖了,而且没有保存。所以接下来拷贝的时候,拷贝的是已经被覆盖的内容,显然这是有问题的。
实现:
<span style="font-size:14px;">//mommove函数的模拟(数组自身也可它与momcpy均可实现moncpy的功能)
#include<stdio.h>
#include<assert.h>
void *my_memmove(void *dest,void const *src,int count)
{
char *pdest = (char*)dest ;
char const *psrc =(char *) src;
void *pret = dest;
assert(dest);
assert(src);
if(pdest > psrc && pdest > psrc + count)
{
while(count--)
{
*(pdest+count) = *(psrc+count);/*内存重叠时,随着count--则从后向前拷贝
}
}
else
{
while(count--)
{
*pdest++ = *psrc++; /*内存不重叠时,由前向后不会覆盖原先内容*/
}
}
}
int main()
{
int str[] = {1,2,3,4,5,6,7,8,9};
int i = 0;
my_memmove(str+3,str,5*sizeof(int));
for(i = 0; i < sizeof(str)/sizeof(str[0]);i++)
{
printf("%d ",str[i]);
}
return 0;
}
</span>
相关文章推荐
- Maven3--基本配置--01
- Effective STL 条款8
- 【groupadd】 创建组
- 【gpasswd】给组加密码
- iOS之AFN文件上传(4)
- 问题:iis配置json;结果:如何配置iis支持.json格式的文件
- 【Android】Intent的显式隐式用法
- StreamDM:基于Spark Streaming、支持在线学习的流式分析算法引擎
- 【passwd】修改用户密码
- 【openssl】 生成加密密码
- 【id】查看用户的账号属性信息
- 【groupmod】修改组 的相关信息
- 053(十六)
- algrothm_bata structure_base3
- Android数据缓存的实现
- SGU 103 Traffic Lights(spfa)
- java enum的用法详解
- java的getClass()函数
- iOS学习笔记25-录音和网络流媒体
- 【useradd】 选项 用户名