数据结构--定长顺序串的c语言实现(超详细注释/实验报告)

数据结构–定长顺序串的c语言实现(超详细注释/实验报告)

知识小回顾

计算机处理的对象分为数值数据和非数值数据,字符串事最基本的非数值数据。字符串处理在语言编译、信息检索、文字编辑等问题中有着广泛的应用。字符串事一种特定的线性表,其特殊性在于组成线性表的每个元素就是一个单字符。

一些定义

字符串:由零个或多个字符组成的有限序列。
子串:串中任意个连续的字符组成的子序列。
字串在主串中的位置:通常是字符在串中的序号称为该字符在串中的位置。字串在主串中的位置则以字串的第一个字符在主串中的位置来表示。
串也是一种特定的线性表,串的逻辑结构和线性表极为相似,其特定性仅在于串的数据对象限定为字符集。

定长顺序串

定长顺序串是将串设计成一种静态结构类型,串的存储分配是在编译时完成的。与之前的线性表的存储结构类似,可以用一组地址连续的存储单元来存储串的字符序列。

实验题目

熟悉串的基本操作:

  1. 求串长
  2. 插入运算
  3. 子串删除
  4. 串连接
  5. 取子串

实验目的

  1. 熟悉串的基本操作

实验要求

  1. 以顺序串作为存储结构;
  2. 实现顺序串求串长操作;
  3. 实现顺序串插入运算操作;
  4. 实现顺序串子串删除操作;
  5. 实现顺序串连接操作;
  6. 实现顺序串取子串操作;

实验内容和实验步骤

1.需求分析

 以菜单的形式作为用户与程序的接口,用户输入菜单号来实行相应的操作。

2. 概要设计

 设计几个函数来实现初始化、插入、删除和查找的功能,然后再主函数中调用函数来实现操作。

3. 详细设计

导入一些库,并定义顺序串的大小以及顺序串中元素的类型。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#define MAXSIZE 255
using namespace std;
typedef char strs[MAXSIZE];
typedef struct
{
    strs str;
    int length;
}SeqString;

顺序串插入操作

  • 在串s中第pos的字符之前插入串t
    在这一部分中,我相比于实验指导,增加了其他几个条件分支,使得程序的鲁棒性更加好。
void StrInsert(SeqString s,int pos,SeqString t)
{
    //printf("insert函数调用开始\n");
//    printf("%d",s.length);
//    printf("%d",t.length);
    int i;
    pos-=1;
    if(pos<0||pos>=s.length)//插入的位置不能小于0也不能大于最大长度
    {
        printf("插入位置不合法\n");
    }
    if(s.length+t.length<=MAXSIZE)//原串加新串的长度小于最大长度
    {
        for(i=s.length+t.length-1;i>=t.length+pos;i--)//目的:把原串的pos之后的部分往后移新串的长度位,初始条件:i=最后一个元素;结束条件:i>=字串长度加要插入的位置
        {
            s.str[i]=s.str[i-t.length];
        }
        for(i=0;i<t.length;i++)//目的:把新串插进去,新串有多长就循环几次(插入几次)
        {
            s.str[i+pos]=t.str[i];//从pos开始插,这里要注意数组索引和人类感知的差异
        }
        s.length=s.length+t.length;//更新串长
    }
    else if(pos+t.length<=MAXSIZE)//插入后后串长>最大长度,不过串t可以全部插入
    {
//        printf("2调用\n");
        for(i=MAXSIZE-1;i>=t.length+pos;i--)//和上面唯一不同的就是初始条件变了,上面是从插入后的最后一个位置开始的,所以既然插入后已经到达最大长度了,那么就直接用最大长度当初始条件就行了
        {
            s.str[i]=s.str[i-t.length];//还是一样的
        }
        for(i=0;i<t.length;i++)//这个和上面是一样的
        {
            s.str[i+pos]=t.str[i];
        }
        s.length=MAXSIZE;//更新长度,这时候就方便一些了
    }
    else//插入后后串长>最大长度,不过串t不可以全部插入
    {
//        printf("3调用\n");
        for(i=0;i<MAXSIZE-pos;i++)//这时候就不用原来串中元素往后移了,最大长度和pos之间有多长,循环就有几次
        {
            s.str[i+pos]=t.str[i];
        }
        s.length=MAXSIZE;//更新长度,这时候就和上面一样方便了
    }
    printf("插入后的串长为:%d\n",s.length);
    printf("插入后的串是:");
    printf("%s\n",s.str);

}

