strlen
实现的方法:
使用 指针-指针 算出之间的差值,也就是这个字符串的真实长度
(指针-指针的要求就是:两个指针是同一个类型)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int My_Strlen(char *p)
{
char *p1 = p;
while( *p1 != '\0' )
{
*p1++;
}
return p1-p;
}
void testMy_strlen()
{
char *p = "1234";
printf("%d\n",My_Strlen(p));
}
strcpy
功能:字符串拷贝,把源字符串src,拷贝到目标空间dest中
实现过程:
1. 目标空间( dest )足够大,足够容得下src字符串(包括\0)
2. 目标字符串可修改,源字符串不能修改(类型前加const)
3. 模拟实现strcpy返回值类型是char*,有返回值为了实现链式访问
4. 把src中内容拷贝到dest中,直到src的'\0'拷贝过去结束
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
char* my_strcpy( char *dest,const char *src )
{
char *ret = dest;
assert(dest!=NULL);
assert(src!=NULL);
while( *ret++ = *src++ )
{
;
}
return dest;
}
void testMy_strcpy()
{
char p1[20] = "abcd";
char *p2 = "efghi";
my_strcpy(p1,p2);
printf("%s\n",p1);
printf("%d\n",strlen(my_strcpy(p1,p2)));
}
运行结果:
strcat
功能:字符串追加,把源字符串src,追加到目标空间dest中
实现过程:
1. 目标空间( dest )足够大,足够容得下追加的src字符串(包括\0)
2. 目标字符串可修改,源字符串不能修改(类型前加const)
3.模拟实现strcat返回值类型是char*,有返回值为了实现链式访问
4. 过程:
首先要找目标空间dest中'\0',并且让源字符串src覆盖dest中'\0',
然后开始追加,直到追加到src的'\0'结束
显然:
strcat不能实现自己给自己追加,因为刚开始追加的时候,已经
把'\0'覆盖,后面再去追加时(结束条件是:遇到'\0'),所以是无法实现的
char* My_Strcat(char *dest,const char *src)
{
char *ret = dest;
assert(dest && src);
while( *dest != '\0' )
{
*dest++;
}
while( *dest++ = *src++ )
{
;
}
return ret;
}
void testMy_strcat()
{
char p1[20] = "abcd ";
char *p2 = "efgh";
My_Strcat(p1,p2);
printf("%s\n",p1);
}
运行结果:
strcmp
功能:字符串比较函数
实现过程:
1. 首先s1和s2是固定字符串,要实现的是比较,所以都不能被修改
因此必须加上const 修饰
2. 先判断两个字符串长度是否相等,如果不相等,就没有必要再去遍历,直接返回-1
3. 如果相等:一起遍历字符串,首先比较第一个字符:
1. 两个字符的ASCII码值如果不相等,直接返回-1
2. 两个字符的ASCII码值相等,继续遍历
3. 直到遍历遇到'\0',结束遍历
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
int My_Strcmp(const char *dest,const char *src)
{
int len1 = strlen(dest);
int len2 = strlen(src);
if( len1 != len2 )
return -1;
else
{
while( *dest && *src )
{
if( *dest == *src )
{
*dest++ ;
*src++ ;
}
else
return -1;
}
return 0;
}
}
void testMy_strcmp()
{
char *p1 = "hell0";
char *p2 = "hello";
int flag = My_Strcmp(p1,p2);
if( flag == 0 )
{
printf("两个字符串相等\n");
}
else
{
printf("两个字符串不相等\n");
}
}
运行结果:
strstr
功能:在字符串中查找子串,如果找到,输出第一次找到子串的开始位置
实现过程:
1. 首先str和substr是固定字符串,要实现的是查找,所以都不能被修改
因此必须加上const 修饰
2. 要考虑到多种情况如下
1."abcdef"中找"bcd" 返回b的地址,输出bcdef
2."abcdef"中找""(空字符串) 没有必要找,直接把abcdef输出
3.“abcbcd”中找"bcd"
开始找str中b和substr中b相同,继续向后发现b和c不同,这时
substr应当退回去,从str中刚才开始匹配的下一个元素开始重新匹
配,也就是str第三个元素开始继续匹配,如此重复,直到匹配成功。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
char* My_Strstr( const char *str, const char *substr )
{
char *cp = (char *)str;
char *cur1 = (char *)str;
char *cur2 = (char *)substr;
assert(str);
if( *substr == '\0' )
return cp;
while( *cp )
{
cur1 = cp;
cur2 = (char *)substr;
while( *cur1 && *cur2 && (*cur1 == *cur2) )
{
*cur1++;
*cur2++;
}
if( *cur2 == '\0' )
return cp;
*cp++;
}
return NULL;
}
void testMy_strstr()
{
char *p1 = "abcdbcd";
char *p2 = "";
printf("%s\n",My_Strstr(p1,p2));
}
运行结果:
char *p1 = "abcdbcd";
char *p2 = "bcd";
memcpy
功能:
由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。
(src和dest内存不重叠)
memcpy 和 strcpy 的区别:
原型:
void *memcpy(void *memTo,const void *memFrom,size_t size)
char *strcpy(char *dst,const char *src);
相同点:
strcpy与memcpy都可以实现拷贝的功能
不同点:
1、复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,
例如字符数组、整型、结构体、类等。
2、复制的方法不同。strcpy不需要指定长度,它遇到被复制字符的串结束符"\0"才结束,
所以容易溢出。memcpy则是根据其第3个参数决定复制的长度。
3、用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy
4、实现功能不同,strcpy主要实现字符串变量间的拷贝,memcpy主要是内存块间的拷贝。
5、操作对象不同,strcpy的操作对象是字符串,memcpy 的操作对象是内存地址,并不限于何种数据类型。
6、执行效率不同,memcpy最高,strcpy次之。
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void *my_memcpy(void*dest, void*src, size_t n)
{
char *p = (char *)dest;
const char *p1 = (const char *)src;
assert(dest && src);
while(n--)
{
*p++ = *p1++;
}
return dest;
}
void testMy_Memcpy()
{
char p1[20] = "abc";
char *p2 = "abcdefg";
my_memcpy(p1,p2,5);
printf("%s\n",p1);
}
memmove
功能:
由src指向地址为起始地址的连续n个字节的数据复制到以dest指向地址为起始地址的空间内。
(src和dest内存重叠)
注意:
不重叠部分:从前向后拷贝
重叠部分:从后向前拷贝
#include<stdlib.h>
#include<string.h>
#include<assert.h>
void * my_memmove( void *dest, const void * src, size_t count )
{
void * ret = dest;
if( dest <= src || (char *)dest >= (char *)src+count )
{
while( count-- )
{
*(char *)dest = *(char *)src;
dest = (char *)dest + 1;
src = (char *)src + 1;
}
}
else
{
dest = (char *)dest + count-1;
src = (char *)src + count -1;
while(count--)
{
*(char *)dest = *(char *)src;
dest = (char *)dest -1;
src = (char *)src -1;
}
}
return ret;
}
void testMy_Memmove()
{
char p[] = "abcdefgh";
my_memmove(p,p+3,5);
printf("%s\n",p);
}
memset
功能:
将s所指向的某一块内存中的前n个字节的内容全部设置为ch指定的ASCII值
1. 第一个参数为指定内存地址
2. 块的大小由第三个参数指定
3. 这个函数通常为新申请的内存做初始化工作,其返回值为指向s的指针
void * my_memset(void*s, int ch, size_t n)
{
assert(s);
char *ret = (char *)s;
while (n--)
{
*ret++ =(char) ch;
}
return s;
}
int main()
{
char arr[10];
int i;
my_memset(arr, 0, 10*sizeof(char));
for (i = 0; i < 10; i++)
{
printf("%d\n", arr[i]);
}
system("pause");
return 0;
}