zoukankan      html  css  js  c++  java
  • 串String(1):串的实现(定长顺序存储结构)

    前言


    PS:本文相关头文件、预编译以及typedef如下,阅读一遍以便于下面的理解:  

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAXSTRLEN 40
    #define OK 1
    #define ERROR 0
    #define TURE 1
    #define FALSE 0
    #define OVERFLOW -2
    
    typedef int Status;
    typedef char SString[MAXSTRLEN+1];
    

       

    ADT


      

      串是一个重要的数据结构,我在这里实现串的ADT如下:

      

      

    串的结构概念图


      

      我定义了一个数组,0位存储字符长度,1到MAX位存储字符。这和传统的gets();函数或者 scanf(%s,);函数实现的串是有区别的,所以我封装了一个串赋值函数去实现两种串结构之间的转化,代码如下: 

    /* 字符串赋值,当赋值字符串长度超过被赋值字符串时候截断,未超过时先将长度存入T[0],再逐位赋值 */
    Status StrAssign(SString T,char *chars)
    {
            int i;
            if(strlen(chars)>MAXSTRLEN)
            {
                    for(i = 1;i <= MAXSTRLEN;i++)
                    {
                            T[i] = *(chars + i - 1);
                    }
                    T[0] = MAXSTRLEN;  //T[0]存入int 型数据,%s无法打印
            }
            else
            {
                    T[0] = strlen(chars);  //T[0]存入的是chars的字符长度
                    for(i = 1;i <= strlen(chars);i++)
                    {
                            T[i] = *(chars + i - 1);
                    }
            }
            return OK;
    }
    

      

    功能函数算法难点


     

      我认为其中的StrIndex();索引子串函数是相对难理解一些的。其函数功能是:索引子串,返回串T中第一个索引到与串S相同的子串的位置。算法思路图如下:

        

      尤其要注意,当T[i] != S[j]时,需要将i指针置于上次相同时的下一个位置,代码实现为 i = i - j + 2,而不是i++

      该模块函数封装代码如下:  

    /*  索引子串,返回串T中第一个索引到与串S相同的子串的位置  */
    Status StrIndex(SString T,SString S,int *pos)
    {
            int i=1,j=1;
            while((i <= T[0]) && (j <= S[0]))
            {
                    if(T[i] == S[j])
                    {
                            i++;
                            j++;
                    }
                    else
                    {
                            i = i - j + 2;
                            j = 1;
                    }
            }
            if(j > S[0])
            {
                    *pos = i - j + 1;
                    printf("Found,position is %d
    ",*pos);
                    return OK;
            }
            else
            {
                    printf("NOT find child string yet.
    ");
                    return ERROR;
            }
    }
    

      其次,StrInsert();插入函数中也比较难想,因为其需要讨论插入位置以及插入后长度是否越界问题,设计算法时易漏了其中某一个情况。

      该模块函数封装代码如下:

    /*  在串T的第pos个位置后插入子串S  */
    Status StrInsert(SString T,SString S,int pos)
    {
            int i;
            if(pos > T[0])
            {
                    pos = T[0] +1;
            }
            if(T[0] + S[0] <= MAXSTRLEN)
            {
                    for(i = 1; i <= pos;i++)
                            T[T[0] + S[0] - i +1] = T[T[0] + S[0] - i -pos];
                    for(i = 1;i <= S[0];i++)
                            T[pos + i] = S[i];
                    T[0] = T[0] + S[0];
                    return OK;
            }
            if(T[0] + S[0] > MAXSTRLEN)
            {
                    for(i = 1;i <= (MAXSTRLEN - pos);i++)
                            T[i + pos] = S[i];  //超出部分被删除
                    T[0] = MAXSTRLEN;
                    return ERROR;
            }
    }
    

      

    代码


    /*************************************************************************
    	> File Name: String fuctions
    	> Author: Bw98
    	> Mail: 786016746@qq.com
    	> Blog: www.cnblogs.com/Bw98blogs/
    	> Created Time: SUN 23th Jul. 2017
     ************************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define MAXSTRLEN 40
    #define OK 1
    #define ERROR 0
    #define TURE 1
    #define FALSE 0
    #define OVERFLOW -2
    
    typedef int Status;
    typedef char SString[MAXSTRLEN+1];
    
    Status StrEmpty(SString S);
    Status StrAssign(SString T,char *chars);
    Status StrCopy(SString T,SString S);
    Status StrLength(SString T);
    Status StrPrint(SString T);
    Status StrClear(SString S);
    Status StrConcat(SString T,SString S1,SString S2);
    Status StrIndex(SString T,SString S,int *pos);
    Status StrInsert(SString T,SString S,int pos);
    Status StrDelete(SString T,int pos,int len);
    
    int main()
    {
            /*  根据功能自行调用  */
            return 0;
    }
    
    /* 字符串赋值,当赋值字符串长度超过被赋值字符串时候截断,未超过时先将长度存入T[0],再逐位赋值 */
    Status StrAssign(SString T,char *chars)
    {
            int i;
            if(strlen(chars)>MAXSTRLEN)
            {
                    for(i = 1;i <= MAXSTRLEN;i++)
                    {
                            T[i] = *(chars + i - 1);
                    }
                    T[0] = MAXSTRLEN;  //T[0]存入int 型数据,%s无法打印
            }
            else
            {
                    T[0] = strlen(chars);  //T[0]存入的是chars的字符长度
                    for(i = 1;i <= strlen(chars);i++)
                    {
                            T[i] = *(chars + i - 1);
                    }
            }
            return OK;
    }
    
    /* 字符串拷贝,逐个字符拷贝(仅拷贝长度范围内的) */
    Status StrCopy(SString T,SString S)
    {
            int i;
            for(i = 1;i <= S[0];i++)
            {
                    T[i] = S[i];
            }
            T[0] = S[0];
            return OK;
    }
    
    /*  字符串判空,S[0] == 0时为空  */
    Status StrEmpty(SString T)
    {
            if(T[0] == 0)
            {
                    printf("The string is empty!
    ");
                    return TURE;
            }
            else
            {
                    printf("The string is NOT empty!
    ");
                    return FALSE;
            }
    }
    
    /*  返回该字符串的长度  */
    Status StrLength(SString T)
    {
            return T[0];
    }
    
    /*  打印字符串  */
    Status StrPrint(SString T)
    {
            int i;
            for(i = 1;i <= T[0];i++)
                    printf("%c",T[i]);
            printf("
    ");
            return OK;
    }
    /*  清除字符串,即长度清空 */
    Status StrClear(SString S)
    {
            S[0] = 0;
            return OK;
    }
    
    /*  字符串联接,通过T来存储结果,S2连接而成的新串,若未截断则返回TRUE,截断返回FAlSE,注意字符串数组越界问题  */
    Status StrConcat(SString T,SString S1,SString S2)
    {
            int i;
            if(S1[0]+S2[0] <= MAXSTRLEN)
            {
                    for(i = 1;i <= S1[0];i++)
                    {
                            T[i] = S1[i];
                    }
                    for(i = 1;i <= S2[0];i++)
                    {
                            T[S1[0]+i] = S2[i];
                    }
                    T[0] = S1[0] + S2[0];
                    return TURE;
            }
            else
            {
                    for(i = 1;i <= S1[0];i++)
                    {
                            T[i] = S1[i];
                    }
                    for(i = 1;i <= (MAXSTRLEN-S1[0]);i++)
                    {
                            T[S1[0]+i] = S2[i];
                    }
                    T[0] = MAXSTRLEN;
                    return FALSE;
            }
    }
    
    /*  索引子串,返回串T中第一个索引到与串S相同的子串的位置  */
    Status StrIndex(SString T,SString S,int *pos)
    {
            int i=1,j=1;
            while((i <= T[0]) && (j <= S[0]))
            {
                    if(T[i] == S[j])
                    {
                            i++;
                            j++;
                    }
                    else
                    {
                            i = i - j + 2;
                            j = 1;
                    }
            }
            if(j > S[0])
            {
                    *pos = i - j + 1;
                    printf("Found,position is %d
    ",*pos);
                    return OK;
            }
            else
            {
                    printf("NOT find child string yet.
    ");
                    return ERROR;
            }
    }
    
    /*  在串T的第pos个位置后插入子串S  */
    Status StrInsert(SString T,SString S,int pos)
    {
            int i;
            if(pos > T[0])
            {
                    pos = T[0] +1;
            }
            if(T[0] + S[0] <= MAXSTRLEN)
            {
                    for(i = 1; i <= pos;i++)
                            T[T[0] + S[0] - i +1] = T[T[0] + S[0] - i -pos];
                    for(i = 1;i <= S[0];i++)
                            T[pos + i] = S[i];
                    T[0] = T[0] + S[0];
                    return OK;
            }
            if(T[0] + S[0] > MAXSTRLEN)
            {
                    for(i = 1;i <= (MAXSTRLEN - pos);i++)
                            T[i + pos] = S[i];  //超出部分被删除
                    T[0] = MAXSTRLEN;
                    return ERROR;
            }
    }
    
    /*  删除串T的第pos个位置起,长为len的子串  */
    Status StrDelete(SString T,int pos,int len)
    {
            int i;
            if(pos > T[0])
                    return ERROR;
            if(len > T[0])
                    len = T[0] - pos + 1;
            for(i = len + pos;i <= T[0];i++)
                    T[i - len] =T[i];
            T[0] = T[0] - len;
            return OK;
    }
    

      

    ————全心全意投入,拒绝画地为牢
  • 相关阅读:
    2020年,初级、中级 Android 工程师可能因离职而失业吗?
    Android 后台运行白名单,优雅实现保活
    使用DataBinding还在为数据处理头疼?这篇文章帮你解决问题
    Android 7.x Toast BadTokenException处理
    2017-2020历年字节跳动Android面试真题解析(累计下载1082万次,持续更新中)
    Flutter 尺寸限制类容器总结:这可能是全网解析最全的一篇文章,没有之一!
    并行收集器
    高性能索引策略
    Innodb简介
    索引的优点
  • 原文地址:https://www.cnblogs.com/Bw98blogs/p/7225114.html
Copyright © 2011-2022 走看看