实现字符串替换
假设原字符串长度足够大, replaced 字符串 和 new 字符串的 长度没有限制
算法中用到了 KMP 的匹配算法
// 字符串替换2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
/**
* @brief CalcKMPNext 计算kmp算法需要的next数组
*
* @param keyword 关键字
* @param keywordLen 关键字长度
* @param next 存储next
*/
void CalcKMPNext(const char* keyword, const int keywordLen, char* next)
{
int i = 0, j = -1;
next[i] = j;//初始化next[0],没有什么意义
while (i < keywordLen)
{
//如果不相等,回退直到相等,或者没有相等
while (j >= 0 && keyword[i]!=keyword[j])
j = next[j];
++i;
++j;
if (i<keywordLen)
next[i] = j;
}
}
/**
* @brief KMPSearch kmp搜索字符串算法
*
* @param src 待搜索的文本
* @param srcLen 待搜索文本长度
* @param keyword 搜索关键字
* @param keywordLen 搜索关键字长度
*
* @return 搜索到第一个结果停止,返回关键字在文本出现的索引,否则返回-1
*/
int KMPSearch(const char* src, const char* keyword)
{
int srcLen = strlen(src);
int keywordLen = strlen(keyword);
//存储kmp需要的next数组
char* next = (char*)malloc(keywordLen*sizeof(char));
if (!next)
return -1;
//初始化next数组的值
CalcKMPNext(keyword, keywordLen, next);
int i = 0, j = 0;
for ( ; i<keywordLen; ++i)
printf("next: %d\n", next[i]);
i = 0;
while (i < srcLen)
{
//如果比较结果不同,则需要回退关键字的索引,继续比较,如果回退至关键字开始处(j==0)时break,下次直接从当前i与关键字的第一个字符开始比较
while (j >= 0 && src[i] != keyword[j])
j = next[j];
printf("i=%d,j=%d\n",i,j);
i++;
j++;
if (j == keywordLen)
{
free(next);
return i - keywordLen;
}
}
free(next);
return -1;
}
int calcStrTimes(char *Array, char *pattern)
{
char *pCur = Array;
int patternLen = strlen(pattern);
int arrStrLen = strlen(Array);
int patternPos;
int count = 0;
while (pCur < Array+arrStrLen)
{
patternPos = KMPSearch(pCur, pattern);
if (patternPos != -1)
{
count++;
pCur = pCur + patternPos + patternLen;
}
else
{
break;
}
}
return count;
}
char* replace2(char *Array, char* oldStr, char* newStr)
{
if (Array == NULL || Array[0] == '\0')
return NULL;
if (oldStr == NULL || oldStr[0] == '\0')
return Array;
if (newStr == NULL || newStr[0] == '\0')
return Array;
int oldStrLen = strlen(oldStr);
int newStrLen = strlen(newStr);
int arrStrLen = strlen(Array);
bool bSiftFlag = newStrLen > oldStrLen? true:false;
char *pCur;
char *pNew;
int siftDistance = 0;
if (!bSiftFlag)
{
pCur = Array;
}
else
{
siftDistance = calcStrTimes(Array, oldStr) * (newStrLen - oldStrLen);
for (int idx = arrStrLen - 1; idx >=0; idx--)
{
Array[idx+siftDistance] = Array[idx];
}
pCur = Array + siftDistance;
}
pNew = Array;
int oldStrPos = KMPSearch(pCur, oldStr);
while (pCur < &Array[0]+arrStrLen+siftDistance)
{
if (oldStrPos != -1)
{
char *pDestPos = pCur + oldStrPos;
while(pCur < pDestPos)
{
*pNew++ = *pCur++;
}
memcpy(pNew, newStr, newStrLen);
pCur += oldStrLen;
pNew += newStrLen;
oldStrPos = KMPSearch(pCur, oldStr);
}
else
{
*pNew++ = *pCur++;
}
}
*pNew = '\0';
return Array;
}
int _tmain(int argc, _TCHAR* argv[])
{
char A[100] = {'\0'};
memcpy(A, "abcdef345kdgfaxyzfereaxyzeewaxyzdf", 34);
printf("%s\n", A);
replace2(A, "xyz", "CCIC");
printf("%s\n", A);
return 0;
}