1.串的定义
串:由零个或多个字符组成的有限序列,一般记为:s=“a1a2...an” (n≥0)。
ai可以是字母、数字或其他字符。
串中字符的个数n称为串的长度。
空串:零个字符,即长度为零的串称为空串,用或””表示。
空格串:仅由空格组成的的串称为空格串,如:s=〃└┘〃。
若串中含有空格,在计算串长时,空格应计入串的长度中。
如:s=〃I’m a student〃的长度 为13。
空串≠空格串。
子串:串中任意个连续的字符组成的子序列。
主串:包含子串的串相应地称为主串。
位置:字符在序列中的序号。
子串在主串中的位置则以子串的第一个字符在主串中的位置来表示。
例:假设a、b、c、d为如下的四个串 a=“BEI” ,b=“JING” ,c=“BEIJING” ,d=“BEI JING” 子串b在串c中的位置为4,而在串d中的位置为5。
相等:两个串的长度相等,并且对应位置的字符都相同。 如,上述串c和串d就不相等。
串结构与线性表结构的比较:
逻辑结构:极为相似,区别仅在于串的数据对象约束为字符集。
基本操作:有很大差别,线性表大多以“单个元素”作为操作对象,串通常以“串的整体”作为操作对象。
2.串的抽象数据类型定义
抽象数据类型:
ADT String {
数据对象:
D={ ai |ai∈CharacterSet, i=1,2,...,n, n≥0 }
数据关系:
R1={ < ai-1, ai > | ai-1, ai ∈D,i=2,...,n }
基本操作
} ADT String
StrAssign (&T, chars)
初始条件:chars 是字符串常量。
操作结果:把 chars 赋为 T 的值。
等价于C语言中的strset函数。
StrCopy (&T, S)
初始条件:串 S 存在。
操作结果:由串 S 复制得串 T。
等价于C语言中的strcpy函数。
DestroyString (&S)
初始条件:串 S 存在。
操作结果:串 S 被销毁。
StrEmpty (S)
初始条件:串 S 已存在。
操作结果:若 S 为空串,则返回TRUE,否则返回 FALSE。
“”表示空串,空串的长度为零。
StrCompare (S, T)
初始条件:串 S 和 T 存在。
操作结果: 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0。
等价于C语言中的strcmp函数(按ASCII码值进行大小比较)。
StrLength (S)
初始条件:串 S 存在。
操作结果:返回 S 的元素个数,称为串的长度。
等价于C语言中的strlen函数
Concat (&T, S1, S2)
初始条件:串 S1 和 S2 存在。
操作结果:用T返回由S1和S2联接而成的新串。
例如: Concate( T, “man”, “kind”) 求得 T = “mankind” 等价于C语言中的strcat函数
SubString (&Sub, S, pos, len)
初始条件:串S存在,pos和len的取值 1≤pos≤StrLength(S) 且 0≤len≤StrLength(S)-pos+1。
操作结果:用Sub返回串S的第pos个字符起长度 ,为len的子串。
Index (S, T, pos)
初始条件:串S和T存在,T是非空串,1≤pos≤StrLength(S)。
操作结果:若主串 S 中存在和串 T 值相同的子串, 则返回它在主串 S 中第pos个字符之后第一次出现的位置;否则函数值为0。
“子串在主串中的位置”指子串中的第一个字符在主串中的位序。
int Index (String S, String T, int pos)
{
// T为非空串。若主串S中第pos个字符之后存在与 T相等的子
// 串,则返回第一个这样的子串在S中的位置,否则返回0
if (pos > 0) {
n = StrLength(S); m = StrLength(T); i = pos;
while ( i <= n-m+1) {
SubString (sub, S, i, m);
if (StrCompare(sub,T) != 0) ++i ;
else return i ;
} // while
} // if
return 0; // S中不存在与T相等的子串
} // Index
Replace (&S, T, V)
初始条件:串S, T和V均已存在,且T是非空串。
操作结果:用 V 替换主串 S 中出现的所有与(模式串)T 相等的不重叠的子串。
StrInsert (&S, pos, T)
初始条件:串S和T存在,pos取值1≤pos≤StrLength(S)+1
操作结果:在串S的第pos个字符之前插入串T。
StrDelete (&S, pos, len)
初始条件:串S存在 pos取值1≤pos≤StrLength(S)-len+1。
操作结果:从串S中删除第pos个字符起长度为len的子串。
ClearString (&S)
初始条件:串S存在。
操作结果:将S清为空串。
串赋值StrAssign、串复制Strcopy、串比较StrCompare、求串长StrLength、串联接Concat以及求子串SubString等六种操作构成串类型的最小操作子集。
3.串的标准库函数
#include<string.h>
strcpy: 将字符串src复制到dest
Strcat:将字符串src添加到dest末尾
Strchr:检索并返回字符c在字符串s中第一次出现的位置
Strcmp:字符串s1与s2的大小,并返回s1-s2
strcpy :将字符串src复制到dest
Strcspn:扫描s1,返回在s1中有,在s2中也有的字符个数
Strdup:将字符串s复制到最近建立的单元
Strerror: 本函数返回最近一次的错误信息
Stricmp:比较字符串s1和s2,并返回s1-s2 strlen: 返回字符串s的长度
strlwr :字符串s中的大写字母全部转换成小写字母,并返回转换后的字符串
strncat:将字符串src中最多maxlen个字符复制到字符串dest中
strncmp:比较字符串s1与s2中的前maxlen个字符
strncpy:复制src中的前maxlen个字符到dest中
strnicmp:比较字符串s1与s2中的前maxlen个字符
Strnset: 将字符串s的前n个字符置于ch中
strpbrk :扫描字符串s1,并返回在s1和s2中均有的字符个数
Strrchr: 扫描最后出现一个给定字符c的一个字符串s
Strrev: 将字符串s中的字符全部颠倒顺序重新排列,并返回排列后的字符串
Strset: 将一个字符串s中的所有字符置于一个给定的字符ch
strspn: 扫描字符串s1,并返回在s1和s2中均有的字符个数
strstr: 扫描字符串s2,并返回第一次出现s1的位置
strtod: 将字符串str转换成双精度数,并返回这个数
strtok: 检索字符串s1,该字符串s1是由字符串s2中定义的定界符所分隔
strtol:将字符串str转换成长整型数,并返回这个数
strupr: 将字符串s中的小写字母全部转换成大写字母,并返回转换后的字符串
4.抽象数据类型串的实现
在C语言中可以有两种方式:
串的静态存储结构:将串定义为字符型数组,数组名就是串名,串的存储空间分配在编译时完成,程序运行时不能更改。
串的动态存储结构:定义字符指针变量,存储串值的首地址,通过字符指针变量名访问串值,串的存储空间分配是在程序运行时动态分配的。
静态存储采用顺序存储结构; 动态存储采用的是堆存储结构和链式存储。
5.串的静态实现
0.存储结构
#define MAXLEN 20
typedef struct { /* 串结构定义 */
char ch[MAXLEN];
int len;
} SStrin;
1.初始化
//初始化
SStrin * Init_SStrin( )
{ SStrin *s;
s = (SStrin *) malloc ( sizeof( SStrin ) );
s->len=0;
printf("初始化成功。\n");
return s;
}
2.录入
//录入
int Enter_SStrin(SStrin *s)
{char x;
printf("请输入元素:");
scanf(" %c",&x);
while(x!='#')
{
if (s->len==MAXLEN)
{ printf("串已满,录入失败。\n");
return 0;
}
s->ch[s->len] = x;
s->len=s->len+1;
scanf(" %c",&x);
}
printf("录入完成。\n");
return 1; /*入队成功,函数返回1*/
}
3.插入
//串插入函数
int StrInsert(SStrin *s,SStrin *t) /*在串s中序号为pos的字符之前插入串t */
{int i,pos;
printf("请输入插入位置:");
scanf("%d",&pos);
if ( pos<0||pos>s->len) //pos从0开始。
{printf("插入位置不合法。\n");
return 0; /* 插入位置不合法 */
}
if (s->len + t->len<=MAXLEN) /* 插入后串长≤MAXLEN */
{
for (i=s->len + t->len-1;i>=t->len + pos;i--)
s->ch[i]=s->ch[i-t->len] ;
for (i=0;i<t->len;i++)
s->ch[i+pos]=t->ch[i];
s->len=s->len+t->len;
printf("插入完成。\n");
}
else if (pos+t->len<=MAXLEN) /* 插入后串长>MAXLEN, 但串t的字符序列可以全部插入 */
{
for (i=MAXLEN-1;i >= t->len+pos;i--)
s->ch[i]=s->ch[i-t->len];
for (i=0;i<t->len;i++)
s->ch[i+pos]=t->ch[i];
s->len=MAXLEN;
printf("s中元素溢出,但t完整插入。\n");
}
else { /* 串t的部分字符序列要舍弃 */
for (i=0;i<MAXLEN-pos;i++)
s->ch[i+pos]=t->ch[i];
s->len=MAXLEN;
printf("s和t都溢出,插入部分t。\n");
}
return(1);
}
4.遍历
//遍历
int Printf(SStrin *s)
{int i;
if(s->len==0)
{printf("串为空。\n");
return 0;
}
printf("查看表中元素:");
for(i=0;i<s->len;i++)
{printf("%c",s->ch[i]);
}
printf("\n");
return 1;
}
5.删除
//串删除函数。
int StrDelete(SStrin *s) /* 在串s中删除从序号pos起len个字符 */
{
int i,pos,len;
printf("请输入插入位置,和删除字符个数:");
scanf("%d %d",&pos,&len);
if (pos<0 || pos>(s->len-len))
{printf("删除位置不合理。\n");
return(0);}
for (i=pos+len;i<s->len;i++)
s->ch[i-len]=s->ch[i];
s->len=s->len - len;
printf("删除成功。\n");
return(1);
}
6.复制
//串复制函数
void StrCopy(SStrin *s,SStrin *t) /* 将串t的值复制到串s中 */
{
int i;
for (i=0;i<t->len;i++)
s->ch[i]=t->ch[i];
s->len=t->len;
printf("复制完成。\n");
}
7.判空
//判空函数
int StrEmpty(SStrin *s) /* 若串s为空(即串长为0), 则返回1, 否则返回0 */
{
if (s->len==0)
{printf("串为空。\n");
return(1);}
else
{printf("串不为空。\n");
return(0);}
}
8.比较
//串比较函数
int StrCompare(SStrin *s,SStrin *t) /* 若串s和t相等, 则返回0;若s>t,则返回>0;若s<t,则返回<0 */
{
int i;
for (i=0;i<s->len&&i<t->len;i++)
if (s->ch[i]!=t->ch[i])
{if(s->ch[i]- t->ch[i]==0)
printf("串s和t相等。\n");
if(s->ch[i]- t->ch[i]>0)
printf("串s大于t。\n");
if(s->ch[i]- t->ch[i]<0)
printf("串s小于t。\n");
return(s->ch[i]- t->ch[i]);}
if(s->len - t->len==0)
printf("串s和t相等。\n");
if(s->len - t->len>0)
printf("串s大于t。\n");
if(s->len - t->len<0)
printf("串s小于t。\n");
return(s->len - t->len);
}
9.串长
//求串长函数
int StrLength(SStrin *s)/* 返回串s的长度 */
{printf("串s长度为:%d",s->len);
printf("\n");
return(s->len);
}
10.清空串
//清空函数
int StrClear(SStrin *s) /* 将串s置为空串 */
{
s->len=0;
printf("清空完成。\n");
return(1);
}
11.连接
//连接函数
int StrCat(SStrin *s,SStrin *t) /* 将串t连接在串s的后面 */
{
int i, flag;
if (s->len + t->len<=MAXLEN) { /* 连接后串长小于MAXLEN */
for (i=s->len; i<s->len + t->len; i++)
s->ch[i]=t->ch[i-s->len];
s->len+=t->len;
flag=1;
printf("连接成功。\n");
}
else if (s->len<MAXLEN) /* 连接后串长大于MAXLEN, 但串s的长度小于MAXLEN,即连接后串t的部分字符序列被舍弃 */
{
for (i=s->len;i<MAXLEN;i++)
s->ch[i]=t->ch[i-s->len];
s->len=MAXLEN;
flag=0;
printf("溢出,已连接部分t串。\n");
}
else
{flag=0; /* 串s的长度等于MAXLEN, 串t不被连接 */
printf("s串已满无法连接。\n");}
return(flag);
}
12.求子串
//求子串函数
SStrin *SubString(SStrin *s) /* 将串s中序号pos起len个字符复制到sub中 */
{
int i,pos,len;
SStrin *sub;
sub = (SStrin *) malloc ( sizeof( SStrin ) );
sub->len=0;
printf("请输入子串起始位置,和子串长度:");
scanf("%d %d",&pos,&len);
if (pos<0 || pos>s->len || len<1 || len>s->len-pos)
{ sub->len=0;
printf("子串不合法。\n");
return(sub);}
else {
for (i=0;i<len;i++)
sub->ch[i]=s->ch[i+pos];
sub->len=len;
printf("截取子串成功。\n");
return(sub);
}
}
13.定位
//定位函数
int StrIndex(SStrin *s,SStrin *t) /* 求串t在串s中的位置 */
{
int i, j=0,pos;
printf("请输入在第几个元素之后进行查找:");
scanf("%d",&pos);
i=pos;
if (t->len==0)
{printf("t不存在。\n");
return(0);}
while (i<s->len && j<t->len)
if (s->ch[i]==t->ch[j])
{i++;
j++;}
else
{i=i-j+1;
j=0;}
if (j>=t->len)
{printf("串t首在s中的位置为:%d",i-j);
return(i-j);}
else
{printf("未在s中找到t。\n");
return(0);}
}
6.串的静态存储总代码
#include<stdio.h>
#include<malloc.h>
#define MAXLEN 20
typedef struct { /* 串结构定义 */
char ch[MAXLEN];
int len;
} SStrin;
//初始化
SStrin * Init_SStrin( )
{ SStrin *s;
s = (SStrin *) malloc ( sizeof( SStrin ) );
s->len=0;
printf("初始化成功。\n");
return s;
}
//录入
int Enter_SStrin(SStrin *s)
{char x;
printf("请输入元素:");
scanf(" %c",&x);
while(x!='#')
{
if (s->len==MAXLEN)
{ printf("串已满,录入失败。\n");
return 0;
}
s->ch[s->len] = x;
s->len=s->len+1;
scanf(" %c",&x);
}
printf("录入完成。\n");
return 1; /*入队成功,函数返回1*/
}
//遍历
int Printf(SStrin *s)
{int i;
if(s->len==0)
{printf("串为空。\n");
return 0;
}
printf("查看表中元素:");
for(i=0;i<s->len;i++)
{printf("%c",s->ch[i]);
}
printf("\n");
return 1;
}
//串插入函数
int StrInsert(SStrin *s,SStrin *t) /*在串s中序号为pos的字符之前插入串t */
{int i,pos;
printf("请输入插入位置:");
scanf("%d",&pos);
if ( pos<0||pos>s->len) //pos从0开始。
{printf("插入位置不合法。\n");
return 0; /* 插入位置不合法 */
}
if (s->len + t->len<=MAXLEN) /* 插入后串长≤MAXLEN */
{
for (i=s->len + t->len-1;i>=t->len + pos;i--)
s->ch[i]=s->ch[i-t->len] ;
for (i=0;i<t->len;i++)
s->ch[i+pos]=t->ch[i];
s->len=s->len+t->len;
printf("插入完成。\n");
}
else if (pos+t->len<=MAXLEN) /* 插入后串长>MAXLEN, 但串t的字符序列可以全部插入 */
{
for (i=MAXLEN-1;i >= t->len+pos;i--)
s->ch[i]=s->ch[i-t->len];
for (i=0;i<t->len;i++)
s->ch[i+pos]=t->ch[i];
s->len=MAXLEN;
printf("s中元素溢出,但t完整插入。\n");
}
else { /* 串t的部分字符序列要舍弃 */
for (i=0;i<MAXLEN-pos;i++)
s->ch[i+pos]=t->ch[i];
s->len=MAXLEN;
printf("s和t都溢出,插入部分t。\n");
}
return(1);
}
//串删除函数。
int StrDelete(SStrin *s) /* 在串s中删除从序号pos起len个字符 */
{
int i,pos,len;
printf("请输入插入位置,和删除字符个数:");
scanf("%d %d",&pos,&len);
if (pos<0 || pos>(s->len-len))
{printf("删除位置不合理。\n");
return(0);}
for (i=pos+len;i<s->len;i++)
s->ch[i-len]=s->ch[i];
s->len=s->len - len;
printf("删除成功。\n");
return(1);
}
//串复制函数
void StrCopy(SStrin *s,SStrin *t) /* 将串t的值复制到串s中 */
{
int i;
for (i=0;i<t->len;i++)
s->ch[i]=t->ch[i];
s->len=t->len;
printf("复制完成。\n");
}
//判空函数
int StrEmpty(SStrin *s) /* 若串s为空(即串长为0), 则返回1, 否则返回0 */
{
if (s->len==0)
{printf("串为空。\n");
return(1);}
else
{printf("串不为空。\n");
return(0);}
}
//串比较函数
int StrCompare(SStrin *s,SStrin *t) /* 若串s和t相等, 则返回0;若s>t,则返回>0;若s<t,则返回<0 */
{
int i;
for (i=0;i<s->len&&i<t->len;i++)
if (s->ch[i]!=t->ch[i])
{if(s->ch[i]- t->ch[i]==0)
printf("串s和t相等。\n");
if(s->ch[i]- t->ch[i]>0)
printf("串s大于t。\n");
if(s->ch[i]- t->ch[i]<0)
printf("串s小于t。\n");
return(s->ch[i]- t->ch[i]);}
if(s->len - t->len==0)
printf("串s和t相等。\n");
if(s->len - t->len>0)
printf("串s大于t。\n");
if(s->len - t->len<0)
printf("串s小于t。\n");
return(s->len - t->len);
}
//求串长函数
int StrLength(SStrin *s)/* 返回串s的长度 */
{printf("串s长度为:%d",s->len);
printf("\n");
return(s->len);
}
//清空函数
int StrClear(SStrin *s) /* 将串s置为空串 */
{
s->len=0;
printf("清空完成。\n");
return(1);
}
//连接函数
int StrCat(SStrin *s,SStrin *t) /* 将串t连接在串s的后面 */
{
int i, flag;
if (s->len + t->len<=MAXLEN) { /* 连接后串长小于MAXLEN */
for (i=s->len; i<s->len + t->len; i++)
s->ch[i]=t->ch[i-s->len];
s->len+=t->len;
flag=1;
printf("连接成功。\n");
}
else if (s->len<MAXLEN) /* 连接后串长大于MAXLEN, 但串s的长度小于MAXLEN,即连接后串t的部分字符序列被舍弃 */
{
for (i=s->len;i<MAXLEN;i++)
s->ch[i]=t->ch[i-s->len];
s->len=MAXLEN;
flag=0;
printf("溢出,已连接部分t串。\n");
}
else
{flag=0; /* 串s的长度等于MAXLEN, 串t不被连接 */
printf("s串已满无法连接。\n");}
return(flag);
}
//求子串函数
SStrin *SubString(SStrin *s) /* 将串s中序号pos起len个字符复制到sub中 */
{
int i,pos,len;
SStrin *sub;
sub = (SStrin *) malloc ( sizeof( SStrin ) );
sub->len=0;
printf("请输入子串起始位置,和子串长度:");
scanf("%d %d",&pos,&len);
if (pos<0 || pos>s->len || len<1 || len>s->len-pos)
{ sub->len=0;
printf("子串不合法。\n");
return(sub);}
else {
for (i=0;i<len;i++)
sub->ch[i]=s->ch[i+pos];
sub->len=len;
printf("截取子串成功。\n");
return(sub);
}
}
//定位函数
int StrIndex(SStrin *s,SStrin *t) /* 求串t在串s中的位置 */
{
int i, j=0,pos;
printf("请输入在第几个元素之后进行查找:");
scanf("%d",&pos);
i=pos;
if (t->len==0)
{printf("t不存在。\n");
return(0);}
while (i<s->len && j<t->len)
if (s->ch[i]==t->ch[j])
{i++;
j++;}
else
{i=i-j+1;
j=0;}
if (j>=t->len)
{printf("串t首在s中的位置为:%d",i-j);
return(i-j);}
else
{printf("未在s中找到t。\n");
return(0);}
}
void menu()
{
printf("--------1.初始化s------\n");
printf("--------2.初始化t------\n");
printf("--------3.录入s--------\n");
printf("--------4.录入t--------\n");
printf("--------5.插入---------\n");
printf("--------6.删除---------\n");
printf("--------7.判空---------\n");
printf("--------8.复制---------\n");
printf("--------9.比较---------\n");
printf("--------10.求长度------\n");
printf("--------11.清空--------\n");
printf("--------12.连接--------\n");
printf("--------13.求子串sub---\n");
printf("--------14.定位-------\n");
printf("--------15.遍历s-------\n");
printf("--------16.遍历t-------\n");
printf("--------17.遍历sub-----\n");
printf("--------18.退出程序----\n");
}
int main()
{SStrin *s,*t,*sub;
int n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,a,quit=0;
menu();
while(1)
{
scanf("%d",&a);
switch(a)
{
case 1:s=Init_SStrin( );break;
case 2:t=Init_SStrin( );break;
case 3:n1=Enter_SStrin(s);break;
case 4:n2=Enter_SStrin(t);break;
case 5:n3=StrInsert(s,t) ;break;
case 6:n4=StrDelete(s) ;break;
case 7:n5=StrEmpty(s);break;
case 8:StrCopy(s,t);break;
case 9:n6=StrCompare(s,t) ;break;
case 10:n7=StrLength(s);break;
case 11:n8=StrClear(s) ;break;
case 12:n9=StrCat(s,t);break;
case 13:sub=SubString(s);break;
case 14:n10=StrIndex(s,t);break;
case 15:n11=Printf(s);break;
case 16:n11=Printf(t);break;
case 17:n11=Printf(sub);break;
case 18:quit=1;break;
default:printf("输入1~18之间的数字\n");break;
}
if(quit==1)
{break;
}
}
return 0;
}