strcat strcpy strlen strcmp

strcat

我自己写的是这样:

char* _strcat(char *_Dest, const char *_Source)
{
    assert((_Dest != NULL) && (_Source != NULL));
    char* p= _Dest;
    while(*p!='\0')
    {
        p++;
    }
    const char* temp = _Source;
    while( *temp!='\0')
    {
        *p=*temp;
        p++;
        temp++;
    }
    return _Dest;
}

strcat的源码如下:

char *strcat(char *des, const char *src)
{
    assert((des!=NULL) && (src!=NULL));
    char* address = des;
    while(*des != '\0')  // 移动到字符串末尾
        ++des;
    while(*des++ = *src++)  //dest的下一个字符用src的下一个字符赋值
        ;
    return address;
}

必须加assert判断,src指向的字符添加到dest所指向的结尾处,覆盖原来的\0,添加新的\0。二者所指的内存区不可重叠,并且dest要有足够的内存容纳src字符串,但源码也没有对此判断,所以它是危险的。注意其中dest不能指向常量区。

这样用是错的,p1指向了常量字符串:

    char *p1 = "123";
    char *p2 = "ABC";
    std::cout<<strcat(p1,p2)<<endl;

改变连接的起始点:

    char p1[4]="123";
    char p2[4]="ABC";
    std::cout<<strcat(p1+2,p2)<<endl;

结果是3ABC

以’\0’作为连接的标志:

    char p1[40]="123\0abc";
    char p2[8]="ABC\0DEF";
    std::cout<<strcat(p1,p2)<<endl;

结果是123ABC

strcpy

函数源码:

char* _strcpy(char *dst, const char *src)
{
    assert((dst!=NULL)&&(src!=NULL));
    char* p1 =dst;
    const char* p2 = src;
    while(*p1!='\0')
    {
        *p1 = *p2;
        p1++;
        p2++;
    }
    return dst;
}

函数不安全,src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。
源指针所指的字符串内容是不能修改的,因此应该声明为 const 类型。与strcat相比,没有先移动到dst末尾。注意复制src到\0为止。

测试代码:

    char s1[]="12345";
    char s2[]="abc";
    std::cout<<strcpy(s1,s2)<<endl;     //abc

复制s2到s1时,以\0为准。

strlen

我写的实现代码:

int _strlen(const char* s)
{
    assert(s!=NULL);
    char* p =s;
    int n=0;
    while(*p!='\0')
    {
        p++;
        n++;
    }
    return n;
}

注意指针不能为NULL,不统计最后的’\0’

strcmp

两个字符串的大小不能用关系运算符判断,应该用strcmp(a,b),两个字符串相同时返回0,a>b返回一个正值,否则返回负值.
从左向右逐个比较a,b中的字符,根据二者的ASCII值确定结果,如果二者一直相同,但字符串a长度较小,那么结果为负。
我用的编译器对正负的处理是1和-1,有的是ASCII的差值。
我是这样实现的:

int _strcmp(const char *dst, const char *src)
{
    assert((dst!=NULL)&&(src!=NULL));
    const char* p1 = dst;
    const char* p2 = src;
    while(*p1!='\0' && *p2!='\0')
    {
        if(*p1 > *p2)
            return 1;
        else if(*p1 < *p2)
            return -1;
        p1++;
        p2++;
    }
    if(*p1!='\0' && *p2=='\0')
        return 1;
    else if(*p1=='\0' && *p2!='\0')
        return -1;
    return 0;
}

一种源码是这样的:

int strcmp(const char *s1, const char *s2)  
{  
   //两字符串相等的情况,如果两个字符串中所有的字符相等,则返回0  
    while (*s1 == *s2++)    //两个字符相等  
        if (*s1++ == 0) //达到字符串末尾  
                return (0);  
   //不相等,则返回值为第一次不相等时的两字符之差  
    return (*(unsigned char *)s1 - *(unsigned char *)--s2);  
}  

以上几个函数中的src全要加const限定,strcmp的两个参数都要加const

参考: 博客

猜你喜欢

转载自blog.csdn.net/yao5hed/article/details/82186398