C语言中strcat的实现方法

最近看到一道题目要求, 自己码代码实现strcat的功能, 于是自己实现了一个如下:


/*
*   12.编写一个函数JOIN,让它实现字符串连接运算功能。
*/

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

// ==============【自己实现的strcat】==============
char * join(char * str1, const char * str2)
{
    assert(str1 != NULL && str2 != NULL);

    char * pstr = str1;
    while (*pstr++);
    --pstr;

    while ((*pstr++ = *str2++) != 0);

    return str1;
}

int main()
{
#define  N 20

    char buf[N] = "hello ";
    char * str2 = "world!";
    char buf1[N] = "hello ";

    char * res = join(buf, str2);
    char * res1 = strcat(buf1, str2);

    printf("%s\n", res);
    printf("%s\n", res1);

    return 0;

}

因为, 我们知道这个函数输入的第一个字符串是需要有足够内存空间的, 如果空间不够, 会引起栈崩溃的情况
这里写图片描述

于是我们试图查看一下标准库中的写法,下面是标准strcat.c的实现代码

/***
*strcat.c - contains strcat() and strcpy()
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       Strcpy() copies one string onto another.
*
*       Strcat() concatenates (appends) a copy of the source string to the
*       end of the destination string, returning the destination string.
*
*******************************************************************************/

#include <cruntime.h>
#include <string.h>

#ifndef _MBSCAT
#pragma function(strcat,strcpy)
#endif  /* _MBSCAT */

/***
*char *strcat(dst, src) - concatenate (append) one string to another
*
*Purpose:
*       Concatenates src onto the end of dest.  Assumes enough
*       space in dest.
*
*Entry:
*       char *dst - string to which "src" is to be appended
*       const char *src - string to be appended to the end of "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*
*******************************************************************************/

char * __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 */

}


/***
*char *strcpy(dst, src) - copy one string over another
*
*Purpose:
*       Copies the string src into the spot specified by
*       dest; assumes enough room.
*
*Entry:
*       char * dst - string over which "src" is to be copied
*       const char * src - string to be copied over "dst"
*
*Exit:
*       The address of "dst"
*
*Exceptions:
*******************************************************************************/

char * __cdecl strcpy(char * dst, const char * src)
{
        char * cp = dst;

        while( *cp++ = *src++ )
                ;               /* Copy src over dst */

        return( dst );
}

很明显, 原始的strcat函数是没有对 可能出现的各种问题做检查的。也就是说,如果我们输入一个空指针, 程序是会直接崩溃掉的<-_->!!
难怪现在推出了一个strcat_s版本。

/***
*strcat_s.c - contains strcat_s()
*
*   Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*   strcat_s() concatenates (appends) a copy of the source string to the
*   end of the destination string.
*
*******************************************************************************/

#include <string.h>
#include <internal_securecrt.h>

#define _FUNC_PROLOGUE
#define _FUNC_NAME strcat_s
#define _CHAR char
#define _DEST _Dst
#define _SIZE _SizeInBytes
#define _SRC _Src

#include <tcscat_s.inl>

其中tcscat_s.inl内容如下

/***
*tcscat_s.inl - general implementation of _tcscpy_s
*
*       Copyright (c) Microsoft Corporation. All rights reserved.
*
*Purpose:
*       This file contains the general algorithm for strcat_s and its variants.
*
****/

_FUNC_PROLOGUE
errno_t __cdecl _FUNC_NAME(_CHAR *_DEST, size_t _SIZE, const _CHAR *_SRC)
{
    _CHAR *p;
    size_t available;

    /* validation section */
    _VALIDATE_STRING(_DEST, _SIZE);
    _VALIDATE_POINTER_RESET_STRING(_SRC, _DEST, _SIZE);

    p = _DEST;
    available = _SIZE;
    while (available > 0 && *p != 0)
    {
        p++;
        available--;
    }

    if (available == 0)
    {
        _RESET_STRING(_DEST, _SIZE);
        _RETURN_DEST_NOT_NULL_TERMINATED(_DEST, _SIZE);
    }

    while ((*p++ = *_SRC++) != 0 && --available > 0)
    {
    }

    if (available == 0)
    {
        _RESET_STRING(_DEST, _SIZE);
        _RETURN_BUFFER_TOO_SMALL(_DEST, _SIZE);
    }
    _FILL_STRING(_DEST, _SIZE, _SIZE - available + 1);
    _RETURN_NO_ERROR;
}

很明显可以看到, strcat_s 除了添加了一个参数之外, 还加入了根据这个参数进行检测的功能, 检测数据的有效性, 以及回滚操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值