字符串操作原型

char *strcpy(char *s1,const char *s2);//该函数把s2指向的字符串复制到s1指向的位置,返回值是s1
char *strncpy(char *s1,const char *s2,size_t n);//该函数把s2指向的字符串复制到s1的位置,最多复制n个,返回值是s1


char *strcat(char *s1,const char *s2);//s2指向的字符串被复制到s1的结尾,返回值是s1.
char *strncat(char *s1,const char *s2,size_t n);//复制过来的s2字符串的第一个字符覆盖了s1字符串结尾的空字符。s2字符串的空字符及其后的任何字符都不会被复制,并且追加一个空字符到结果的后面,返回值是s1.


int strcmp(const char *s1,const char *s2);
int strncmp(const char *s1,const char *s2);


char *strchr(const char *s,int c);//该函数返回一个指向字符串s中的存放c的第一个位置的指针,如果没有找到该字符,返回空指针。


char *strpbrk(const char *s,intc);//该函数返回一个指针,指向字符串s1中存放s2字符串中的任何字符的第一个位置。如果没有找到任何字符,则返回空指针。


char *strrchr(const char *s,int c);//返回值指向字符串s中字符c最后出现的位置。


char *strstr(const char *s1,const char *s2);//该函数返回一个指针,指向s1字符串中第一次出现s2的位置。


size_t strlen(const char *s);


char *strcpy(char *s1,const char *s2);










1、Strcat函数原型如下:
char *strcat(char *strDest, const char *strScr) //将源字符串加const,表明其为输入参数
{
       char * address = strDest;             //该语句若放在assert之后,编译出错
       assert((strDest != NULL) && (strScr != NULL)); //对源地址和目的地址加非0断言
       while(*strDest)             //是while(*strDest!=’/0’)的简化形式
       {                        //若使用while(*strDest++),则会出错,因为++是不受循环
              strDest++;               //约束的。所以要在循环体内++;因为要是*strDest最后指
       }                        //向该字符串的结束标志’/0’。
       while(*strDest++ = *strScr++) 
       {
              NULL;                 //该循环条件内可以用++,
       }                          //此处可以加语句*strDest=’/0’;有无必要?
return address;               //为了实现链式操作,将目的地址返回
}




1、附件
#include<assert.h>


char *strncat(char *dst,char const *src,unsigned int count)
{
char *address=dst;
assert( (dst!=NULL)&&(src!=NULL) );
while(*dst!='\0')
dst++;
while(count-- && *dst!='\0')
*dst++=*src++;
*dst='\0';
return address;


}


2、Strcpy函数原型如下:
char *strcpy(char *strDest, const char *strScr)
{
       char *address=strDest;
       assert((strDest != NULL) && (strScr != NULL));
       while(*strScr)                   //是while(*strScr != ’/0’)的简化形式;
       {
              *strDest++ = *strScr++;
       }
       *strDest = '\0';                       //当strScr字符串长度小于原strDest字符串长度
       return address;                      //时,如果没有改语句,就会出错了。
}


strcpy()返回的是字符的地址。其次,第一个参数不需要指向数组的开始,这样就可以只复制数组的一部分。另外,其与gets()函数一样,不检查目标字符是否容纳的下源字符串。




2、附件
//strncpy()如果src指向的字符个数少于count,则用'\0'补齐
#include<stddef.h>//为了使用size_t
#include<assert.h>
char *strncpy(char *dst,const *src,size_t count)
{
assert( (dst!=NULL)&&(src!=NULL) );
char *address=dst;


while(count--)
{
if(*src!='\0')
{
*dst++=*src++;
}
else
{
*dst++='\0';
}
}
return address;
}




3、Strcmp函数原型如下:
int strcmp (const char *str1,const char *str2)
{           
       int len = 0;
       assert((str1 != '/0') && (str2 != '/0'));
       while(*str1 && *str2 && (*str1 == *str2))
       {
              str1++;
              str2++;
       }
       return *str1-*str2;
}
  3附件//字符串比较,不区分大小写比较,大写字母会被映射wie小写字母
int stricmp(const char *dst,const char *src)
{
assert(dst!=NULL && src!=NULL);
int ch1,ch2;
while(*dst && *src)
{
if( (ch1=(int)*dst)<='A' && (ch2<='Z'))
ch1+=0x20;
if( (ch2=(int)*src)>='A' && (ch2<='Z'))
ch2+=0x20;
if(ch1==ch2)
{
dst++;
src++;
}
else break;
}
return (ch1-ch2);
}




int strncmp(const char *s, const char *t, unsigned int count)   
{   
    assert((s != NULL) && (t != NULL));   
    while (*s && *t && *s == *t && count --)   
    {   
        ++ s;   
        ++ t;   
    }   
    return(*s - *t);   
}




