字符串中的子串替換

串的替換
服務器君一共花費了114.285 ms進行了5次數據庫查詢,努力地為您提供了這個頁面。
試試閱讀模式?希望聽取您的建議

在很多編程語言中,都封裝了字符串替換的操作,那么我們這里自己用C語言來實現一個字符串替換的函數。具體需求為:Replace(String S,String T,String V),用V替換主串S中出現的所有與T相等的不重疊的子串。

字符串替換這個操作,需要結合我們前面講到的幾個函數。

  1. 首先是Index,找到子串位置。
  2. 然后是StrDelete,將找到的子串刪除。
  3. 再執行StrInsert,把新的子串插入。
  4. OK,完成

如果對這三個函數不熟悉,可以翻看本專題的前面三篇文章。具體函數設計為:

/*  初始條件: 串S,T和V存在,T是非空串(此函數與串的存儲結構無關) */
/*  操作結果: 用V替換主串S中出現的所有與T相等的不重疊的子串 */
Status Replace(String S,String T,String V)
{
	int i=1; /*  從串S的第一個字符起查找串T */
	if(StrEmpty(T)) /*  T是空串 */
		return ERROR;
	do
	{
		i=Index(S,T,i); /*  結果i為從上一個i之后找到的子串T的位置 */
		if(i) /*  串S中存在串T */
		{
			StrDelete(S,i,StrLength(T)); /*  刪除該串T */
			StrInsert(S,i,V); /*  在原串T的位置插入串V */
			i+=StrLength(V); /*  在插入的串V后面繼續查找串T */
		}
	}while(i);
	return OK;
}

完整的可執行程序:

#include "stdio.h"
#include "string.h"
#include "stdlib.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXSIZE 40 /* 存儲空間初始分配量 */

typedef int Status;		/* Status是函數的類型,其值是函數結果狀態代碼,如OK等 */
typedef char String[MAXSIZE+1]; /*  0號單元存放串的長度 */

/*  輸出字符串T */
void StrPrint(String T)
{
	int i;
	for(i=1;i<=T[0];i++)
		printf("%c",T[i]);
	printf("\n");
}

/* 若S為空串,則返回TRUE,否則返回FALSE */
Status StrEmpty(String S)
{
	if(S[0]==0)
		return TRUE;
	else
		return FALSE;
}

/* 生成一個其值等于chars的串T */
Status StrAssign(String T,char *chars)
{
	int i;
	if(strlen(chars)>MAXSIZE)
		return ERROR;
	else
	{
		T[0]=strlen(chars);
		for(i=1;i<=T[0];i++)
			T[i]=*(chars+i-1);
		return OK;
	}
}

/* 返回串的元素個數 */
int StrLength(String S)
{
	return S[0];
}

/*  初始條件: 串S和T存在 */
/*  操作結果: 若S>T,則返回值>0;若S=T,則返回值=0;若S < T,則返回值< 0 */
int StrCompare(String S,String T)
{
	int i;
	for(i=1;i<=S[0]&&i<=T[0];++i)
		if(S[i]!=T[i])
			return S[i]-T[i];
	return S[0]-T[0];
}

/* 用T返回S1和S2聯接而成的新串。若未截斷,則返回TRUE,否則FALSE */
Status Concat(String T,String S1,String S2)
{
	int i;
	if(S1[0]+S2[0]<=MAXSIZE)
	{ /*  未截斷 */
		for(i=1;i<=S1[0];i++)
			T[i]=S1[i];
		for(i=1;i<=S2[0];i++)
			T[S1[0]+i]=S2[i];
		T[0]=S1[0]+S2[0];
		return TRUE;
	}
	else
	{ /*  截斷S2 */
		for(i=1;i<=S1[0];i++)
			T[i]=S1[i];
		for(i=1;i<=MAXSIZE-S1[0];i++)
			T[S1[0]+i]=S2[i];
		T[0]=MAXSIZE;
		return FALSE;
	}
}

/* 用Sub返回串S的第pos個字符起長度為len的子串。 */
Status SubString(String Sub,String S,int pos,int len)
{
	int i;
	if(pos < 1||pos>S[0]||len < 0||len>S[0]-pos+1)
		return ERROR;
	for(i=1;i<=len;i++)
		Sub[i]=S[pos+i-1];
	Sub[0]=len;
	return OK;
}

