串的基本概念
串(string)(或字符串)是由零个或多个字符组成的有限序列,一般记为:
s='a1a2...an'(n>=0)
串的基本操作
串的逻辑结构与线性表极为相似,区别仅在于串的数据对象约束为字符集 。然而串的操作与线性表有很大的差别。在线性表基本操作中,大多以单个元素作为操作对象;而在串的基本操作中通常以“串的整体”作为操作对象。
例如在串中查找某个子串、求取某一个字串、在串的某个位置插入一个字串以及删除一个字串等。
常用的c语言标准库字符串函数,像strcpy()、strcmp(),strcat(),substr(),strlen()等。
串的基本运算
对于串的基本运算,很多高级语言均提供了相应的运算符或标准的库函数来实现。
为叙述方便,先定义几个相关的变量:
char s1[20]="dir/bin/appl",s2[20]="file.asm",s3[30],*p;
int result;
下面以C语言中串运算介绍串的基本运算
1、求串长
int strlen(char *s);//求串s的长度
【例】printf("%d",strlen(s1)); //输出s1的串长12
2、串复制
char *strcpy(char *to,*from);//将from串复制到to串中,并返回to开始处指针
【例】strcpy(s3,s1); //s3="dir/bin/appl",s1串不变
3、联接
char *strcat(char *to,char *from);//将from串复制到to串的末尾,
//并返回to串开始处的指针
【例】strcat(s3,"/"); //s3="dir/bin/appl/"
strcat(s3,s2); //s3="dir/bin/appl/file.asm"
4、串比较
int strcmp(char *s1,char *s2);//比较s1和s2的大小,
//当s1<s2、s1>s2和s1=s2时,分别返回小于0、大于0和等于0的值
【例】result=strcmp("baker","Baker"); //result>0
result=strcmp("12","12"); //result=0
result=strcmp("Joe","joseph") //result<0
5、字符定位
char *strchr(char *s,char c);//找c在字符串s中第一次出现的位置,
//若找到,则返回该位置,否则返回NULL
【例】p=strchr(s2,'.'); //p指向"file"之后的位置
if(p) strcpy(p,".cpp"); //s2="file.cpp"
注意:
①上述操作是最基本的,其中后 4个操作还有变种形式:strncpy,strncath和strnchr。
②其它的串操作见C的<string.h>。在不同的高级语言中,对串运算的种类及符号都不尽相同
③其余的串操作一般可由这些基本操作组合而成
动态存储分配的顺序串
顺序串的字符数组空间可使用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;
}