4、Strlen函数原型如下:
int strlen(const char *str)
{
    int len = 0;
       assert(str != NULL);
       while(*str++)
       {
              len++;
       }
       return len;
}


size_t __cdecl strlen(const char *src)
{
const char *eos=str;
while(*eos++);


return ((int)(eos-str-1));
}


同时应注意strcat---strncat
          strcmp---strncmp
          strcpy---strcpy 


5》strchr//函数返回一个指向str中c的首次出现的位置,没有找到返回NULL


char *strchr_(char *str,char c)
{
if(NULL==str)
return(char*)NULL;


while(*str &&*str!=c)
str++;
if(*str==c)


return str;//该局与if相匹配
return(char *)NULL;//该句与else向匹配
}




6》strchri//函数返回一个指向str中c的首次出现的位置,没有找到返回-1


int strchri_(const)






7》memset();把指定内存区域的前count个字节设置成字符c
#include<assert.h>
#include<stddef.h>
void *memset(void *buffer,int c,size_t count)
{
assert(buffer!=NULL);
char *p=(char *)buffer;


while(count--)
*p++=(char)c;
return buffer;
}




8》
//查找字符串第一次出现的位置
char *strstr(const char *strsrc,const char *str)
{
assert( (strsrc!=NULL)&&(str!=NULL) );
const char *s=strsrc;
const char *t=str;
for( ; *strsrc!='\0'; __strsrc)
{
for(s=strsrc,t=str;*t!='\0' && *s==*t;++s,++t)
NULL;
if(*t=='\0')
return (char *)strsrc;
}
}


9》//将字符串拷贝到新的位置
#include<assert.h>
#include<stddef.h>
#include<stdlib.h>
#include<string.h>
char *strdup_(char *strsrc)
{
if(strsrc!=NULL)
{
char *start=strsrc;
int len=0;
while(*strsrc++!='\0')
len++;


char *address=(char *)malloc(len+1);
assert(address!=NULL);


while( (*address++=*start++)!='\0')
;
return address-(len+1);
}
return NULL;
}




内存拷贝函数
7》memset();把指定内存区域的前count个字节设置成字符c
#include<assert.h>
#include<stddef.h>
void *memset(void *buffer,int c,size_t count)
{
assert(buffer!=NULL);
char *p=(char *)buffer;


while(count--)
*p++=(char)c;
return buffer;
}




10》memcpy(),拷贝不重叠的内存块
void *memcpy(void *dst,const void *src,size_t count)
{
assert( (dst!=NULL)&&(src!=NULL));
void *address=dst;
char *pdst=(char *)dst;
char *psrc=(char *)src;
assert( pdst<psrc ||pdst>psrc+count-1);
while(count--)
{
*pdst++=*psrc++;
}
return address;
}
11》


#include<string.h>
char *strtok(char* restrict s1,const char* restrict s2);


strtok在调用的时候忽略了起始位置开始的分隔符
    strtok将字符串分隔成标记。对strtok的第一次调用与后继的调用不同。第一次调用的时候,将要解析的字符串地址作为第一个参数s1,传递进去。在后继的解析同一个字符串的调用中,用NULL作为第一个参数。
    对strtok的每个后继调用都返回下一个标记的起始,并在返回的标记末尾插入一个'\0'。当strtok函数到达s1的末尾时,就返回NULL。
    strtok没有为标记分配新的空间,而是就地对s1进行了标记,理解这一点是很重要的。因此,如果需要在调用该函数后访问原来的s1,就必须传递字符串的一个拷贝。
    这两个参数使用的限定符restrict要求:这个函数中s1引用的任何对象都不能被s2访问。也就是说,被解析的字符串的末端不能用来包含定界符。


    但是,strtok不是一个线程安全的函数。因为根据其定义,它必须使用内部静态变量来记录字符串中下一个需要解析的标记的当前位置。但是,由于指示这个位置的变量只有一个,那么,在同一个程序中出现多个解析不同字符串的strtok调用时,各自的字符串的解析就会互相干扰。


    下面这个程序是一个用来确定一个文本中的每行单词个数的平均次数的错误算法。wordaverage函数用来确定每一行,不幸的是,wordcount函数也使用了strtok,这一次是用它来解析本行中的字,这时,strtok保持的内部状态信息被改变了=,=


#include<string.h>
#define LINE_DELIMITERS "\n"
#define WORD_DELIMITERS " "


static int wordcount(char *s)
{
    int coutn=1;


    if(strtok(s,WORD_DELIMITERS)==NULL)
        return 0;
    while(strtok(NULL,WORD_DELIMITERS)!=NULL)
        count++;
    return count;
}


