首发于 C语言
C语言:输入任意字符串替换字符串中任意的子字符串,无限制中英文

C语言:输入任意字符串替换字符串中任意的子字符串,无限制中英文

一、实现的功能

1.提示用户输入一段句子,用户可以输入任意长度的句子,不限制中英文。
2.提示用户输入需要被替换的文字。
3.提示用户输入替换的内容,不限制长度和中英文。
4.然后输出替换后的句子。

二、算法实现

1.实现功能1、2、3

(1)首先需要声明一个动态输入函数:
char* strdc(char *s)
该函数的返回值为一个字符型指针,指向输入字符串的内存地址,该函数接收一个字符型指针,该指针的指向与返回值指向相同。

(2)在函数内定义整型变量:count,ch并初始化为0,来分别记录循环的次数以便增加多少内存和用于接收用户输入的字符

(3)然后初始化指针s指向的内存大小,这里采用malloc()函数,该函数包含在头文件stdlib.h中,初始空间只需要申请一个字符大小即可,用来保存用户输入的第一个字符,其余字符的保存靠循环增加其内存。

(4)进入循环,每当用户输入一个字符,将该值对应的ASCII码赋值给变量ch,然后判断该值是否为换行符,这是循环退出的条件,然后将ch赋值给s[count],完成一个字符的存储,然后使count自增1,然后为指针s指向的内存扩大1个字符的内存大小,这里采用realloc()函数,并将新内存的地址返回给s(这里不能确定relloc函数返回的指针指向和之前指针s的指向一样,所以需要重新将其赋值给s),然后循环往复,直到用户按下回车换行键位’\n’,退出循环,然后将结尾字符’\0’地址赋值给指针s[count],完成动态输入字符串,然后返回指针s,然后手动释放指针s的内存,避免产生内存泄露并使s指向空,防止s变成野指针。

2.实现字符串替换:

(1)需要声明一个字符串替换的函数:
char* strsub(char *str1,char *str2,char *str3)
该函数的返回值为一个字符指针,该函数接受三个字符型指针参数,str1,str2,str3分别为指向句子的字符指针,指向被替换字符串的指针,替换的字符串。
(2)不难想到一共有三种情况:
第一种:str2指向的字符串长度大于str3
第二种:str2指向的字符串长度小于str3
第三种:是str2指向的字符串长度等于str3
显然需要采用选择结构,switch和if均可,笔者采用的是if.
(3)在对上述情况分别编程前,还需要先定义选择结构中需要用到的变量:

  • 字符型指针变量k: 存储指针str2指向的字符串在str1指向的字符串中第一次出现的地址。
  • 整型变量str1_l,str2_l,str3_l: 分别是存储str1,str2,str3指向的字符串的长度。
  • 整型变量n: 存储str3指向的字符串的长度与str2指向的字符串的长度的差值,用于判断是否增加内存。n>0扩容,n<=0不扩容。
  • 整型变量y_l: 余长,y_l为str2指向的字符串在str1指向的字符串中,其str2指向字符串后面的字符的总数包括结尾’\0’。
    (4)接下来开始进入选择结构:
    1)当str3的长度大于str2的时候(n>0):
  • 首先要获取余长y_l,这些字符需要往后面移动,包括最后的’\0’
  • 获取指针str1指向的字符串的长度str1_l,每一次替换字符串前都需要重新获取,因为总字符串的长度str1_l会改变。
  • 用变量y_l创建一个字符数组rep[y_l]用来保存需要移动的字符,包括最后的’\0’,每轮替换,数组的长度会改变,用变量y_l去定义数组。
  • 使用realloc()函数为指针str1指向的内存扩容,新的大小为str1_l+n+1,这包括了最后的’\0’(字符串结束字符),并将返回的的指针转换为char*型赋值给str1,因为realloc()返回的指针指向并非一定就是原来str1的指向,所以得重新赋值。
  • 同理的,指针k的指向也要重新获取,用strstr()函数,该函数包含在头文件string.h中。
  • 然后进入第一个循环,将被替换的字符串后面的所有字符存入字符数组rep中,这些字符是需要移动的。
  • 进入第二个循环,将替换的字符串存入k指向的字符串中,k指向的字符串就是str1指向的字符串的子字符串(str2指向的字符串)。
  • 进入第三个循环,将rep数组的字符全部存回在替换的字符串后面,完成一轮替换
  • 获取k的指向,这里检查的时候应该跳过已经替换的字符串,即替换的时候要将指针k往后移动str3_l的长度,避免如下例子的死循环:
  • 如str1=“fish”,str2=“sh”,str3=“fish”
  • 如果k的指向空,就退出循环,完成替换。
    2)当str3的长度小于str2的时候(n<0):
  • 这时候就无需扩容了。
  • 首先要获取余长y_l,这些字符需要往前面移动,包括最后的’\0’。
  • 进入第一个循环,将替换字符串先存入指针str1指向的字符串中,注意这里不能包括结尾的’\0’,所以这里的循环条件的最大值不加1。否则会导致格式化%s输出的时候,输出到’\0’这里就停止了。
  • 进入第二个循环,将子字符串后面的所有字符存回字符串str1中,包括最后的’\0’,注意这里的下标,n为负数,要加负号。
  • 子字符串后面的所有字符存回字符串str1中,包括最后的’\0’
  • 获取k的指向,这里检查的时候也同样要跳过已经替换的字符串,不在赘述。
    3)当str3的长度等于str2的时候(n==0):
  • 这里还要分成两种情况,即当指针str2指向的字符串与str2指向的字符串内容相等的时候,指针str2指向的字符串与str2指向的字符串内容不相等的时候
  • 所以这里还要使用选择语句if,判断表达式采用了strcmp()函数,该函数包含在头文件string.h中,如果两字符串相等就会返回一个非零值,相等就返回0。
  • 显然当指针str2指向的字符串与str2指向的字符串内容相等的时候,不会进入循环,直接就到后面返回指针str1.
  • 指针str2指向的字符串与str2指向的字符串内容不相等的时候进入循环,这里直接将替换字符串先存入str1指向的字符串中就可以,不用移位。
    最后出选择结构后,返回指针str1,然后手动释放str1指向的堆区内存,避免内存泄漏,并给str1赋值NULL,使其变为空指针,防止str1变成野指针。
    至此实现字符串替换的函数已经完成。

