【心得】strcat函数的实现与应用

实现

金山面试的问题之一,比较简单。
须要注意两点:1.字符串空间检测判断2.字符串末尾记得加'0'html

第一种写法:

也是个人答案:c++

char *strcat(char *str1, char *str2)
{
    if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";

    int len1=strlen(str1),len2=strlen(str2);
    for(int i=strlen(str1);i<len1+len2;i++){
        str1[i]=str2[i-len1];
    }
    str1 [len1+len2]= '\0';
    return str1;
}

当时少写了 str1 [len1+len2]= '0';面试

第二种写法:

char *strcat(char *str1, char *str2)
{
    if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";
    char *pt = str1;
    while(*str1!='\0') str1++;
    while(*str2!='\0') *str1++ = *str2++;
    *str1++ = '\0';
    return pt;
}

切不可写成return str1;
由于此时函数体内的str1指针已经被移动到字符串结尾,指向'0'。
因此只能返回一开始pt保存的原始str1。返回值错误!数组

因为函数strcat的参数str1是形参,因此主函数的数组a的指针不会变化。
可是最好的写法仍是不要直接对str1作修改:ide

char *strcat(char *str1, char *str2)
{
    if((str1==NULL)||(str2==NULL)) throw "Invalide arguments!";
    char *pt = str1;
    while(*pt!='\0') pt++;
    while(*str2!='\0') *pt++ = *str2++;
    *pt = '\0';
    return str1;
}

应用

参考:http://www.blog.chinaunix.net...
声明:使用gcc和vc++(VS2010)编译函数

函数定义:char *strcat (char *dest,const char *src)
函数说明:strcat()会将参数src字符串拷贝到参数dest所指的字符串尾,第一个参数dest要有足够的空间来容纳要拷贝的字符串;
返回值: 返回dest字符串参数的起始地址;ui

接下来分三种状况来看strcat()函数:.net

方案一:两个参数都是数组

#include <string.h>
#include <stdio.h>

int main(void)
{
    char dest[30] = "Hello";
    char src[] = "World";

    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

GCC/VC++:dest:[HelloWorld]unix

方案二:两个参数都是指针

  1. dest为空指针

    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char *dest = NULL;
        char *src = "World";
    
        strcat(dest, src);
        printf("dest:[%s]", dest);
    
        return 0;
    }

    GCC:Segmentation fault (core dumped)居然是段错误,为何呢?

    dest没有足够的空间来存储src中的内容;

    VC++:

    cmd:空
    弹出:.exe已中止工做。

    修改以后的:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char *dest = NULL;
        dest = (char *)malloc(1024);
        *dest='\0';//显式将首地址指向结束符。很是必要。不然1024个字节的字符串会充满随机的字符。
        char *src = "World";
    
        strcat(dest, src);
        printf("dest:[%s]", dest);
    
        return 0;
    }

    GCC/VC++:dest:[World]
    若是没有*dest='\0';,GCC经过,VC++不经过。
    猜想:gcc在malloc后,新分配的空间自动补全了'0'。

  2. dest非空

    但此时的dest是空字符串,若是想要在非空字符串(好比"aaa")后strcat怎么办?
    直接把char *dest = NULL;改为char *dest = "aaa";吗?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    int main(void)
    {
        char *dest = "aaa";
        dest = (char *)malloc(1024);
        *(dest+3)='\0';
        char *src = "World";
    
        strcat(dest, src);
        printf("dest:[%s]", dest);
    
        return 0;
    }

    VC++:

    cmd: dest:[屯蚖orld]

    gcc:

    dest[World]

    VC++中, "aaa"被新分配的内存地址的值覆盖。因为新分配的内存地址的值并未初始化(除了dest+3位置上赋值为'0'), 因此出现乱码。"World"的第一个字母W(1字节)被a的第三个字符组合成了汉字“蚖”(2字节)。

    那么,先分配内存,而后赋值:char *dest = (char *)malloc(1024);dest = "aaa";?
    同样不能够!
    VC++:

    cmd:空
    弹出:.exe已中止工做!

    gcc:Segmentation fault (core dumped)
    缘由相同:"aaa"将分配的空间覆盖,也就是说a指向新的字符串"aaa",它的大小为4,没法放下a和b。

    正确的作法是对a先申请内存,而后用strxxx函数对a开始几位进行修改。好比用strcpy:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    int main ()
    {
        char *dest=(char *)malloc(1024);
        char *src="World";
        strcpy (dest,"aaa");
        strcat (dest,src);
        printf("dest:[%s]", dest);//puts (dest);
        return 0;
    }

    vc++:

    cmd:dest:[aaaWorld]

    gcc:

    dest:[aaaWorld]

    OK!

方案三:第一个是数组,第二个是指针

#include <stdio.h>
#include <string.h>

int main(void)
{
    char dest[6] = "Hello";
    char *src = "World";

    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

gcc:

dest:[HelloWorld]
*** stack smashing detected ***: ./1 terminated
Aborted (core dumped)

为何会这样呢?不是说要空间足够的时候才能够拷贝成功的么?
很明显,这属于数组越界的问题,在C语言中,c不检查也不提示,因此这里的拷贝用到了dest[6]后面紧挨着的几个存储单元;

VC++:

cmd:dest:[HelloWorld]
弹出:stack around the variable “XX” was corrupted!

方案四:第一个指针,第二个数组

#include <stdio.h>
#include <string.h>

int main(void)
{
    char *dest;
    char src[] = "World";

    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

看到这里,都会知道确定是dest的空间不足,没法拷贝src中的内容;
因此输出结果是:
gcc:

dest:[�Ax�World]
//原文说他的结果是Segmentation fault (core dumped)

vc++:

cmd:空。
弹出:dest未初始化就被使用。

更改以后:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char *dest;
    dest = (char *)malloc(1024);
    *dest='\0';
    char src[] = "World";
    
    strcat(dest, src);
    printf("dest:[%s]\n", dest);

    return 0;
}

OK输出结果是
GCC/vc++:dest:[World]
若是没有*dest='\0';,GCC经过,VC++不经过。

相关文章
相关标签/搜索