double wordaverage(char *s)
{
    int linecount=1;
    char* nextline;
    int words;


    nextline=strtok(s,LINE_DELIMITERS);
    if(nextline==NULL)
        return 0.0;
    words=wordcount(nextline);
    while((nextline=strtok(NULL,LINE_DELIMITERS))!=NULL){
        words+=wordcount(nextline);
        linecount++;
    }
    return (double)words/linecount;
}




    POSIX定义了一个线程安全的函数——strtok_r,以此来代替strtok。_r表示可以重入(reentrant)。


    #include<string.h>
    char * strtok_r(char* restrict s,const char* restrict sep,char **restrict lasts);


这样,对上面程序稍作修正,就能正确运行了。
#include<string.h>
#define LINE_DELIMITERS "\n"
#define WORD_DELIMITERS " "


static int wordcount(char *s)
{
    int coutn=1;
    char *lasts;


    if(strtok_r(s,WORD_DELIMITERS,&lasts)==NULL)
        return 0;
    while(strtok_r(NULL,WORD_DELIMITERS,&lasts)!=NULL)
        count++;
    return count;
}


double wordaverage(char *s)
{
    int linecount=1;
    char* nextline;
    int words;
    char* lasts;


    nextline=strtok_r(s,LINE_DELIMITERS,&lasts);
    if(nextline==NULL)
        return 0.0;
    words=wordcount(nextline);
    while((nextline=strtok_r(NULL,LINE_DELIMITERS,&lasts))!=NULL){
        words+=wordcount(nextline);
        linecount++;
    }
    return (double)words/linecount;
}


    除了额外的参数lasts外,strtok_r函数与strtok的表现类似,lasts是用户提供的一个指针,指向strtok_r用来存放下一次解析的起始地址的那个单元。
























//mommove(),拷贝重叠或者是不重叠的内存块
void *memmove(void *to,const void *from,size_t count)
{
assert( (to!=NULL) && (from!=NULL));
void *result=to;
char *pto=(char *)to;
char *pfrom=(char *)from;
//to与from没有重叠
if(pto<pfrom || pto>pfrom+count-1)
{
while(count--)
{
*pto++=*pfrom++;
}
}
//to与from有冲叠,从后向前move
else
{
pto=pto+count-1;
pfrom=pfrom+count-1;
while(count--)
{
*pto--=*pfrom--;
}
}
return result;
}




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;  
}  


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;  
}  


//c标准库部分源代码
har * __cdecl strcat (char * dst,const char * src)  
{  
    char * cp = dst;  


    while( *cp )  
        cp++;                   /* find end of dst */  


    while( *cp++ = *src++ ) ;       /* Copy src to end of dst */  


    return( dst );                  /* return dst */  
}  
  
int __cdecl strcmp (const char * src,const char * dst)  
{  
    int ret = 0 ;  
    while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)  
        ++src, ++dst;  
      
    if ( ret < 0 )  
        ret = -1 ;  
    else if ( ret > 0 )  
        ret = 1 ;  
      
    return( ret );  
}  
  
size_t __cdecl strlen (const char * str)  
{  
    const char *eos = str;  
      
    while( *eos++ ) ;  
      
    return( (int)(eos - str - 1) );  
}  
  
char * __cdecl strncat (char * front,const char * back,size_t count)  
{  
    char *start = front;  
      
    while (*front++)  
        ;  
    front--;  
      
    while (count--)  
        if (!(*front++ = *back++))  
            return(start);  
          
        *front = '\0';  
        return(start);  
}  
  
int __cdecl strncmp (const char * first,const char * last,size_t count)  
{  
    if (!count)  
        return(0);  
      
    while (--count && *first && *first == *last)  
    {  
        first++;  
        last++;  
    }  
      
    return( *(unsigned char *)first - *(unsigned char *)last );  
}  
  
/* Copy SRC to DEST.  */  
char *  strcpy (char * dest,const char* src)   
{  
    reg_char c;  
    char *__unbounded s = (char *__unbounded) CHECK_BOUNDS_LOW (src);  
    const ptrdiff_t off = CHECK_BOUNDS_LOW (dest) - s - 1;  
    size_t n;  
      
    do  
    {  
        c = *s++;  
        s[off] = c;  
    }  
    while (c != '\0');  
      
    n = s - src;  
    (void) CHECK_BOUNDS_HIGH (src + n);  
    (void) CHECK_BOUNDS_HIGH (dest + n);  
      
    return dest;  
}  
  
char * __cdecl strncpy (char * dest,const char * source,size_t count)  
{  
    char *start = dest;  
      
    while (count && (*dest++ = *source++))    /* copy string */  
        count--;  
      
    if (count)                              /* pad out with zeroes */  
        while (--count)  
            *dest++ = '\0';  
          
        return(start);  
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值