从内存中正/反向查找特定字符串,字符串替换的2种方法

本文介绍了一种实现字符串搜索和替换功能的算法,包括从头开始编写strstr和rstrstr函数来查找子串,并在此基础上实现了两种不同的字符串替换方法。一种采用正向遍历的方式进行替换,另一种则使用逆向遍历来提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

// return: NULL Not Found
char* s_strstr(const char* _pBegin, int _MaxLen,const char* _szKey)
{
    if (NULL == _pBegin || NULL == _szKey || _MaxLen <= 0)
    {
        return NULL;
    }
    int i = 0, j = 0, k = 0;
    int s32CmpLen = strlen(_szKey);
    
    for (i = 0; i < _MaxLen; i++)
    {
        if(_pBegin[i] == _szKey[j])
        {
            for (j = 0, k = i; j < s32CmpLen; j++, k++)
            {
                if (_pBegin[k] != _szKey[j])
                {
                    j = 0;
                    break;
                }  
                if (j == s32CmpLen - 1)
                {
                    return (char*)_pBegin + i;
                }
            }
        }
    }

    return NULL;
}

// return: NULL Not Found
char* s_rstrstr(const char* _pBegin, int _MaxLen,const char* _szKey)
{
    if (NULL == _pBegin || NULL == _szKey || _MaxLen <= 0)
    {
        return NULL;
    }
    int i = _MaxLen - 1;
    int j = strlen(_szKey) - 1;
    int k = 0;
    int s32CmpLen = strlen(_szKey);
    
    for (i = _MaxLen - 1; i >= 0; i--)
    {
        if(_pBegin[i] == _szKey[j])
        {
            for (j = strlen(_szKey) - 1, k = i; j >= 0; j--, k--)
            {
                if (_pBegin[k] != _szKey[j])
                {
                    j = strlen(_szKey) - 1;
                    break;
                }  
                if (j == 0)
                {
                    return (char*)_pBegin + i - strlen(_szKey) + 1;
                }
            }
        }
    }

    return NULL;
}

// return: false error O(n*n)
bool replace(char* _szInput, int _MaxLen, const char* _szOld, const char* _szNew)
{
    if (NULL == _szInput || NULL == _szOld || NULL == _szNew || _MaxLen <= 0)
    {
        return false;
    }
    bool bRet = true;
    char* find = NULL;
    do
    {
        find = s_strstr(_szInput, _MaxLen, _szOld);
        if (NULL != find)
        {
            int BlankLen = _MaxLen - strlen(_szInput);
            int NeedLen = strlen(_szNew) - strlen(_szOld);
            if (BlankLen >= NeedLen)// check length
            {
                if (NeedLen >= 0) // 往后移动(空间变大或不变)
                {
                    memmove(find + strlen(_szNew), find + strlen(_szOld), _szInput+ _MaxLen - find - strlen(_szOld) - NeedLen); // prevent overflow
                }
                else // 往前移动(空间变小)
                {
                    memmove(find + strlen(_szNew), find + strlen(_szOld), _szInput+ _MaxLen - find - strlen(_szOld));
                }
                memcpy(find, _szNew, strlen(_szNew));
            }
            else
            {
                printf("buffer is too small[%d bytes] BlankLen[%d bytes] NeedLen[%d bytes]", _MaxLen, BlankLen, NeedLen);
                bRet = false;
                break;
            }
        }
    }while(NULL != find);
    
    return bRet;
}

// return: false error O(n)
bool replace1(char* _szInput, int _MaxLen, const char* _szOld, const char* _szNew)
{
    if (NULL == _szInput || NULL == _szOld || NULL == _szNew || _MaxLen <= 0)
    {
        return false;
    }
    bool bRet = true;
    char* find = NULL;
    int count = 0;
    int offset = 0;
    // calculate number of szOld
    do
    {
        find = s_rstrstr(_szInput, _MaxLen - offset, _szOld);
        if (NULL != find)
        {
            count ++;
            offset = _szInput + _MaxLen - find;
        }
    }while (NULL != find);
    if (0 == count)
    {
        return false;
    }
    
    int BlankLen = _MaxLen - strlen(_szInput);
    int NeedLen = (strlen(_szNew) - strlen(_szOld)) * count;
    char* pOldEnd = NULL;
    char* pNewEnd = NULL;
    // check length
    if (BlankLen >= NeedLen)
    {
        pOldEnd = _szInput + strlen(_szInput); // include '\0'
        pNewEnd = _szInput + strlen(_szInput) + NeedLen;
    }
    else
    {
        printf("buffer is too small[%d bytes] BlankLen[%d bytes] NeedLen[%d bytes]", _MaxLen, BlankLen, NeedLen);
        return false;
    }
    // replace
    if (pNewEnd - pOldEnd < 0)
    {
        // 往前移动(空间变小)
        find = _szInput;
        offset = 0;
        do
        {
            find = s_strstr(find, _MaxLen - offset, _szOld);
            if (NULL != find)
            {
                memmove(find + strlen(_szNew), find + strlen(_szOld), _szInput+ _MaxLen - find - strlen(_szOld));
                memcpy(find, _szNew, strlen(_szNew));
                find += strlen(_szOld);
                offset += find - _szInput;
            }
        }while (NULL != find);
    }
    else
    {
        // 往后移动(空间变大或不变)
        do
        {
            find = s_rstrstr(_szInput, pOldEnd - _szInput, _szOld);
            if (NULL != find)
            {
                while (pOldEnd != find + strlen(_szOld) - 1)
                {
                    *pNewEnd -- = *pOldEnd --;
                }
                memcpy(pNewEnd - strlen(_szNew) + 1, _szNew, strlen(_szNew));
                pNewEnd = pNewEnd - strlen(_szNew);
                pOldEnd = pOldEnd - strlen(_szOld);
            }
        }while (NULL != find);
    }

    return true;
}

int main(int argc, char** argv)
{
    if (4 != argc)
    {
        printf("Usage: %s <str> <key> <key>\n", argv[0]);
        return 0;
    }
    const char* szInput = argv[1];
    char* pos = s_strstr(szInput, strlen(szInput), argv[2]);
    printf("pos: %s\n", pos);
    
    pos = s_rstrstr(szInput, strlen(szInput), argv[2]);
    printf("pos: %s\n", pos);
    
    char str[256];
    
    memset(str, 0, sizeof(str));
    strcpy(str, argv[1]);
    bool bRet = replace(str, sizeof(str), argv[2], argv[3]);
    assert(bRet);
    printf("replace: %s\n", str);
    
    memset(str, 0, sizeof(str));
    strcpy(str, argv[1]);
    bRet = replace1(str, sizeof(str), argv[2], argv[3]);
    assert(bRet);
    printf("replace1: %s\n", str);
    
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值