C语言之字符串搜索以及替换

字符串搜索以及替换

刚开始摸爬打滚的登上了求职的路上,经历了无数的面试以及笔试。至今还没有着落。经验已经积累了一些,今天在这里写详细分析一下我在笔试当中遇到的一个高频考题。没错,就是本章的题目,字符串的搜索以及替换。

题目介绍

目前参过4个不同公司企业的笔试了。其中这一题居然连续出现了两次。这一题比较考基础以及程序员的思维。看似简单但暗藏的玄机,如果不在考试之前做好充分的准备,那么在半个小时或一个小时以内把代码解出来,还是有相当的难度的。

其中有一家公司的考题我保留了下来,这道题是这样描述的:

A,B,C是3个字符串。把A中包含的所有B都替换为C,如果替换以后还有B就继续替换,直到A不包含B为止。

  1. 请编写程序实现以上功能。不允许使用系统提供的字符串比较,查找和替换函数。
  2. 以上程序是佛总是能正常输出结果?如果不是,列出哪些情况无法正常输出结果。尽可能详细和全面。

main函数里的内容分析

本题有三个字符串,由于字符串的大小以及内容并不是本题考点关键,所以我们一开始就可以很轻松的定义和赋值给这三个字符串。假如,
A[1000]=“abcdefghijklmn”;
B[100]=“cdef”;
C[100]=“zz”;
创建完之后,我们直接调用一个自己编写的函数,"“replace”,来完成题目的要求以及输出结果即可。

以上主要是main函数里的代码的解释。

具体代码如下:

int main(){
    char A[1000], B[100], C[100];
    printf("input A:");
    fgets(A,1000,stdin);
    printf("input B:");
    fgets(B,100,stdin);
    printf("input C:");
    fgets(C,100,stdin);
    printf("output A:");
    printf("%s",replace(A,B,C));
    return 0;
}

Replace函数详解

首先Replace函数是一个指针函数,这里需要重复指针函数的定义就是它是一个返回指针的函数,所以它的定义是这样的:


```c
char *replace(char *A, const char *B, const char *C)

这里之所以会把replace定义成一个指针函数,主要是为了方便上文中在main函数里的输出可以直接调用replace函数。这个函数里的参数分别为三个指针,就是这三个数组首位字母的地址。而其中B和C的类型为const目的主要是防止B和C的内容被修改。而A的内容是必须要被替换掉的,所以它的类型不可以是const。

字符串的扫描

A 是需要被修改的字符串,我们需要对这个字符串进行扫描,找出其中与B一样的部分,然后把这一个部分给替换成C。为了更好的理解,图一显示了整个代码的大概步骤。

在这里插入图片描述
第一步扫描就是把字符串从头到为都观察一遍。至于观察到什么时候为止呢?正常来说直接在for循环里面i++一直执行到i小于strlen(A)【A的大小】就可以了。不过在这道题里面,这样做会有一个问题。
观察一下上图,第四步里由于B和C的尺寸不一样,当C替代B之后,A的尺寸也发生了改变。所以A在这个函数里面尺寸是一直在变化的,所以这个办法不行。
通常会用的是第二个方法,当读到结束字符时停止。结束字符可以从上图看出来就是‘\0’。这个属于字符串的基础,暂时先不多加解释。

所以目前为止,我们的代码是:


```c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *replace(char *A, const char *B, const char *C){
    int i;
    for(i=0;*(A+i)!='\0';i++){
    ...
    ...
    ...
    }
    return A;
}

int main(){
    char A[1000], B[100], C[100];
    printf("input A:");
    fgets(A,1000,stdin);
    printf("input B:");
    fgets(B,100,stdin);
    printf("input C:");
    fgets(C,100,stdin);
    printf("output A:");
    printf("%s",replace(A,B,C));
    return 0;
}

字符串的搜索

字符串的搜索主要是找出A里面的B部分。刚才已经提到过以上扫描的概念了,而搜索又恰恰发生在扫描之下。大致思想就是,扫描A时,当扫到一个字符与字符串B第一个字符一样时,就会开始检测这个字之后的字符是否跟字符串B其余字符一致。一直检测到不一致为止。此过程中会有一个计数器。若计数器与字符串B的长度一直【count=strlen(B)-1】,则表示搜索成功。过程大致如下图:
在这里插入图片描述

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

