导航

堆分配存储表示的串其基本操作的实现

Posted on 2015-09-18 01:15  CSU蛋李  阅读(2308)  评论(0编辑  收藏  举报

以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配而得。

下面是基本操作的头文件

#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define MYOVERFLOW -2
typedef int Status;


//-------串的堆分配存储表示---------
typedef struct{
    char *ch;   //若是非空串,则按串长分配存储区,否则ch为NULL
    int length; //串长度
}HString;

//------基本操作的函数原型说明--------

Status StrAssign(HString &T, char *chars);//生成一个其值等于串常量chars的串T

int StrLength(HString S);//返回S的元素个数,称为串的长度

int StrCompare(HString S, HString T);//若S>T,则返回值>0;若S==T,则返回值为0,若S<T,则返回值<0

Status ClearString(HString &S);//将S清为空串,并释放S所占空间

Status Concat(HString &T, HString S1, HString S2);//用串T返回由S1和S2联接而成的新串

Status SubString(HString &Sub,HString S, int pos, int len);
//1<=pos<<StrLength(S)且0<=len<=StrLength(S)-pos+1
//返回串S的第pos个字符起长度为len的子串

Status StrCopy(HString &T, HString S);//串S存在,由串S复制得到串T

Status StrEmpty(HString S);//串S存在,若S为空串,则返回TRUE,否则返回FALSE

int Index(HString S, HString T, int pos);
//串S和串T存在,T是非空串,1<=pos<<Strlength(s).若主串S中存在和串T值相同的子串,则返回
//它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0;

Status Replace(HString &S, HString T, HString V);
//串S,T和V存在,T是非空串
//用V替换主串S中出现的所有与T相等的不重叠的子串

Status StrInsert(HString &S, int pos, HString T);
//串S和T存在,1<=pos<<Strlength(S)+1.在串S的第pos个字符之前插入串T

Status StrDelete(HString &S, int pos, int len);
//串S存在,1<=pos<<Strlength(S)-len+1。从串S中删除第pos个字符起长度为len的子串

Status DestroyString(HString &S);
//串S存在,串S被销毁
                                   

上述基本操作的实现:

#include"stdafx.h"

Status StrAssign(HString &T, char *chars)//生成一个其值等于串常量chars的串T
{
    if (T.length > 0)delete T.ch;//如果T存在值,则删除T以前所占空间
    int i = 0;
    for (char *c = chars; *c; ++c, ++i){}//求chars的长度
    if (!i){ T.ch = NULL; T.length = 0; }
    else{
        if (!(T.ch = (char *)malloc((i+1)*sizeof(char))))//为T分配i+1个空间,最后一个空间储存NULL是为了操作方便
            exit(MYOVERFLOW);
        for (int j = 0; j < i; j++)//将chars[]的值传给T
            T.ch[j] = chars[j];
        T.ch[i] = NULL;
        T.length = i;        //T.length=i;
    }
    return OK;
} 

int StrLength(HString S)//返回S的元素个数,称为串的长度
{
    return S.length;
}

int StrCompare(HString S, HString T)//若S>T,则返回值>0;若S==T,则返回值为0,若S<T,则返回值<0
{
    for(int i=0;i<S.length&&i<T.length;i++)
    if (*(S.ch+i) != *(T.ch+i))//如果在未达到其中一个字符串的末端就有不等的,则返回第一个不相等的两字符之差
    return *(S.ch) - *(T.ch);

    return S.length - T.length;//如果全部相等,则返回字符串长度之差
}

Status ClearString(HString &S)//将S清为空串,并释放S所占空间
{
    if (S.length)
    delete S.ch;//删除S所占空间
    S.ch = NULL;
    S.length = 0;
    return OK;
}

Status Concat(HString &T, HString S1, HString S2)//用串T返回由S1和S2联接而成的新串
{
    if (T.length > 0)delete T.ch;
    T.ch = (char *)malloc((S1.length + S2.length+1)*sizeof(char));//为T分配空间,最后一个空间储存NULL是为了操作方便
    if (!T.ch)exit(MYOVERFLOW);
    int i = 0;
    for (; i < S1.length; i++)//将S1的值传给T
        T.ch[i] = S1.ch[i];
    for (int j = 0; i < S1.length + S2.length; i++, j++)//将S2的值传给T
        T.ch[i] = S2.ch[j];
    T.ch[i] = NULL;
    T.length = S1.length + S2.length;
    return OK;
}

Status SubString(HString &sub, HString S, int pos, int len)
//1<=pos<<StrLength(S)且0<=len<=StrLength(S)-pos+1
//返回串S的第pos个字符起长度为len的子串
{
    if (sub.length > 0)delete sub.ch;
    if (len == 0){
        sub.ch = NULL;
        sub.length = len;
    }
    else{
        
        if (pos >= 1 && pos <= S.length&&len > 0 && len <= S.length - pos + 1)
        {
            sub.ch = (char *)malloc(len+1*sizeof(char));//为子串分配空间
            if (!sub.ch)exit(MYOVERFLOW);
            for (int i = 0; i < len; i++, pos++)//将相对应的字符传给子串
                sub.ch[i] = S.ch[pos-1];
            sub.ch[len] = NULL;
            sub.length = len;
            return OK;
        }
    }
     return ERROR;
}

Status StrCopy(HString &T, HString S)//串S存在,由串S复制得到串T
{
    if (T.length > 0)delete T.ch;
    if (S.length < 0)return ERROR;
    else{
        if (S.length == 0){
            T.ch = NULL;
            T.length = 0;
            return OK;
        }
        T.ch = (char *)malloc((S.length + 1)*sizeof(char));//为T分配空间
        for (int i = 0; i <= S.length; i++)//将S的值传给T
            T.ch[i] = S.ch[i];
        T.length = S.length;
        return OK;
    }
}

Status StrEmpty(HString S)//串S存在,若S为空串,则返回TRUE,否则返回FALSE
{
    if (S.length == 0)return FALSE;
    else return TRUE;
}

int Index(HString S, HString T, int pos)
//串S和串T存在,T是非空串,1<=pos<<Strlength(s).若主串S中存在和串T值相同的子串,则返回
//它在主串S中第pos个字符之后第一次出现的位置;否则函数值为0;
{
    if (T.length == 0)return 0;
    pos++;
    for (; pos + T.length-1 <= S.length; pos++)
    {
        HString sub;
        SubString(sub, S, pos, T.length);//求长度相等的子串
        if (StrCompare(T, sub) == 0)return pos;//如果该子串与T相等,则返回第一次出现的位置
    }
    return 0;
}

Status Replace(HString &S, HString T, HString V)
//串S,T和V存在,T是非空串
//用V替换主串S中出现的所有与T相等的不重叠的子串
{
    if (T.length <= 0)return ERROR;
    for (int i = 0; i <= S.length - T.length; ){
        int j = 0;
        if (j = Index(S, T, i)){//如果S中存在于T相等的子串,则用V替换T
            HString sub1,sub2,temp;
            SubString(sub1, S, 1, j - 1);//求T之前的子串
            Concat(temp, sub1, V);       //将前子串与V相连保存在temp中
            if (SubString(sub2, S, j + T.length, S.length - T.length - j + 1))//求T之后的子串,如果T恰好在S的末尾,则不执行下面的操作
            {
                Concat(S, temp, sub2);//将temp和后子串相连
                i = j + V.length - 1;//因为不重叠,所以要将i的值移到j+V.length-1的位置上
            }
            else {                   //如果没有后子串则直接将temp拷贝给S
                StrCopy(S, temp);
                break;
            }
        }
        else break;
    }
    return OK;
}

Status StrInsert(HString &S, int pos, HString T)
//串S和T存在,1<=pos<=Strlength(S)+1.在串S的第pos个字符之前插入串T
{
    if (S.length >= 0 && T.length >= 0 && 1 <= pos&&pos <= S.length + 1){
        if (pos == S.length + 1){//如果是在S之后插入T
            HString temp;
            Concat(temp, S, T);//将S和T连接
            StrCopy(S, temp);//将S和T连接的值传给S
            return OK;
        }
        HString sub1, sub2,temp;//如果是在S中间插入T
        SubString(sub1, S, 1, pos - 1);//求前子串
        SubString(sub2, S, pos, S.length - pos + 1);//求后子串
        Concat(temp, sub1, T);//前子串与T相连保存在temp中
        Concat(S, temp, sub2);//后子串与temp相连传给S
        return OK;
    }
    else return ERROR;
}

Status StrDelete(HString &S, int pos, int len)
//串S存在,1<=pos<<Strlength(S)-len+1。从串S中删除第pos个字符起长度为len的子串
{
    if (1 <= pos&&pos <= S.length - len + 1){
        HString str1, str2;
        SubString(str1, S, 1, pos - 1);//求删除子串前的子串
        SubString(str2, S, pos + len, S.length - pos - len + 1);//求删除子串后的子串
        Concat(S, str1, str2);//将前子串和后子串相连
        return OK;
    }
    else return ERROR;
}

Status DestroyString(HString &S)
//串S存在,串S被销毁
{
    if (S.length>0){
        delete S.ch;
        S.length = 0;
        return OK;
    }
    else return ERROR;
}

 

主函数:

// HString.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"


int _tmain(int argc, _TCHAR* argv[])
{
    HString str1, str2,str3;
    char ch[] = "lidanldan";
    StrAssign(str1, ch);
    char ch1[] = "dan";
    StrAssign(str2, ch1);
    char ch2[] = "dd";
    StrAssign(str3, ch2);
    Replace(str1, str2, str3);//验证替换
    cout << str1.ch << endl;
    StrInsert(str2, 2, str3);//验证插入
    cout << str2.ch << endl;
    StrDelete(str2, 2, 2);   //验证删除
    cout << str2.ch << endl;
    return 0;
}

结果:

这是延续了C语言的风格,在字符串末尾加上一个结束字符。。C语言用'\0',本人用NULL。。其实在C++的最新标准中C++11,是不推荐这种风格的。而且不推荐用字符数组来表示字符串,而是用string