求串长

//求串长操作
int StrLength(SeqString s)
{
    int i=0;
    while(s.str[i]!=0)//元素不为零就加一,一直加到元素为零为止
    {
        i++;
    }
    s.length=i;
    printf("串s的长度为%d\n",s.length);
    return s.length;
}

串连接

int StrConcat(SeqString *s,SeqString t)
{
    int i;
    s->length=strlen(s->str);
    t.length=strlen(t.str);
    if(s->length+t.length>MAXSIZE)
    {
        printf("连接后的串长超过最大长度\n");
        return 0;
    }
    else
    {
        for(i=s->length;i<s->length+t.length;i++)
        {
            s->str[i]=t.str[i-s->length];
        }
    }
    s->length+=t.length;
    printf("两串连接后的长度为%d\n",s->length);
    printf("连接后的串是:%s\n",s->str);
    return 1 ;
}

串删除

//顺序串的删除操作
void StrDelete(SeqString *s,int pos,int len)
{
    int i;
    if(pos>s->length||pos+len-1>s->length)
    {
        printf("删除位置不正确或要删除的字符数量太多了\n");
    }
    else if(pos<0||len<0)
    {
        printf("参数输入有误\n");
    }
    else
    {
        /*for(i=pos-1;i<pos+len-1;i++)
        {
            s->str[i]=s->str[i+len];
        }算法设计有问题*/
        for(i=pos+len-1;i<s->length;i++)
        {
            s->str[i-len]=s->str[i];
        }
        s->length=s->length-len;
        s->str[s->length]='\0';
        printf("删除后的串是:");
        printf("%s\n",s->str);
    }
}

取子串

  • 和串删除有异曲同工之妙
//取子串操作
SeqString *SubString(SeqString s,int pos,int len)
{
    int i;
    SeqString *r;//新开一个r来存储取出的字串
    if(s.length<=0)
    {
        printf("无子串可取!!\n");
        return NULL;
    }
    else
    {
        r=(SeqString *)malloc(sizeof(SeqString));//这个地方最后调试的时候改一下
        for(i=pos-1;i<pos+len-1;i++)
        {
            r->str[i-pos+1]=s.str[i];
            r->length=len;
            r->str[r->length]='\0';
        }
    }
    printf("取出的子串是:");
    printf("%s\n",r->str);
    return r;
}

主函数部分,用一种“菜单”的形式使线性表的操作更加地清晰地展示出来。
在这里插入图片描述