/* 返回子串T在主串S中第pos個字符之后的位置。若不存在,則函數返回值為0。 */
/* 其中,T非空,1≤pos≤StrLength(S)。 */
int Index(String S, String T, int pos)
{
	int i = pos;	/* i用于主串S中當前位置下標值,若pos不為1,則從pos位置開始匹配 */
	int j = 1;				/* j用于子串T中當前位置下標值 */
	while (i <= S[0] && j <= T[0]) /* 若i小于S的長度并且j小于T的長度時,循環繼續 */
	{
		if (S[i] == T[j]) 	/* 兩字母相等則繼續 */
      	{
			++i;
         	++j;
      	}
      	else 				/* 指針后退重新開始匹配 */
      	{
         	i = i-j+2;		/* i退回到上次匹配首位的下一位 */
         	j = 1; 			/* j退回到子串T的首位 */
      	}
	}
	if (j > T[0])
		return i-T[0];
	else
		return 0;
}

/*  初始條件: 串S和T存在,1≤pos≤StrLength(S)+1 */
/*  操作結果: 在串S的第pos個字符之前插入串T。完全插入返回TRUE,部分插入返回FALSE */
Status StrInsert(String S,int pos,String T)
{
	int i;
	if(pos< 1||pos>S[0]+1)
		return ERROR;
	if(S[0]+T[0]<=MAXSIZE)
	{ /*  完全插入 */
		for(i=S[0];i>=pos;i--)
			S[i+T[0]]=S[i];
		for(i=pos;i < pos+T[0];i++)
			S[i]=T[i-pos+1];
		S[0]=S[0]+T[0];
		return TRUE;
	}
	else
	{ /*  部分插入 */
		for(i=MAXSIZE;i<=pos;i--)
			S[i]=S[i-T[0]];
		for(i=pos;i < pos+T[0];i++)
			S[i]=T[i-pos+1];
		S[0]=MAXSIZE;
		return FALSE;
	}
}

/*  初始條件: 串S存在,1≤pos≤StrLength(S)-len+1 */
/*  操作結果: 從串S中刪除第pos個字符起長度為len的子串 */
Status StrDelete(String S,int pos,int len)
{
	int i;
	if(pos < 1||pos>S[0]-len+1||len < 0)
		return ERROR;
	for(i=pos+len;i<=S[0];i++)
		S[i-len]=S[i];
	S[0]-=len;
	return OK;
}

/*  初始條件: 串S,T和V存在,T是非空串(此函數與串的存儲結構無關) */
/*  操作結果: 用V替換主串S中出現的所有與T相等的不重疊的子串 */
Status Replace(String S,String T,String V)
{
	int i=1; /*  從串S的第一個字符起查找串T */
	if(StrEmpty(T)) /*  T是空串 */
		return ERROR;
	do
	{
		i=Index(S,T,i); /*  結果i為從上一個i之后找到的子串T的位置 */
		if(i) /*  串S中存在串T */
		{
			StrDelete(S,i,StrLength(T)); /*  刪除該串T */
			StrInsert(S,i,V); /*  在原串T的位置插入串V */
			i+=StrLength(V); /*  在插入的串V后面繼續查找串T */
		}
	}while(i);
	return OK;
}

