传智播客 C/C++学习笔记 字符串替换
目录
方案1
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
有字符串有以下特征(“abcd11111abcd2222abcdqqqqq”),求写一个函数接口,
输出以下结果。
把字符串替换成(dcba11111dcba2222dcbaqqqqq),并把结果传出。
要求:
1. 正确实现接口和功能
2. 编写测试用例
/*
src: 原字符串
dst: ⽣成的或需要填充的字符串
sub: 需要查找的⼦字符串
new_sub:提换的新⼦字符串
return : 0 成功
-1 失败
*/
int replaceSubstr(/* in */char *src, /* out */char** dst,
/* in */char *sub, /* in */char *new_sub)
{
char *out = NULL;
char *p = NULL;
char *q = NULL;
int sub_len = 0;
int new_sub_len = 0;
if (src == NULL || dst == NULL || sub == NULL || new_sub == NULL) {
fprintf(stderr, "(src == NULL || dst == NULL || sub == NULL || new_sub == NULL)\n");
return -1;
}
out = (char*)malloc(sizeof(char) * 4096);
if (out == NULL) {
fprintf(stderr, "malloc out error\n");
return -1;
}
memset(out, 0, 4096);
p = src;
q = p;
sub_len = strlen(sub);
new_sub_len = strlen(new_sub);
while ((p = strstr(p, sub)) != NULL) {
//找到了子串
strncat(out, q, p - q);
strncat(out, new_sub, new_sub_len);
p += sub_len;
q = p;
if (*p == '\0') {
break;
}
}
if (*q != '\0') {
strncat(out, q, (src + strlen(src) - q));
}
*dst = out;
return 0;
}
int main(void)
{
char *str = "abcd213213abcddjisoabcd2131abcd";
char *dst = NULL;
replaceSubstr(str, &dst, "abcd", "X");
printf("dst: %s\n", dst);
replaceSubstr(str, &dst, "abcd", "dcba");
printf("dst: %s\n", dst);
return 0;
}
方案2
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//函数: str_replace
//功能: 将字符串s中所有f的内容替换成r的内容
//返回: 新字符串的地址(使用free释放), 失败返回0。
char * str_replace(const char * s, const char * f, const char * r)
{
int inum = 1;
int if_len, ir_len;
char * ps;
char * pt;
char * pn;
char * pp;
if (s == 0 || f == 0 || r == 0) return 0;
if (s[0] == 0 || f[0] == 0) return 0;
if_len = strlen(f);
ir_len = strlen(r);
for (ps = (char *)s;;)
{
pt = strstr(ps, f);
if (pt == 0)
{
inum += strlen(ps);
break;
}
inum += (pt - ps) + ir_len;
ps = pt + if_len;
}
pn = pp = (char*)malloc(inum);
if (pn == 0) return 0;
pn[inum - 1] = 0;
for (ps = (char *)s;;)
{
pt = strstr(ps, f);
if (pt == 0)
{
memcpy(pp, ps, strlen(ps));
break;
}
memcpy(pp, ps, pt - ps);
pp += pt - ps;
memcpy(pp, r, ir_len);
pp += ir_len;
ps = pt + if_len;
}
return pn;
}
int main(void)
{
char * cstr;
char * cnew;
cstr = "Good morning.";
cnew = str_replace(cstr, "morning", "evening");
if (cnew != 0)
{
puts(cnew);
free(cnew);
}
cstr = "aa..bb..cc..dd..!";
cnew = str_replace(cstr, "..", "");
if (cnew != 0)
{
puts(cnew);
free(cnew);
}
return 0;
}
方案三
#include <iostream>
#include<stdio.h>
#include<string.h>
char *replace(char* source, char *sub, char *rep)
{
char *result;
///*pc1 是复制到结果result的扫描指针*/
///*pc2 是扫描 source 的辅助指针*/
// /*pc3 寻找子串时,为检查变化中的source是否与子串相等,是指向sub的扫描指针 */
// /*找到匹配后,为了复制到结果串,是指向rep的扫描指针*/
char *pc1, *pc2, *pc3;
int isource, isub, irep;
isub = strlen(sub);
/*对比字符串的长度*/
irep = strlen(rep);
/*替换字符串的长度*/
isource = strlen(source);
/*源字符串的长度*/
if (NULL == *sub) return _strdup(source);
/*申请结果串需要的空间*/
result = (char *)malloc(((irep > isub) ? (float)strlen(source) / isub* irep + 1 : isource) * sizeof(char));
pc1 = result; /*为pc1依次复制结果串的每个字节作准备*/
while (*source != NULL)
{
/*为检查source与sub是否相等作准备,为pc2,pc3 赋初值*/
pc2 = source;
pc3 = sub;
/* 出循环的(任一)条件是:
* *pc2 不等于 *pc3 (与子串不相等)
* pc2 到源串结尾
* pc3 到源串结尾 (此时,检查了全部子串,source处与sub相等)
*****************************************************/
while (*pc2 == *pc3 &&*pc3!= NULL && *pc2 != NULL)
pc2++, pc3++;
/* 如果找到了子串,进行以下处理工作*/
if (NULL == *pc3)
{
pc3 = rep;
/*将替代串追加到结果串*/
while (*pc3 != NULL)
*pc1++ = *pc3++;
pc2--;
source = pc2;
/* 检查 source与sub相等的循环结束后,
* pc2 对应的位置是在 sub 中串结束符处。该是源串中下一个位置。
* 将 source 指向其前面一个字符。
***************************************************/
}
else /*如果没找到子串,下面复制source所指的字节到结果串*/
*pc1++ = *source;
source++; /* 将source向后移一个字符*/
}
*pc1 = NULL;
return result;
}
//以下为测试代码:
int main()
{
char s1[] = "abbccdfdcdbbdcd";
char s2[] = "dcd";
char s3[] = "12345";
char *p = replace(s1, s2, s3);
printf("source=%s\n",s1);
puts(s1);
printf("sub = %s\n",s2);
puts(s2);
printf("replace string = %s\n", p);
char str1[] = " 究天人之际, 通古今之变, 成一家之说";
char str2[] = "说";
char str3[] = "言";
char *strp = replace(str1, str2, str3);
//printf("source=%s\n", str1);
puts(str1);
//printf("sub = %s\n", str2);
puts(str2);
printf("replace string = %s\n", strp);
return 0;
}
第四种方案
//在s串中查找与s1相匹配的字符串,找到后用s2将s中与s1相配的串替换掉
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
void replace(char *s, char *s1, char *s2);
int main(int argc, char *argv[])
{
char s[256], s1[256], s2[256];
if (argc != 4)
{
printf("Usage:%s 源串 查找串 替换串\n", argv[0]);
return -1;
}
memset(s, sizeof(s), 0x00);
memset(s1, sizeof(s1), 0x00);
memset(s2, sizeof(s2), 0x00);
strcpy(s, argv[1]);
strcpy(s1, argv[2]);
strcpy(s2, argv[3]);
replace(s, s1, s2);
printf("%s\n", s);
}
void replace(char *s, char *s1, char *s2)
{
char *p, *sp, *dp;
int len, cnt;
for (;;)
{
if ((p = strstr(s, s1)) == NULL) return;
len = strlen(s2) - strlen(s1);
if (len)
{
//查找串和替换串长度不相同,需移位动作
sp = p + strlen(s1); //从sp所指位置移
dp = sp + len; //移到dp所指位置
cnt = strlen(sp) + 1; //所要移动的长度
memmove(p + strlen(s1) + len, p + strlen(s1), cnt);
}
memcpy(p, s2, strlen(s2));
}
}
思考
但不是很有时候会有问题,比如
后面的一个是另一个的字串时就会出错。其实通过第一次替换就成功了。
Without labor nothing prospers.
没有辛勤劳动,就不会有欣欣向荣的一切。