/*郭睿玥第五次算法实验作业*/
/*实验原理
串的堆存储结构,与定长顺序串的存储结构类似,都是用一维数组地址连续的存储单元存储串
的字符序列,不同的是堆串的存储空间是在程序执行过程中动态分配的。
在系统中存在一个称为“堆”的自由存储区,每当建立一个新串时,可以通过动态分配函数从
这个空间中分配一块实际串所需的存储空间,来存储新的串值。只要空间能分配成功,则在操作的
过程中就不会发生“截断”的情况。C语言采用malloc()、free()等函数完成动态存储管理。
*/
/*实验环境
CodeBlocks*/
/*实验目的
1. 了解顺序串的结构特点及有关概念;
2. 理解顺序串的存储结构;
3. 掌握顺序串的基本操作算法。
*/
/*实验内容
建立顺序串,完成顺序串的基本操作:初始化、求串长、串赋值、串连接、求子串、串比较、字串定位、串插入、子串删除、串替换、串清空、串输出等。
*/
#include
#include
#include
#define MAXSIZE 100
typedef int Status;// 定义函数返回值类型
typedef char ElemType; // 定义每条数据的结构体类型
typedef struct{//定义串
char *stri;//若不是空串则按照串长度分配空间,否则为NULL
int length;//串长
}string;//别名
Status insitstring(string * SS){//初始化
SS->stri =NULL;//空串不分配空间
SS->length = 0;//空串串长为0
return 1;
}
Status lengthstring(string * SS)//求串长
{
return SS->length;//返回SS的元素个数,串长度包含在数据结构中因此直接返回即可
}
void StrAssign(string *SS,char str1[])//串赋值
{
int i,j;
if (SS->length)//如果不是空串则清空需要赋值的串
free(SS); //清空操作
for(i=0;str1[i]!=NULL;i++)//循环查找所要赋值的字符数组,直到字符数组的某个元素为空,循环次数就是串长度
{
;
}
SS->length=i;//串长度赋值
if(i){
SS->stri=(char*)malloc(SS->length*sizeof(char*));//根据串长度申请空间
if(!SS->stri)//如果分配失败则结束
exit(-1);//退出
for(j=0;jlength;j++)//通过循环逐个元素赋值,j表示循环次数,也表示被赋值的元素下标
{
SS->stri[j]=str1[j];//赋值操作
}
}
else {//如果输入的字符数组不合理则重新输入
printf("请重新输入\n");//提示
char ch1[MAXSIZE];//新建数组
gets(ch1);//输入
StrAssign(SS,ch1);//递归调用赋值函数
}
return 0;//程序结束返回
}
void printstring(string T)//串输出
{
int i;
for(i=0;istri=(char*)realloc(SS->stri,(SS->length+S->length )*sizeof(char));//根据需要连接的两个穿分配空间
if(!SS->stri)//如果分配失败则结束
{
printf("分配空间失败");//提示
exit(-1);//退出
}
else{//如果成功,则通过循环,按照顺序一个个把S的元素增加到SS内,i表示S下标,j表示SS下标
for(i=0,j=SS->length;ilength;i++,j++)//循环,一共执行S->length次
SS->stri[j]=S->stri[i];//赋值
SS->length+=S->length;//改变串长
}
return 1;//返回
}
Status comparestring(string * SS,string *S)//串比较
{
int i,j;
if(SS->length!=S->length)//首先比较串长,如果两个串的串长不一致比较无意义,故不进行比较
{
printf("两个串的长度不一致无法比较\n");//提示
return 5;//返回
}
for(i=0;ilength;i++)//通过循环,按照顺序逐个比较知道找到第一个两个串不一样的元素
{
if(SS->stri[i]>S->stri[i])//如果SS的第i个元素大,则返回1
return 1;
if(SS->stri[i]stri[i])//如果S的第i个元素大,则返回
return -1;
//如果两个一样大则循环继续
}
return 0;
}
void clearstring(string * SS)//串清空
{
if (SS->stri)//如果不是空串则清空需要赋值的串
free(SS);//清空操作
insitstring(SS);//调用初始化函数
printf("清空成功");//提示
return 0;//返回
}
Status emptystring(string * SS)//串判空
{
if (SS->length = 0) //空串的串长为0可以直接判断
return 0; //空串返回0
return 1;//非空串返回1
}
Status insertstring(string * SS,string * S,int pos)//串插入
{
if(pos < 0||pos-1>SS->length)//判断插入位置是否合法
{
printf("插入位置不正确\n");//提示
return 0;//由于插入的位置不合法故函数无法进行
}
int i=SS->length-1,j=i+S->length,k;
SS->stri=(char*)realloc(SS->stri,(SS->length+S->length )*sizeof(char));//根据需要连接的两个穿分配空间
if(!SS->stri)//如果分配失败则结束
{
printf("内存分配失败");//提示
exit(-1);//退出
}
for(k=0;klength-pos+1;i--,j--,k++)//通过循环,从后往前一直到要插入的位置的串元素依次后移
SS->stri[j]=SS->stri[i];//后移操作
for(i=0,j=pos-1;ilength;i++,j++)//通过循环,从要插入串的位置开始,依次赋值
SS->stri[j]=S->stri[i];//赋值
SS->length=SS->length+S->length;//改变串长
printf("插入后的串为");//提示
printstring(*SS);//调用输出函数输出插入后的串
return 0;
}
Status findstring(string * substr,string SS,int pos,int len)//截取子串
{
int i;
if(!substr->stri)//如果不是空串则清空串
free(substr->stri);//清空操作
else
{
substr->stri=(char*)malloc(len*sizeof(char));//为子串分配空间
if(!substr->stri)//如果分配失败则结束
{
printf("存储分配失败");//提示
exit(-1);//退出
}
for(i=0;istri[i]=SS.stri[i+pos-1];//逐个元素截取
substr->length=len;//子串长度就是参数中的len
return 1;//返回
}
}
Status searchsub(string * SS,string substr)//子串定位
{
int i=1,j=0,k;
do{
if(substr.stri[0]==SS->stri[j])//如果SS中存在子串则substr的第一个元素一定和ss的某个元素相等,如果相等往下比较,不相等ss后移
{
k=j+1;
while(istri[k])//如果当前元素和子串的元素不一致则跳出循环
{
i=1;//返回初始状态方便下一次判断
j++;//j后移
break;//跳出循环
}
else {//如果一直接着判断下一个元素
i++;
k++;
}
}
if(i==substr.length)//判断是否进行完毕
break;//循环结束
}
else
j++;//如果SS中的第j个元素和子串中第0个元素不等则j后移
}while(jlength);//循环条件
if(j==SS->length)//如果j能等于SS的串长则没有这个子串
{
printf("没有这个子串");//提示
return -1;//返回
}
printf("字串位于第%d\n",j+1);//输出子串位置
return j+1;//返回子串位置
}
void deletesub(string* SS,string substr,int pos)//子串删除
{
int i,len;
char *p;//定义一个指针
len=substr.length;
if(pos<0||len<0||pos+len-1>SS->length)//判断删除位置是否合法
{
printf("删除位置不正确\n");//提示
return 0;//由于删除的位置不合法故函数无法进行
}
p=(char*)malloc(SS->length-len);//根据需要删除的子串分配空间
if(!p)//如果分配失败则结束
exit(-1);//退出
for(i=0;istri[i];
for(i = pos-1;i < SS->length-len;i++)//将串第pos+len位置以后的字符复制到p中
p[i] = SS->stri[i+len];//逐个元素复制
SS->length=SS->length-len;//修改串的长度
free(SS->stri);//释放原来的串S的内存空间
SS->stri=p;//将串的str指向p字符串
return 1;//返回
}
void repalcesub(string * SS,string substr,string*S)//串替换,用S替换串SS中的所有子串substr
{
int i=0,j;
if(substr.length==0)//判断要替换的串是否是空串
return 0;//返回
do{//通过循环替换所有子串
i=searchsub(SS,substr);//通过调用定位函数找到子串位置
if(i==-1)//如果没有这个子串结束
return 0;//返回
insertstring(SS,S,i);//在找到的位置里插入要替换的子串
j=i+S->length;//j表示要被替换子串当前的位置
deletesub(SS,substr,j);//根据位置删除要被替换的子串
printf("现在s1为");//提示
printstring(*SS);//输出替换后的SS
}while(i!=-1);
}
int main()
{
char ch[MAXSIZE];
string S1,S2,sub;//建立两个串
int postion,length;//位置和长度
printf("请输入S1\n");//提示
gets(ch);//输入S1的串数据
insitstring(&S1);//初始化S1
StrAssign(&S1,ch);//用输入的字符数组为S1赋值
printf("请输入S2\n");//提示
gets(ch);//输入S2的串数据
insitstring(&S2);//初始化S2
StrAssign(&S2,ch);//用输入的字符数组为S1赋值
printf("s1为");//提示
printstring(S1);//输出S1
printf(",长度为%d\n",lengthstring(&S1));//输出S1长度
printf("s2为");//提示
printstring(S2);//输出S2
printf(",长度为%d\n",lengthstring(&S2));//输出S2长度
if(comparestring(&S1,&S2)==0)//通过比较函数的返回值比较S1,S2是否相等
printf("两者相等\n");//提示
if(comparestring(&S1,&S2)==1)//通过比较函数的返回值比较S1,S2是否相等
printf("s1大\n");//提示
if(comparestring(&S1,&S2)==-1)//通过比较函数的返回值比较S1,S2是否相等
printf("s2大\n");//提示
//有关插入的一系列操作
printf("请输入你想插入的位置\n");//提示
scanf("%d",&postion);//输入位置
insertstring(&S1,&S2,postion);//调用插入函数
//有关连接的一系列操作
constring(&S1,&S2);//调用连接函数
printf("连接后的子串为");//提示
printstring(S1);//输出S1
printf(",长度为%d\n",lengthstring(&S1));//输出S1现在长度
//有关截取子串的一系列操作
printf("截取子串\n");//提示
printf("请输入截取子串的位置\n");//提示
scanf("%d",&postion);//输入要截取的起始位置
printf("请输出字串长度\n");//提示
scanf("%d",&length);//输入要截取的长度
while(postion<0||length<0||postion+length-1>S1.length)//判断截取的子串是否合法
{
printf("无法插入请重新输入\n");//提示
printf("请输入截取子串的位置\n");//提示
scanf("%d",postion);//重新输入位置
printf("请输出字串长度\n");//提示
scanf("%d",length);//重新输入长度
}
findstring(&S2,S1,postion,length);//调用截取子串函数
printf("该字串为");//提示
printstring(S2);
//有关子串删除的一系列操作
printf("字串删除\n");//提示
printf("首先,字串定位\n");//提示
postion=searchsub(&S1,S2);//调用函数寻找第一个子串位置
deletesub(&S1,S2,postion);//根据刚才的位置删除子串
printf("现在s1为");//提示
printstring(S1);//输出现在的S1
//有关子串替换的一系列操作
printf("把S1的子串替换为\n");//提示
gets(ch);//输入要替换的数据
insitstring(&sub);//初始化sub
StrAssign(&sub,ch);//赋值
printf("替换为\n");//提示
printstring(sub);//打印子串
repalcesub(&S1,S2,&sub);//调用替换子串函数
return 0;
}
/*实验结果
请输入S1
ILIKECHINA
请输入S2
CHINA
s1为ILIKECHINA
,长度为10
s2为CHINA
,长度为5
两个串的长度不一致无法比较
两个串的长度不一致无法比较
两个串的长度不一致无法比较
请输入你想插入的位置
4
插入后的串为ILICHINAKECHINA
连接后的子串为ILICHINAKECHINACHINA
,长度为20
截取子串
请输入截取子串的位置
4
请输出字串长度
4
该字串为CHIN
字串删除
首先,字串定位
字串位于第4
现在s1为ILIAKECHINACHINA
把S1的子串替换为
请重新输入
abc
替换为
abc
字串位于第7
插入后的串为ILIAKEabcCHINACHINA
现在s1为ILIAKEabcACHINA
字串位于第11
插入后的串为ILIAKEabcAabcCHINA
现在s1为ILIAKEabcAabcA
没有这个子串
*/