char *replace(char *A, const char *B, const char *C){
    int i;
    for(i=0;*(A+i)!='\0';i++){//扫描
    	int count;
        for(count=0;*(A+i+count)==*(B+count);count++){};//检测
    	if(count==strlen(B)-1){ //搜索成功
    	
    	}
    }
    return A;
}

int main(){
    char A[1000], B[100], C[100];
    printf("input A:");
    fgets(A,1000,stdin);
    printf("input B:");
    fgets(B,100,stdin);
    printf("input C:");
    fgets(C,100,stdin);
    printf("output A:");
    printf("%s",replace(A,B,C));
    return 0;
}

字符串的备份

当发现A部分里的B后,我们不能马上把C替换掉B。原因在之前提及过,B和C的长度不一定相等。在本题假设中,若直接替代会发生如下情况:
在这里插入图片描述
在这个过程中,若直接进行位替代的话,我们会发现原本应该被覆盖掉的‘e’还存在在字符串里。如果在B长度小于C这种情况,还会导致原内容被篡改,这是一个更加严重问题。
为了解决这个问题,我在这里用到了一个比较笨拙的办法,叫做字符串备份。大致思路如下:
在这里插入图片描述
如图所示,我们会定义一个新的数组D,来记录被替代的B之后的部分,这样做可以避免了若B长度小于C而导致内容被覆盖的问题。
所以代码目前为止是这样的:

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

char *replace(char *A, const char *B, const char *C){
    int i;
    for(i=0;*(A+i)!='\0';i++){	//扫描
    	int count,k;
        for(count=0;*(A+i+count)==*(B+count);count++){};	//检测
    	if(count==strlen(B)-1){	 //搜索成功
    		for(k=0;*(A+i+strlen(B)-1+k)!='\0';k++){ 
                *(D+k)=*(A+i+strlen(B)-1+k); 	//备份后续字符串
                *(A+i+strlen(B)-1+k)=0; 	//清空
            }
            *(A+i+strlen(B)-1+k)=0; //清空末尾
    	}
    }
    return A;
}

int main(){
    char A[1000], B[100], C[100];
    printf("input A:");
    fgets(A,1000,stdin);
    printf("input B:");
    fgets(B,100,stdin);
    printf("input C:");
    fgets(C,100,stdin);
    printf("output A:");
    printf("%s",replace(A,B,C));
    return 0;
}

字符串替代

终于都到了实现本题关键也是最容易的环节了——字符串替代。在这,我们直接修改A字符串内关于B的信息就可以了。详细内容如下图所示:
在这里插入图片描述

字符串补齐

由于刚才做了字符串的备份,替代完之后,字符串后面的部分都为空,为了能够继续扫描下去,必须把后续的字符串给复原。这一步骤与字符串的替代相似,详细过程也如下图所示:
在这里插入图片描述
所以,最终的代码为:

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

char *replace(char *A, const char *B, const char *C){
    int i,j;
    for(i=0;*(A+i)!='\0';i++){
        int count=0,k=0,l=0;
        char *D=(char*)malloc(1000*sizeof(char));
        for(count=0;*(A+i+count)==*(B+count);count++){};
        if(count==strlen(B)-1){ //搜索成功
            for(k=0;*(A+i+strlen(B)-1+k)!='\0';k++){ 
                *(D+k)=*(A+i+strlen(B)-1+k); //复制后续字符串,为位移做准备
                *(A+i+strlen(B)-1+k)=0; //清空
            }
            *(A+i+strlen(B)-1+k)=0; //
            for(j=0;j<strlen(C)-1;j++){
                *(A+i+j)=*(C+j);    //插入字符
            }
            for(l=0;l<strlen(D)-1;l++){
                *(A+i+j+l)=*(D+l); //添加后续字符
            }
            *(A+i+j+l)='\0';
            i=i+j-1;
        }
    }
    return A;
}

int main(){
    char A[1000], B[100], C[100];
    printf("input A:");
    fgets(A,1000,stdin);
    printf("input B:");
    fgets(B,100,stdin);
    printf("input C:");
    fgets(C,100,stdin);
    printf("output A:");
    printf("%s",replace(A,B,C));
    return 0;
}

总结

题主这个办法其实实在笨拙,而且对于熟悉掌握字符串内位于位直接的关系特别讲究。其实还有很多其余的方法,例如利用string.h里就有很多可用的函数库了。以后有机会的话定会再更新。

谢谢。

发布了1 篇原创文章 · 获赞 2 · 访问量 23

猜你喜欢

转载自blog.csdn.net/weixin_44403637/article/details/104940016