1、实验目的
(1)掌握串的特点及其存储方式
(2)用顺序存储结构实现一个串
(3)掌握串的查找、定位、连接、插入子串、删除子串等各个操作
2、实验内容
(1)定义一个存储顺序串的类型
(2)编写插入、删除、查找等所有基本函数
(3)设计如下选择式菜单,以选择菜单方式进行操作,将上述各种算法实现。
3、源程序(仅供参考)
//顺序串
#include<stdio.h>
#include<stdlib.h>
typedef struct{
char Data[100];//定义字符串的总大小
int len;//记录字符串长度
}String;
int Long(String *s){//求字符串长度
int i=0;
while(s->Data[i]!='\0'){
i++;
}
s->len=i;
return(s->len);//返回串长
}
void Establish(String *s){//建立字符串
printf("输入元素:");
gets(s->Data);//输入元素
s->len=Long(s); //求长度
if(s->len>0){//判断创建是否成功
printf("String创建成功!");
}else{
printf("String创建失败!!!");
}
}
void SubString(String *s,String *Sud){//求子串函数,String *Sud定义存放子表元素
int pod;//定义变量pod表示位置
int i,len;//定义len子串长度
printf("输入开始求子串的位置:");
scanf("%d",&pod);
printf("\n输入子串长度:");
scanf("%d",&len);
if(pod<1||pod>s->len||len<1||len>s->len-pod+1){//判断所开始查找的位置是否在主串上,如果在就执行else里的语句,如果不在吧Sud置空输出错误信息结束。
Sud->len=0;
printf("\n参数错误!!");
}else{
for(i=0;i<len;i++){
Sud->Data[i]=s->Data[pod+i-1];//把pod位置上的元素赋值给Sud串上的第一个位置
}
Sud->Data[i]='\0';//Sud尾部加上结束标志
Sud->len=len;//把len输入的长度赋值给Sud串的len,表示子串长度
if(Sud->len<len){//如果Sud的长度小于输入len 在输出错误 结束程序 ,反之输出子表元素
printf("发生错误!!");
exit(1);
}else{
printf("\n子串元素为:");
for(i=0;i<len;i++){
printf("%5c",Sud->Data[i]);
}
}
}
}
void StrDelete(String *s){
int j,k,l,x,i,y;
printf("输入子串删除的位置:");
scanf("%d",&j);
printf("\n输入删除子串的长度:");
scanf("%d",&l);
x=s->len;//把串长赋值给X变量
if(j+l-1>s->len){//删除的位置加上删除子串的长度如果大于主串则报错退出程序
printf("\n子串越界!!");
exit(1);
}else{
y=s->len;
for(k=j+l-1;k<y;k++,j++){//从第j个位置开始删除长度l的子串
s->Data[j-1]=s->Data[k];
s->len--;
}
s->Data[s->len]='\0';//尾部结束标志
}
if(s->len>x){//如果串长大于删除之前的串长则报错,退出程序
printf("\n删除错误!!");
exit(1);
}else{
printf("\n删除成功。");//删除成功,输出删除后的串
printf("\n删除后的串:");
for(i=0;i<s->len;i++){
printf("%5c",s->Data[i]);
}
}
}
void StrInsert(String *s ,String *s1){//插入子串的操作
printf("创建子串:");
gets(s1->Data);//给子串s1赋值
int i,k;
k=0;
while(s1->Data[k]!='\0'){//计算子串S1长度
k++;
}
s1->len=k;//把计算得到s1长度的K赋值给len
printf("输入插入子串的位置:");
scanf("%d",&i);
if(i>s->len){//如果插入子串S1的位置大于主串S,则直接报错 退出程序
printf("插入子串的位置错误!");
exit(1);
}
else if(s->len+s1->len>100){//如果插入S1和主串S大于最大分配空间,则直接报错,退出程序
printf("\n错误!串超过存储空间!!");
exit(1);
}else{
for(k=s->len-1;k>=i-1;k--){//将第i位开始向后移动S1长度
s->Data[s1->len+k]=s->Data[k];
}
for(k=0;k<s1->len;k++){//将s1插入到串S的第i为处
s->Data[i+k-1]=s1->Data[k];
}
s->len=s->len+s1->len;//修改S串的总长度
s->Data[s->len]='\0';//尾部加结束标志
}
i=s->len;
if(s->len==s->len-s1->len){//判断如果修改后的主串长度与修改前的主串长度相等则直接报错
printf("发错错误!!");
exit(1);
}else{
printf("插入子串后的串:"); //输出插入子串后的串
for(k=0;k<i;k++){
printf("%5c",s->Data[k]);
}
}
}
void StrIndex_BF(String *s,String *t){//子串的定位操作 (模式匹配 BF算法)
printf("创建子串:");
int i=0,j=0,k;
gets(t->Data);
while(t->Data[i]!='\0'){
i++;
}
t->len=i;
i=0;
while(i<s->len&&j<t->len){
if(s->Data[i]==t->Data[j]){//主串元素等子串元素
i++;
j++;
}else{
i=i-j+1;//如果不相等主串元素一项下一个元素,j归零重新比较
j=0;
}
}
if(j>=t->len){//在串S中有串T
k=i-t->len+1;
printf("子串在主串的%d位置!",k);
}else{
printf("主串上并没有找到该子串!");
}
}
void StrIndex_KMP(String *s,String *t){//子串的定位操作 (模式匹配 KMP算法)
printf("创建子串:");
gets(t->Data);
int i,j,l,k;
i=0;
j=1;
int nextval[100];//T的next函数修正值并存入数组nextval
while(t->Data[i]!='\0'){
i++;
}
t->len=i;
l=0;k=1;
nextval[1]=0;
while(k<t->len){
if(l==0||t->Data[k]==t->Data[l]){//t->Data[K]表示后缀,t->Data[l]表示前缀
++l;++k;
if(t->Data[k]!=t->Data[l]){//如果当前字符与前缀不相同
nextval[k]=l;//则修正数组存放当前字符的前缀。
}else{
nextval[k]=nextval[l];//如果与前缀字符相同,则将前缀字符的 nextval值赋值给nextval在i位置的值
}
}
else {
k=nextval[k];
}
}
while(i<s->len&&j<t->len){
if(j==0||s->Data[i]==t->Data[j]){
i++;j++;
}else{
j=nextval[j];
}
}
k=t->len;
j=l=0;
if(i>t->len){
while(j<s->len){
if(s->Data[j]==t->Data[l]&&l<=t->len){
k--;
}
j++;l++;
}
if(k==0){
printf("子串在主串的%d位置!",i-t->len+1);
}else{
printf("主串上并没有找到该子串!");
}
}else{
printf("主串上并没有找到该子串!");
}
}
void StrCompare(String *s,String *s1){
printf("创建对比串:");
gets(s1->Data);
int i=0,floa=0;
while(s1->Data[i]!='\0'){
i++;
}
s1->len=i;
i=0;
if(s->len==s1->len){//判断长度是否相等,相等则进入下一步
while(s->len='\0'){//判断元素是否相等
if(s->Data[i]==s1->Data[i]){
floa++;
}
}
if(floa==s->len==s1->len){
printf("这个两字符串相等。");
}
}else{
printf("两字符串不相等!!");
}
}
void StrCat(String *s,String *t){//两串链接
printf("创建链接串:");
gets(t->Data);
int i=0;
while(t->Data[i]!='\0'){
i++;
}
t->len=i;
if(s->len+t->len<=100){
for(i=s->len;i<s->len+t->len;i++){
s->Data[i]=t->Data[i-s->len];
}
s->Data[i]='\0';
s->len=s->len+t->len;
printf("链接后的串:");
for(i=0;i<s->len;i++){
printf("%5d",s->Data[i]);
}
}else if(s->len+t->len>100&&s->len<100){
for(i=s->len,i<100;i++;){
s->Data[i]=t->Data[i-s->len];
}
s->len=100;
printf("链接后的串:");
for(i=0;i<s->len;i++){
printf("%5c",s->Data[i]);
}
}
else{
printf("出错了!!");
}
}
void Menu(){
printf("\n 字符串系统");
printf("\n---------------------------------------------------------");
printf("\n 1--创建串 ");
printf("\n 2--求子串 ");
printf("\n 3--插入子串 ");
printf("\n 4--删除子串 ");
printf("\n 5--BF算法定位串 ");
printf("\n 6--KMP算法定位串 ");
printf("\n 7--判断两串是否相等 ");
printf("\n 8--两串链接 ");
printf("\n---------------------------------------------------------");
printf("\n请输入 (0-8):");
}
int main(){
String s,s1,Sud,t,v;
char ch1,ch2,a;
ch1='y';
while(ch1=='y'||ch1=='Y'){
Menu();
scanf("%c",&ch2);
getchar();
switch(ch2){
case '1':
Establish(&s);
break;
case '2':
SubString(&s,&Sud);
break;
case '3':
StrInsert(&s,&s1);
break;
case '4':
StrDelete(&s);
break;
case '5':
StrIndex_BF(&s,&t);
break;
case '6':
StrIndex_KMP(&s,&t);
break;
case '7':
StrCompare(&s,&s1);
break;
case '8':
StrCat(&s,&t);
break;
case '0':
ch1='n';
break;
default:
printf("输入错误!!!!");
}
if(ch2!='0'){
printf("\n按回车键继续,按任意键返回\n");
}
a=getchar();
if(a!='\xA'){
getchar();
ch1='n';
}
}
}