3.主函数

(1)首先要定义三个字符型指针用来保存输入的字符串的地址。
(2)调用printf()函数提示用户输入相应的字符串,注意换行,然后调用动态输入函数strdc()保存用户输入的字符串。
(3)重复步骤(2)直到所有字符串输入完毕。
(4)调用printf()函数,在其里面调用字符串函数strsub(),输出替换后的字符串,注意换行。
(5)return 0;至此整个程序结束。

三、代码实现

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char* strsub(char *str1,char *str2,char *str3);//函数声明放前面,主函数才能放前面,美观
char* strdc(char* s);//声明动态输入函数
int main()
	char *str1,*str2,*str3;
	printf("请输入需要更改的句子:\n");
	str1=strdc(str1);//str1,str2,str3均存放在堆区
	printf("请输入需要被更改的文字:\n");
	str2=strdc(str2);//str2为被替换的字符串
	printf("请输入替换的文字:\n");
	str3=strdc(str3);//str3为替换的字符串
	printf("更改后的句子为:\n%s",strsub(str1,str2,str3));
	return 0;
char* strsub(char *str1,char *str2,char *str3)
	char *k=strstr(str1,str2);//定义一个字符指针k接收被替换的子字符串在字符串中的地址。
    int str1_l,str2_l=strlen(str2),str3_l=strlen(str3);
    int n=str3_l-str2_l,y_l;
    if(n>0)
    	while(k!=NULL)//没有被替换字符串的时候退出循环
    		y_l=strlen(k)-str2_l+1;
			str1_l=strlen(str1);
			char rep[y_l];
    		str1=(char*)realloc(str1,str1_l+n+1);
    		k=strstr(str1,str2);
			for(int i=0;i<y_l;i++)
				rep[i]=k[i+str2_l];
			for(int i=0;i<str3_l;i++)//将替换的字符串存入str1指向的字符串中
				k[i]=str3[i];
			for(int i=0;i<y_l;i++)//将rep数组中所有字符包括最后的'\0'存回在替换的字符串后面
				k[i+str3_l]=rep[i];
            k=strstr(k+str3_l,str2);//这里写一句是为了判断k是否为空指针,空则退出循环。
	else if(n<0)
		while(k!=NULL)
			y_l=strlen(k)-str2_l+1;
			for(int i=0;i<str3_l;i++)//将替换字符串先存入字符串str1中
				k[i]=str3[i];
			for(int i=0;i<y_l;i++)//将子字符串后面的所有字符向前移动n个步长,包括最后的'\0'
				k[i+str3_l]=k[i+str3_l-n];
			k=strstr(k+str3_l,str2);//作用同上
	else//n=0的时候
		if(strcmp(str2,str3)!=0)//内容相同不进循环
		while(k!=NULL)
			for(int i=0;i<str3_l;i++)//直接将替换字符串先存入字符串str1中就可以不用移位
				k[i]=str3[i];
			k=strstr(k+str3_l,str2);
	return str1;//返回字符指针
	free(str1);//调用函数结束手动释放堆区内存避免内存泄漏
	str1=NULL;//防止产生野指针
char* strdc(char *s)
	int count=0,ch=0;
	s=(char*)malloc(sizeof(char));
	while((ch=getchar())!='\n')
		s[count]=ch;
		++count;
		s=(char*)realloc(s,sizeof(char)*(1+count));
	s[count]='\0';//字符串结尾
	return s;
	free(s);
	s=NULL;  
}

四、实例展示

请输入需要更改的句子:
永远不相信美好的事情即将发生