int main()
{
    int i, j, opp, pos;
    char s, str;
	String t,s1,s2,sub;
	Status k;

    printf("\n1.StrAssign 生成串 \n2.StrLength 求串長 \n3.StrCompare 串比較 ");
    printf("\n4.Concat 串連接 \n5.SubString 求子串 \n6.Index 求子串位置");
    printf("\n7.StrInsert 子串插入 \n8.StrDelete 子串刪除 \n9.Replace 子串替換");
    printf("\n0.退出 \n請選擇你的操作:\n");
    while(opp != '0')
    {
        scanf("%d",&opp);
        switch(opp)
        {
        case 1:
            k=StrAssign(s1,"nowamagic.net");
            if(!k)
            {
                printf("串長超過MAXSIZE(=%d)\n",MAXSIZE);
                exit(0);
            }
            printf("串s1為:");
            StrPrint(s1);
            printf("\n");
            break;

        case 2:
            printf("串s1長為%d \n",StrLength(s1));
            break;

        case 3:
            k=StrAssign(s2,"google.com");
            if(!k)
            {
                printf("串長超過MAXSIZE(%d)\n",MAXSIZE);
                exit(0);
            }
            printf("串s2為:");
            StrPrint(s2);
            printf("\n");

            i=StrCompare(s1,s2);
            if(i < 0)
                s=' < ';
            else if(i==0)
                s='=';
            else
                s='>';
            printf("串s1%c串s2\n",s);
            break;

        case 4:
            Concat(t,s1,s2);
            StrPrint(t);
            break;

        case 5:
            printf("求串s1的子串,請輸入子串的起始位置: ");
            scanf("%d", &i);
            printf("請輸入子串的長度: ");
            scanf("%d", &j);
            printf("起始位置:%d,子串長度:%d\n", i, j);
            k=SubString(sub,s1,i,j);
            if(k)
            {
                printf("子串sub為: ");
                StrPrint(sub);
            }
            break;

        case 6:
            printf("主串s1為: ");
            StrPrint(s1);
            k=StrAssign(sub,"magic");
            printf("子串sub為: ");
            StrPrint(sub);
            i=Index(s1,sub,1);
            printf("s1的第%d個字母起和sub第一次匹配\n",i);
            break;

        case 7:
            printf("主串s1為: ");
            StrPrint(s1);
            k=StrAssign(sub,"lol");
            printf("子串sub為: ");
            StrPrint(sub);
            printf("請輸入要插入的位置: ");
            scanf("%d", &pos);
            StrInsert(s1,pos,sub);
            StrPrint(s1);
            break;

        case 8:
            printf("從串s1的第pos個字符起,刪除len個字符,請輸入pos: \n");
            scanf("%d", &i);
            printf("再輸入len: \n");
            scanf("%d", &j);
            StrDelete(s1,i,j);
            StrPrint(s1);
            break;

        case 9:
            printf("主串s1為: ");
            StrPrint(s1);
            StrAssign(t,"a");
            printf("串t為:");
            StrPrint(t);
            StrAssign(sub,"aa");
            printf("串sub為:");
            StrPrint(sub);
            printf("用串s2取代串s1中和串t相同的不重疊的串后,串s1為: ");
            Replace(s1,t,sub);
            StrPrint(s1);
            break;

        case 0:
            exit(0);
        }
    }
}

延伸閱讀

此文章所在專題列表如下:

  1. 數據結構里的串是什么東西?
  2. 如何比較串的大小
  3. 串的抽象數據類型ADT
  4. 串的順序存儲結構
  5. 串最基本的5個操作的C實現
  6. 尋找子串在主串中的位置
  7. 如何在串中插入串
  8. 如何在串中刪除特定長度的子串
  9. 字符串中的子串替換
  10. 題外話:談談malloc()和free()

本文地址:http://www.snpmgr.live/librarys/veda/detail/2426,歡迎訪問原出處。

不打個分嗎?

轉載隨意,但請帶上本文地址:

http://www.snpmgr.live/librarys/veda/detail/2426

如果你認為這篇文章值得更多人閱讀,歡迎使用下面的分享功能。
小提示:您可以按快捷鍵 Ctrl + D,或點此 加入收藏

大家都在看

閱讀一百本計算機著作吧,少年

很多人覺得自己技術進步很慢,學習效率低,我覺得一個重要原因是看的書少了。多少是多呢?起碼得看3、4、5、6米吧。給個具體的數量,那就100本書吧。很多人知識結構不好而且不系統,因為在特定領域有一個足夠量的知識量+足夠良好的知識結構,系統化以后就足以應對大量未曾遇到過的問題。

奉勸自學者:構建特定領域的知識結構體系的路徑中再也沒有比學習該專業的專業課程更好的了。如果我的知識結構體系足以囊括面試官的大部分甚至吞并他的知識結構體系的話,讀到他言語中的一個詞我們就已經知道他要表達什么,我們可以讓他坐“上位”畢竟他是面試官,但是在知識結構體系以及心理上我們就居高臨下。

所以,閱讀一百本計算機著作吧,少年!

《深入理解MySQL核心技術》 Sasba Pacbev (作者), 李芳 (譯者), 于紅蕓 (譯者), 邵健 (譯者)

《深入理解MySQL核心技術》:從公共可用性的意義上講,MySQL源代碼是開放源代碼,但如果對其不了解,則實質上,它對于您來說是封閉的。MysQL開發團隊的前成員Sasha Pachev通過《深入理解MySQL核心技術》給出了MySQL 5的全面指南,揭示了這一強大數據庫的內部運作。您將直奔MySQL核心技術,了解各種數據結構和各種方便的功能的運作情況,了解如何添加新的存儲引擎和配置選項等。 《深入理解MySQL核心技術》從結構概況講起,在這一部分解釋了MysQL的不同組件是如何協同工作的。接著將學習設置有效的可編譯代碼副本的步驟,然后使用基本架構添加自己的配置變量和存儲引擎。

更多計算機寶庫...

燃烧吧足球登陆