「<string>」 库函数算是C语言中较为常用的库了,这里简单实现了几个库函数。实现肯定会存在部分漏洞。
0.「预编译」
若要将以下函数实现封装为一个库,便需要将一下每一个函数实现写为一个 .h 文件,并加上这个预编译.h文件
#ifndef _M_STRING
#define _M_STRING
#ifndef _YVALS
#include<yvals.h>
#endif
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
#ifndef _SIZE_T_DEFINED
typedef unsigned int size_t;
#define _SIZE_T_DEFINED
#endif
void *M_memchr(const void *,int ,size_t );
void *M_memcpy(void *,const void *,size_t );
void *M_memmove(void *,const void *,size_t );
char *M_strcpy(char *,char *);
char *M_strcat(char *,const char *);
char *M_strncat(char *,const char *,size_t );
int M_memcmp(const void *,const void *,size_t );
int M_strcmp(const char *,const char *);
int M_strncmp(const char *,const char *,size_t );
void *M_memset(void *,int ,size_t );
size_t M_strlen(const char *);
char *M_strncpy(char *,const char *,size_t );
size_t M_strspn(const char *,const char * );
char *M_strchr(const char *,int );
char *M_strrchr(const char *,int );
char *M_strstr(const char *,const char *);
size_t M_strcspn(const char *,const char *);
#endif
1.「memchr」
「函数说明」 :memchr()从头开始搜寻s所指的内存内容前n个字节,直到发现第一个值为c的字节,则返回指向该字节的指针。
「代码实现」:
void *M_memchr(const void *s,int c,size_t n){
const unsigned char *su;
for(su=s ; n>0 ; su++,n--)
if(*su==(unsigned char )c)
return (void *)su;
return (void *)NULL;
}
2. 「memcmp」
「函数说明」:memcmp()用来比较s1和s2所指的内存区间前n个字符。字符串大小的比较是以ASCII码表上的顺序来决定,次顺序亦为字符的值。memcmp()首先将s1第一个字符值减去s2第一个字符的值,若差为0则再继续比较下个字符,若差值不为0则将差值返回。例如,字符串"Ac"和"ba"比较则会返回字符'A'(65)和'b'(98)的差值(-33)。
「代码实现」:
int M_memcmp(const void *s1,const void *s2,size_t n){
const char *p1,*p2;
for(p1=s1,p2=s2 ; 0<n ; ++p1,++p2, --n)
if(*p1!=*p2)
return ( (*p1>*p2) ? +1 : -1 );
return 0;
}
3.「memcpy」
「函数说明」:memcpy()用来拷贝src所指的内存内容前n个字节到s1所指的内存地址上。与strcpy()不同的是,memcpy()会完整的复制n个字节,不会因为遇到字符串结束'\0'而结束
「代码实现」:
void *M_memcpy(void *s1,const void *s2,size_t n){
char *p1;
const char *p2;
for(p1=s1,p2=s2 ; 0<n ; p1++,p2++ , --n)
*p1=*p2;
return s1;
}
4.「memmove」
「函数说明」:memmove()与memcpy()一样都是用来拷贝src所指的内存内容前n个字节到s1所指的地址上。不同的是,当s2和s1所指的内存区域重叠时,memmove()仍然可以正确的处理,不过执行效率上会比使用memcpy()略慢些。
「代码实现」:
void *M_memmove(void *s1,const void *s2,size_t n){
char *p1;
const char *p2;
p1=s1;
p2=s2;
if(p2<p1 && p1<p2+n)
for(p1+=n,p2+=n ; n>0 ; --n)
*--p1=*--p2;
else
for( ; n>0 ; --n)
*p1++=*p2++;
return ( s1 );
}
5.「memset」
「函数说明」:memset()会将参数s所指的内存区域前n个字节以参数c填入,然后返回指向s的指针。在编写程序时,若需要将某一数组作初始化,memset()会相当方便。
「代码实现」:
void *M_memset(void *s ,int c,size_t n){
char *su;
for(su=s ; n>0 ; su++,n--)
{
*su=(char)c;
}
return s;
}
6.「strcat」
「函数说明」:strcat()会将参数s2字符串拷贝到参数s1所指的字符串尾。第一个参数s1要有足够的空间来容纳要拷贝的字符串。
「代码实现」:
char *M_strcat(char *s1,const char *s2) {
char *pt=s1;
while(*s1!='\0')
s1++;
s1--;
while(*s2!='\0')
*(s1++)=*(s2++);
*s1='\0';
return pt;
}
7.「strchr」
「函数说明」:strchr()用来找出参数s字符串中第一个出现的参数c地址,然后将该字符出现的地址返回。
「代码实现」:
char *M_strchr(const char *s,int c){
for( ; *s!=((char)c) ; s++)
if(*s=='\0')
return NULL;
return ((char *)s) ;
}
8.「strcmp」
「函数说明」:strcmp()用来比较参数s1和s2字符串。字符串大小的比较是以ASCII 码表上的顺序来决定,此顺序亦为字符的值。strcmp()首先将s1第一个字符值减去s2第一个字符值,若差值为0则再继续比较下个字符,若差值不为0则将差值返回。例如字符串"Ac"和"ba"比较则会返回字符"A"(65)和'b'(98)的差值(-33)。
「代码实现」:
int M_strcmp(const char *s1,const char *s2){
for( ; *s1==*s2 ; *s1++,*s2++)
if(*s1=='\0')
return (0);
return((*s1>*s2) ? 1 : -1);
}
9.「strcpy」
「函数说明」:strcpy()会将参数s2字符串拷贝至参数s1所指的地址。
「代码实现」:
char *M_strcpy(char *s1,const char *s2){
char *s=s1;
while(*s2!='\0'&&*s!='\0')
*s++=*s2++;
*s='\0';
return s1;
}
10.「strcspn」
「函数说明」:strcspn()从参数s1字符串的开头计算连续的字符,而这些字符都完全不在参数s2 所指的字符串中。简单地说,若strcspn()返回的数值为n,则代表字符串s1开头连续有n个字符都不含字符串s2内的字符。
「代码实现」:
size_t M_strcspn(const char *s1,const char *s2){
const char *p1,*p2;
for(p1=s1; *p1!='\0' ; p1++)
for(p2=s2 ; *p2!='\0'; p2++)
if(*p1==*p2)
return (p1-s1);
return (p1-s1);
}
11.「strlen」
「函数说明」:strlen()用来计算指定的字符串s的长度,不包括结束字符"\0"。
「代码实现」:
size_t M_strlen(const char *s){
int len=0;
const char *p;
for( p=s ; *p!='\0' ; *p++)
len++;
return len;
}
12.「strncat」
「函数说明」:strncat()会将参数s2字符串拷贝n个字符到参数s1所指的字符串尾。第一个参数s1要有足够的空间来容纳要拷贝的字符串。
「代码实现」:
char *M_strncat(char *s1,const char *s2,size_t n){
char *s;
for(s=s1 ; *s!='\0' ; ++s ) ;
for( ; n>0 && *s2!='\0' ; --n )
*s++ = *s2++;
*s='\0';
return s1;
}
13.「strncmp」
「函数说明」:strncmp()会比较s1和s2的前n个字符。如果前n字节完全相等,返回值就=0;在前n字节比较过程中,如果出现s1[n]与s2[n]不等,则返回(s1[n]-s2[n])。
「代码实现」:
int M_strncmp(const char *s1,const char *s2,size_t n){
for( ; n>0 ; s1++,s2++,n--)
{
if(*s1!=*s2)
return ((*s1<*s2) ? -1 : +1 );
else
if(*s1=='\0')
return 0;
}
return 0;
}
14.「strncpy」
「函数说明」:strncpy()会将参数s2字符串拷贝前n个字符至参数s1所指的地址。
「代码实现」:
char *M_strncpy(char *s1,const char *s2,size_t n ){
char *s;
for(s=s1 ; *s2!='\0' ,n>0 ; n-- )
*s++=*s2++;
for( ;n>0;n--)
*s++='\0';
return s1;
}
15.「strrchr」
「函数说明」:strrchr() 函数查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回指向该位置的指针,如果失败,则返回 false。与之相对应的是strchr()函数,它查找字符串中首次出现指定字符的位置。
「代码实现」:
char *M_strrchr(const char *s,int c){
const char *sc;
for( sc=NULL ; ; *s++)
{
if(*s=='\0')
return ((char *)sc);
if(*s==(char)c)
sc=s;
}
}
16.「strspn」
「函数说明」:strspn()从参数s1 字符串的开头计算连续的字符,而这些字符都完全是s2 所指字符串中的字符。简单的说,若strspn()返回的数值为n,则代表字符串s1 开头连续有n 个字符都是属于字符串s2内的字符。
「代码实现」:
size_t M_strspn(const char *s1,const char * s2){
const char *p1,*p2;
for(p1=s1 ; *p1!='\0' ; p1++)
for(p2=s2 ; ; p2++)
{
if(*p2=='\0')
return (p1-s1)+1;
else if(*p1==*p2)
break;
}
return (p1-s1)+1;
}
17.「strstr」
「函数说明」:strstr()会从字符串s1 中搜寻字符串s2,并将第一次出现的地址返回
「代码实现」:
extern char *M_strchr(const char *,int c);
char *M_strstr(const char *s1,const char *s2){
const char *p1,*p2;
if(*s2=='\0'||s2==NULL)
return ((char *)s1);
for( ; (s1=M_strchr(s1,*s2))!=NULL ; ++s1)
{
for(p1=s1 , p2=s2 ; ; )
{
if(*++p2=='\0')
return ((char *)s1);
else if (*++p1!=*p2)
break;
}
}
return NULL;
}
大概就这做了这17个string库函数。 扯个蛋收场吧。