int main()
{
    SeqString x,y;
    char a[MAXSIZE],b[MAXSIZE];
    int a_len,b_len,pos,len,i=1;   
    while(i)//保证一直进行
    {
        printf("-------------------------------------\n");
        printf("             Main Menu         \n");
        printf("    1   求串长    \n");
        printf("    2   插入一个串   \n");
        printf("    3   连接一个串   \n");
        printf("    4   删除子串  \n");
        printf("    5   取子串   \n");
        printf("    6   清屏   \n");
        printf("    0   结束程序      \n");
        printf("--------------------------------------\n");
        printf("请输入你选择的菜单号<1, 2, 3, 4, 5, 6, 0>:\n");
        scanf("%d",&i);
        switch(i)
        {
        case 1:
            printf("请输入串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            //printf("%d",x.length);
            break;
        case 2:
            printf("请输入原来的串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            printf("%d",x.length);
            printf("请输入要插入的新串:");
            scanf("%s",b);
            strcpy(y.str,b);
            y.length=StrLength(y);
            printf("%d",y.length);
            printf("请输入要插入的位置:");
            scanf("%d",&pos);
            StrInsert(x,pos,y);
            break;
        case 3:
            printf("请输入前串:");
            scanf("%s",a);
            strcpy(x.str,a);
            //StrLength(x);
            x.length=StrLength(x);
            printf("请输入后串:");
            scanf("%s",b);
            strcpy(y.str,b);
            y.length=StrLength(y);
            StrConcat(&x,y);
            break;
        case 4:
            printf("请输入串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            printf("从什么地方开始删除?\n");
            scanf("%d",&pos);
            printf("要删除多长的子串?\n");
            scanf("%d",&len);
            StrDelete(&x,pos,len);
            break;
        case 5:
            printf("请输入串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            printf("从什么地方开始取子串?\n");
            scanf("%d",&pos);
            printf("要取出多长的子串?\n");
            scanf("%d",&len);
            SubString(x,pos,len);
            break;
        case 6:
            system("cls");
            break;
        case 0:
            exit(0);
            break;
        default:
            printf("输入有误~");
        }
    }
    return 0;
}

4. 调试分析

遇到的问题及解决方法
  • 一开始插入操作一直有问题,每一次都是按最后一个else来执行的,之后试了一些数据,并仔细检查后发现,串的length没有值,所以后来个所有串都加了一个串.length=StrLength(串)。
算法的时空分析
  • 顺序串比较简单,都是依托着数组来实现的,所以整体难度不大,最多也就一层循环
实验结果

实验结果很不错,所有操作都能正常执行,还使串插入更加的健壮,并且自己加入了“清屏”选项,使得界面更加的整洁。

实验总结

顺序串需要注意的细节很多,多多重复,百炼成钢!

最后附上完整的代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<malloc.h>
#define MAXSIZE 255
using namespace std;
typedef char strs[MAXSIZE];
typedef struct
{
    strs str;
    int length;
}SeqString;

//顺序串插入操作
//在串s中第pos的字符之前插入串t
void StrInsert(SeqString s,int pos,SeqString t)
{
    //printf("insert函数调用开始\n");
//    printf("%d",s.length);
//    printf("%d",t.length);
    int i;
    pos-=1;
    if(pos<0||pos>=s.length)//插入的位置不能小于0也不能大于最大长度
    {
        printf("插入位置不合法\n");
    }
    if(s.length+t.length<=MAXSIZE)//原串加新串的长度小于最大长度
    {
        for(i=s.length+t.length-1;i>=t.length+pos;i--)//目的:把原串的pos之后的部分往后移新串的长度位,初始条件:i=最后一个元素;结束条件:i>=字串长度加要插入的位置
        {
            s.str[i]=s.str[i-t.length];
        }
        for(i=0;i<t.length;i++)//目的:把新串插进去,新串有多长就循环几次(插入几次)
        {
            s.str[i+pos]=t.str[i];//从pos开始插,这里要注意数组索引和人类感知的差异
        }
        s.length=s.length+t.length;//更新串长
    }
    else if(pos+t.length<=MAXSIZE)//插入后后串长>最大长度,不过串t可以全部插入
    {
//        printf("2调用\n");
        for(i=MAXSIZE-1;i>=t.length+pos;i--)//和上面唯一不同的就是初始条件变了,上面是从插入后的最后一个位置开始的,所以既然插入后已经到达最大长度了,那么就直接用最大长度当初始条件就行了
        {
            s.str[i]=s.str[i-t.length];//还是一样的
        }
        for(i=0;i<t.length;i++)//这个和上面是一样的
        {
            s.str[i+pos]=t.str[i];
        }
        s.length=MAXSIZE;//更新长度,这时候就方便一些了
    }
    else//插入后后串长>最大长度,不过串t不可以全部插入
    {
//        printf("3调用\n");
        for(i=0;i<MAXSIZE-pos;i++)//这时候就不用原来串中元素往后移了,最大长度和pos之间有多长,循环就有几次
        {
            s.str[i+pos]=t.str[i];
        }
        s.length=MAXSIZE;//更新长度,这时候就和上面一样方便了
    }
    printf("插入后的串长为:%d\n",s.length);
    printf("插入后的串是:");
    printf("%s\n",s.str);

}

//求串长操作
int StrLength(SeqString s)
{
    int i=0;
    while(s.str[i]!=0)//元素不为零就加一,一直加到元素为零为止
    {
        i++;
    }
    s.length=i;
    printf("串s的长度为%d\n",s.length);
    return s.length;
}


//串连接操作
int StrConcat(SeqString *s,SeqString t)
{
    int i;
    s->length=strlen(s->str);
    t.length=strlen(t.str);
    if(s->length+t.length>MAXSIZE)
    {
        printf("连接后的串长超过最大长度\n");
        return 0;
    }
    else
    {
        for(i=s->length;i<s->length+t.length;i++)
        {
            s->str[i]=t.str[i-s->length];
        }
    }
    s->length+=t.length;
    printf("两串连接后的长度为%d\n",s->length);
    printf("连接后的串是:%s\n",s->str);
    return 1 ;
}

//顺序串的删除操作
void StrDelete(SeqString *s,int pos,int len)
{
    int i;
    if(pos>s->length||pos+len-1>s->length)
    {
        printf("删除位置不正确或要删除的字符数量太多了\n");
    }
    else if(pos<0||len<0)
    {
        printf("参数输入有误\n");
    }
    else
    {
        /*for(i=pos-1;i<pos+len-1;i++)
        {
            s->str[i]=s->str[i+len];
        }算法设计有问题*/
        for(i=pos+len-1;i<s->length;i++)
        {
            s->str[i-len]=s->str[i];
        }
        s->length=s->length-len;
        s->str[s->length]='\0';
        printf("删除后的串是:");
        printf("%s\n",s->str);
    }
}

//取子串操作
SeqString *SubString(SeqString s,int pos,int len)
{
    int i;
    SeqString *r;//新开一个r来存储取出的字串
    if(s.length<=0)
    {
        printf("无子串可取!!\n");
        return NULL;
    }
    else
    {
        r=(SeqString *)malloc(sizeof(SeqString));//这个地方最后调试的时候改一下
        for(i=pos-1;i<pos+len-1;i++)
        {
            r->str[i-pos+1]=s.str[i];
            r->length=len;
            r->str[r->length]='\0';
        }
    }
    printf("取出的子串是:");
    printf("%s\n",r->str);
    return r;
}

int main()
{
    SeqString x,y;
    char a[MAXSIZE],b[MAXSIZE];
    int a_len,b_len,pos,len,i=1;
    while(i)//保证一直进行
    {
        printf("-------------------------------------\n");
        printf("             Main Menu         \n");
        printf("    1   求串长    \n");
        printf("    2   插入一个串   \n");
        printf("    3   连接一个串   \n");
        printf("    4   删除子串  \n");
        printf("    5   取子串   \n");
        printf("    6   清屏   \n");
        printf("    0   结束程序      \n");
        printf("--------------------------------------\n");
        printf("请输入你选择的菜单号<1, 2, 3, 4, 5, 6, 0>:\n");
        scanf("%d",&i);
        switch(i)
        {
        case 1:
            printf("请输入串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            //printf("%d",x.length);
            break;
        case 2:
            printf("请输入原来的串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            printf("%d",x.length);
            printf("请输入要插入的新串:");
            scanf("%s",b);
            strcpy(y.str,b);
            y.length=StrLength(y);
            printf("%d",y.length);
            printf("请输入要插入的位置:");
            scanf("%d",&pos);
            StrInsert(x,pos,y);
            break;
        case 3:
            printf("请输入前串:");
            scanf("%s",a);
            strcpy(x.str,a);
            //StrLength(x);
            x.length=StrLength(x);
            printf("请输入后串:");
            scanf("%s",b);
            strcpy(y.str,b);
            y.length=StrLength(y);
            StrConcat(&x,y);
            break;
        case 4:
            printf("请输入串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            printf("从什么地方开始删除?\n");
            scanf("%d",&pos);
            printf("要删除多长的子串?\n");
            scanf("%d",&len);
            StrDelete(&x,pos,len);
            break;
        case 5:
            printf("请输入串:");
            scanf("%s",a);
            strcpy(x.str,a);
            x.length=StrLength(x);
            printf("从什么地方开始取子串?\n");
            scanf("%d",&pos);
            printf("要取出多长的子串?\n");
            scanf("%d",&len);
            SubString(x,pos,len);
            break;
        case 6:
            system("cls");
            break;
        case 0:
            exit(0);
            break;
        default:
            printf("输入有误~");
        }
    }
    return 0;
}
  • 4
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值