实现字符串替换
假设原字符串长度足够大, 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; }