串的基本概念
串(string)(或字符串)是由零個或多個字符組成的有限序列,一般記爲:
s='a1a2...an'(n>=0)
串的基本操作
串的邏輯結構與線性表極爲相似,區別僅在於串的數據對象約束爲字符集 。然而串的操作與線性表有很大的差別。在線性表基本操作中,大多以單個元素作爲操作對象;而在串的基本操作中通常以“串的整體”作爲操作對象。
例如在串中查找某個子串、求取某一個字串、在串的某個位置插入一個字串以及刪除一個字串等。
常用的c語言標準庫字符串函數,像strcpy()、strcmp(),strcat(),substr(),strlen()等。
動態存儲分配的順序串
順序串的字符數組空間可使用C語言的malloc和free等動態存儲管理函數,來根據實際需要動態地分配和釋放。
這樣定義的順序串類型亦有兩種形式。
(1)較簡單的定義
typedef char *string; //C中的串庫<string.h>相當於使用此類型定義串
(2)複雜定義
{
char *ch; //若是非空串,則按串長分配存儲區,否則ch爲空串
int length; //串長度
}HString;
串的順序儲存操作【參見動畫演示】
下面是具體的實現:
/*
*HString.cpp
*author:xwz
*compiler:Dev-C++
*2017-7-3
*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ERROR -1
#define OVERFLOW 0
#define OK 0
#define TRUE 0
#define FALSE -1
typedef int Status;
typedef struct
{
char *ch; //若是非空串,則按串長分配存儲區,否則ch爲空串
int length; //串長度
}HString;
void init_string(HString *T)
{
//初始化串
T->ch = NULL;
T->length = 0;
}
Status StrAssign(HString &T,char *s)
{
//生成一個其值等於常量s的串T
int i,j=0;
char *p;
if(T.ch) free(T.ch);
for(i=0,p=s; *p ; ++i,++p); //求s的長度 i
if(!i) //若s爲空串
{
T.ch = NULL;
T.length = 0;
}
else
{
if(!(T.ch = (char*)malloc(i*sizeof(char)))) //爲串分配s串度的空間
exit(OVERFLOW);
while(T.ch[j] = s[j++]);
T.length = i;
}
return OK;
}
int StrLength(const HString &T)
{ //返回串T的長度
return T.length;
}
Status StrCopy(HString &T,const HString &S)
{
//將串S複製給串T
int j=0;
if(T.ch) free(T.ch);
if(S.length)
{
if(!(T.ch = (char*)malloc(S.length*sizeof(char))))
exit(OVERFLOW);
while(*(T.ch+j) = *(S.ch+j++));
T.length = S.length;
}
else
{
T.ch = NULL;
T.length = 0;
}
return TRUE;
}
Status StrInsert(HString &S,int pos,const HString &T)
{
//1<=pos<=StrLength(S) + 1 ,在串S的第pos個字符之前插入串T
int i,j;
if(pos<1 || pos > StrLength(S) + 1)
return ERROR;
if(T.length)
{
//重新爲串S分配空間
if(!(S.ch = (char*)realloc(S.ch,(S.length+T.length)*sizeof(char))))
exit(OVERFLOW);
//爲串T騰出空間
for(i=S.length-1; i>=pos-1; --i)
S.ch[i+T.length] = S.ch[i];
//將串T插入至串S中的pos處
for(i=pos-1,j=0; i<=pos+T.length-1 && j<T.length; ++i,++j)
S.ch[i] = T.ch[j];
S.length += T.length;
S.ch[S.length] = '\0';
}
return OK;
}
int StrCompare(const HString &T,const HString &S)
{
//兩串相比,若T>S返回 >0,T<S 返回 <0 ,T=S 返回0
int i;
for(i=0; i<T.length && i<S.length; ++i)
{
if(T.ch[i] != S.ch[i])
return T.ch[i] - S.ch[i]; //ASCAL 值
}
return T.length - S.length;
}
Status Concat(HString &T,const HString &S1,const HString &S2)
{
//用T返回由S1和S2連接而成的新串
int i,j;
if(T.ch) free(T.ch);
if(S1.length && S2.length)
{
if(!(T.ch=(char*)malloc((S1.length+S2.length)*sizeof(char))))
exit(OVERFLOW);
for(i=0;i<S1.length;++i)
T.ch[i] = S1.ch[i];
for(j=0;i<S1.length+S2.length && j<S2.length;++j,++i)
T.ch[i] = S2.ch[j];
T.length = S1.length + S2.length;
T.ch[T.length] = '\0';
}
return TRUE;
}
Status SubString(HString &Sub,const HString &S,int pos,int len)
{
//用Sub返回S從pos位置開始長度爲len的子串
int i,j;
if(pos<1 || pos > S.length+1 || len<1 || len>S.length-pos+1)
return ERROR;
if(Sub.ch) free(Sub.ch);
if(!len)
{
Sub.ch = NULL;
Sub.length = 0;
}
if(S.length)
{
if(!(Sub.ch = (char*)malloc(len*sizeof(char))))
exit(OVERFLOW);
for(j=0,i=pos-1; j<len && i<pos+len-1;++i,++j)
Sub.ch[j]=S.ch[i];
Sub.length = len;
Sub.ch[len] = '\0';
}
return TRUE;
}
void destory_string(HString &T)
{
//銷燬串
if(T.ch)
{
T.length = 0;
free(T.ch);
}
}
int Index(const HString &S,const HString &T,int pos)
{
//T爲非空串,若主串S中第pos個字符之後存在與 T相等的子串
//則返回第一個這樣的字串在S中的位置,否則返回FALSE
HString sub;
init_string(&sub);
int sLen = S.length,tLen = T.length,i;
if(pos>0)
{
i = pos;
while(i <= sLen-tLen+1)
{
SubString(sub,S,i,tLen);
if(StrCompare(T,sub)!=0)
++i;
else
{
destory_string(sub);
return i;
}
}
}
destory_string(sub);
return 0;
}
Status Replace(HString &S, const HString &T,const HString & V)
{
//用V替換主串S中出現的所有與T相等的不重疊的字符串
HString sub;
init_string(&sub);
int sLen = S.length,tLen = T.length,i=1,j,k;
while(i <= sLen-tLen+1)
{
//依次找出與V長度相等的串
SubString(sub,S,i,tLen);
if(StrCompare(T,sub)==0)
{
j=i-1;
k=0;
while((S.ch[j++] = V.ch[k++]) && (k<V.length))
;
}
++i;
}
destory_string(sub);
return TRUE;
}
Status Trimed(HString &T)
{
//去除串T中的空格
int j,i=0,k=0;
if(T.length)
{
while(T.ch[i++] != T.ch[T.length]) //T.ch[i] != '\0'
{
if(T.ch[i] == ' ')
{
for(j=i; j<T.length; ++j)
T.ch[j] = T.ch[j+1];
++k; //記錄空格數
}
//連續兩個或兩個以上的空格
if(T.ch[i] == ' ')
Trimed(T);
}
T.length -= k;
}
return TRUE;
}
bool StrEmpty(const HString &S)
{
return S.length == 0;
}
Status StrDelete(HString &S,int pos,int len)
{
//從字符串中刪除第pos個字符起長度爲len的子串
int i,j;
if(pos<1 || pos > S.length+1 || len<1 || len>S.length-pos+1)
return ERROR;
for(i=pos-1; i<S.length; ++i)
S.ch[i] = S.ch[i+len];
S.length -= len;
}
int main()
{
HString T,S,S2;
char str1[] = "helloppllo";
char str2[] = "llo";
char str3[] = "wsa";
char str4[] = "hello wor ld";
init_string(&T);
StrAssign(T,str1);
// printf("%s\n",T.ch);
init_string(&S);
StrAssign(S,str2);
// StrCopy(T,S);
// StrInsert(S,2,T);
// printf("%s\n",S.ch);
// int j=StrCompare(T,S);
// printf("%d",j);
// Concat(S2,T,S);
// printf("%s\n",S2.ch);
// HString Sub;
// init_string(&Sub);
//
//
//
// SubString(Sub,T,2,2);
// printf("%s",Sub.ch);
//
// destory_string(Sub);
// int i = Index(T,S,1);
// printf("%d\n",i);
// init_string(&S2);
// StrAssign(S2,str3);
// Replace(T,S,S2); //T="helloppllo",S="llo" ,S2="wsa";
// printf("%s\n",T.ch);
// printf("T = %s,T.length = %d\n",T.ch,T.length);
// Trimed(T);
// printf("T = %s,T.length = %d\n",T.ch,T.length);
StrDelete(T,3,2);
printf("T = %s,T.length = %d\n",T.ch,T.length);
// destory_string(S2);
destory_string(T);
destory_string(S);
getchar();
return 0;
}