c语言实现字符串

来源:互联网 发布:怎么卸载mac自带系统 编辑:程序博客网 时间:2024/05/01 16:33

串的基本概念

串 ( 字符串 ) :是零个或多个字符组成的有限序列。 记作: S=”a1a2a3a4…” ,其中 S 是串名, ai (1 ≦ i ≦ n) 是 单个,可以是字母、数字或其它字符。
串值:双引号括起来的字符序列是串值。
串长:串中所包含的字符个数称为该串的长度。
空串 ( 空的字符串 ) :长度为零的串称为空串,它不 包含任何字符。
空格串 ( 空白串 ) :构成串的所有字符都是空格的串 称为空白串。
子串 (substring) :串中任意个连续字符组成的子序 列称为该串的子串,包含子串的串相应地称为主串。
子串的序号:将子串在主串中首次出现时的该子串 的首字符对应在主串中的序号,称为子串在主串中的序
号(或位置)。
串相等:如果两个串的串值相等 ( 相同 ) ,称这两 个串相等。换言之,只有当两个串的长度相等,且各 个对应位置的字符都相同时才相等。

串的基本操作

1.串赋值
2.串拷贝
3.串比较
4.串长度
5.清空串
6.返回第pos个字符起长度为len的字串
7.若存在和T相等的字串,返回其字串第一次出现的位置
8.替换字串
9.在串中的第pos个字符之前插入字串
10.删除第pos个字符起长度为len的字串
11.销毁串
12. 两个串相接

串的表示和实现

◆ 定长顺序存储表示:将串定义成字符数组,利用 串名可以直接访问串值。用这种表示方式,串的存 储空间在编译时确定,其大小不能改变。
特点:
1.操作时间的复杂度基本上基于字符序列的长度
2.如果在操作中出现串值序列的长度超过上界MAXSTRLEN时,约定用截尾法处理.
定长顺序存储结构定义为:

#define MAX_STRLEN 256typedef struct{     char str[MAX_STRLEN] ;    int length;} StringType ;

◆ 堆分配存储方式:仍然用一组地址连续的存储单 元来依次存储串中的字符序列,但串的存储空间是 在程序运行时根据串的实际长度动态分配的。
实现方法:系统提供一个空间足够大且地址连续的存储空间 ( 称为“堆” ) 供串使用。可使用 C 语言的动态存储分配函数 malloc() 和 free() 来管理。
串的堆式存储结构的类型定义

typedef struct{     char *ch; /* 若非空,按长度分配,否则为 NULL */    int length;} HString ;

◆ 块链存储方式:是一种链式存储结构表示。
串的链式存储结构和线性表的串的链式存储结构类似,采用单链表来存储串,结点的构成是:

data 域:存放字符, data 域可存放的字符个数
称为结点的大小;
next 域:存放指向下一结点的指针。
若每个结点仅存放一个字符,则结点的指针域就非常多,造成系统空间浪费,为节省存储空间,考虑串结构的特殊性,使每个结点存放若干个字符,这种
结构称为块链结构。如图 4-1 是块大小为 3 的串的块链式存储结构示意图。

这里写图片描述

结点的大小直接影响着串的处理效率.
串的存储密度:

存储密度=

显然,存储密度小时(例如结点大小为1),运算处理非常方便,但是存储占用量大.而存储密度大时,存储占用量相对较小,但如果在串处理过程中需进行过多的内外存交换时,会影响处理的总效率.

堆分配存储方式C语言实现

接口定义头文件

#define true 1#define false 0#define S_g_T 1#define S_e_T 0#define S_s_T -1/* 串的堆分配存储表示 */typedef struct h_string{    char *str;    /* 串长度 */    int length;}h_string;/* 生成一个值等于str的字符串常量  * 生成成功返回true * 否则返回false*/int string_assign(h_string *S, char *ch);/* 复制串S并返回 */h_string string_copy(h_string S);/* 判断串S是否为空 * 若为空则返回true * 否则返回false*/int string_empty(h_string S);/* 比较串S和T * 若S>T返回S_g_T * 若S=T返回S_e_T * 若S<T返回S_s_T*/int string_compare(h_string S, h_string T);/* 返回自字符串的长度 */int string_length(h_string S);/* 将S清空 */void string_clear(h_string *S);/* S1和S2连接,并由T返回连接的新串 * 若连接成功,返回true * 否则返回false*/int string_contact(h_string *T, h_string S1, h_string S2);/* 用sub返回串S第pos个字符起长度为len的子串  * 成功返回true * 否则返回false*/int string_substring(h_string S, h_string *sub, int pos, int len);/* 若主串S中存在和串T值相等的字串, * 返回它在主串S中第pos个字符之后第一次出现的位置 * 否则返回-1*/int string_index(h_string S, h_string T, int pos);/* 用V替换主串S中出现所有的与T串值相等的不重叠的字串 */h_string string_replace(h_string *S, h_string V, h_string T);/* 在串S的第pos个字符之前插入串T */h_string string_strinsert(h_string S, h_string T, int pos);/* 从串S中删除第pos个字符起长度为len的字串 */h_string string_strdelete(h_string S, int pos, int len);/* 销毁串S */void string_destroy(h_string *S);/* 遍历打印字符 */void string_traverse(h_string S);

接口实现文件

#include<stdio.h>#include<stdlib.h>#include"string.h"int string_assign(h_string *S, char *ch){    /* 释放S的原有空间 */    if(S -> str)        free(S -> str);    /* 求串ch的长度 */    int count = 0;    char *c;    for(count = 0, c = ch; *c; count++, c++);    printf("count  = %d\n", count);    /* 若*ch为空 */    if(!count)    {        S -> length = 0;        S -> str = NULL;        return true;    }    else    {        /* 申请内存空间 */        if(!(S -> str = (char *)malloc(sizeof(char)*count)))            return false;        S -> length = count;        /* 赋值 */        int i = 0;        for(i = 0; i < count; i++)        {            S -> str[i] = ch[i];        }        return true;    }}h_string string_copy(h_string S){    /* 创建新串 */    int len = S.length;    h_string T;    T.str = (char *)malloc(sizeof(char) * len);    T.length = len;    /* 复制 */    int i = 0;    for (i = 0; i < len; i++)    {        T.str[i] = S.str[i];    }    return T;}int string_empty(h_string S){    if(S.length == 0)        return false;    else        return true;}int string_length(h_string S){    return S.length;}int string_compare(h_string S, h_string T){    /* 相同索引号从小到大的字符比较      * 相同则继续比较,直至最后一个字符     * 否则直接返回两字符的差值    */    int i = 0;    for (i = 0;i < S.length && i < T.length; i++)    {        int value = S.str[i] - T.str[i];        if(value > 0)            return 1;        if(value < 0)            return -1;    }    /* 若两个字符串前面的字符都一致     * 则比较长度     * 长度一样说明相等     * 长度短的字符串小    */    int value = S.length - T.length;    if(value == 0)        return 0;    if(value > 0)        return 1;    if(value < 0)        return -1;}void string_clear(h_string *S){    if(S -> str)    {        free(S -> str);        S -> str = NULL;    }    S -> length = 0;}int string_contact(h_string *T, h_string S1, h_string S2){    /* 释放旧字符串(可直接调用string_empty()函数) */    if(T -> str)    {        free(T -> str);        T -> str = NULL;    }    /* 新字符串长度 */    T -> length = S1.length + S2.length;    T -> str = (char *)malloc(sizeof(char)*(T -> length));    if(!T -> str)        return false;    /* 赋值 */    int i = 0;    for(i = 0; i < T -> length; i++)    {        if(i >= S1.length)        {            T -> str[i] = S2.str[i - S1.length];        }        else        {            T -> str[i] = S1.str[i];        }    }    return true;}int string_substring(h_string S, h_string *T, int pos, int len){    /* pos,len与S.length间的关系     * 1 <= pos <= S.length;     * pos + len - 1 <= S.length     * len >= 0    */    /* 判断子串起始索引号和长度是否满足要求 */    if(pos < 1 || pos > S.length || len > S.length + pos - 1 || len < 0)        return false;    /* 清空旧串 */    if(T -> str)        free(T -> str);    /* 空子串 */    if (!len)    {        T -> str = NULL;        T -> length  = 0;        return false;    }    /* 申请内存空间 */    T -> str = (char *)malloc(sizeof(char) * len);    T -> length = len;    /* 申请内存空间失败 */    if(!(T -> str))        return false;    /* 赋值 */    int i = 0;    for (i = 0; i < len; i++)    {        T -> str[i] = S.str[pos - 1 + i];    }    return true;}int string_index(h_string S, h_string T, int pos){    /* 若T为空串 */    if(!(T.length))        return -1;    /* 比较 */    /* 串S的起始位置 */    int i = pos -1;    /* 串T的起始位置 */    int j = 0;    while(i < S.length && j < T.length)    {        if(S.str[i] == T.str[j])        {            i += 1;            j += 1;        }        else        {            i = i -j + 1;            j = 0;        }    }    if (j >= T.length)        return (i - T.length);    return -1;}h_string string_replace(h_string *S, h_string V, h_string T){    /* 替换之后,下一轮替换的起始位置,初始化为1 */    int pos = 1;    while(pos <= S -> length)    {        int index = string_index(*S, T, pos);        /* S中存在与T串值相等的子串 */        if (index >= 0)        {            /* V.length = T.length */            if (V.length == T.length)            {                int i = 0;                for (i = 0; i < V.length; i++)                {                    S -> str[index + i] = V.str[i];                }                pos = index + V.length;                continue;            }            /* V.length > T.length */            if (V.length > T.length)            {                /* 复制字符串S,保存在临时字符串temp中 */                h_string temp = string_copy(*S);                /* 增加申请内存 */                S -> str = (char *)malloc(sizeof(char) * S -> length + V.length - T.length);                S -> length = S -> length + V.length - T.length;                int i = 0;                int j = 0;                for (i = 0; i < index; i++)                {                    S -> str[i] = temp.str[i];                }                for (i = 0; i < V.length; i++)                {                    S -> str[index + i] = V.str[i];                }                for(i = index + V.length, j = index + T.length; j < temp.length; i++, j++)                {                    S -> str[i] = temp.str[j];                    printf("temp.length =%d j=%d\n", temp.length, j);                }                pos = index + V.length;                printf("部分\n");                string_traverse(*S);                continue;            }            /* V.length < T.length */            if(V.length < T.length)            {               /* 复制字符串S,保存在临时字符串temp中 */                h_string temp = string_copy(*S);                /* 释放旧字符串 */                free(S -> str);                S -> str = NULL;                /* 新申请内存 */                int len = temp.length + V.length - T.length;                S -> str = (char *)malloc(sizeof(char) * len);                S -> length = len;                int i = 0;                int j = 0;                for (i = 0; i < index; i++)                {                    S -> str[i] = temp.str[i];                }                for (i = 0; i < V.length; i++)                {                    S -> str[index + i] = V.str[i];                }                for(i = index + V.length, j = index + T.length; j < temp.length; i++, j++)                {                    S -> str[i] = temp.str[j];                }                pos = index + V.length;                continue;             }        }        else            return *S;    }}h_string string_strinsert(h_string S, h_string T, int pos){    /* 插入字符串为空 */    if(!T.length)        return S;    /* 存储字符串S的临时字符串 */    h_string temp = S;    /* 增加申请内存 */    int len = S.length + T.length;    S.length = len;    S.str = (char *)malloc(sizeof(char) * len);    /* 插入字符串 */    int i = 0;    int j = 0;    for (i = 0; i < pos - 1; i++)    {        S.str[i] = temp.str[i];    }    for (i = 0; i < T.length; i++)    {        S.str[pos - 1 + i] = T.str[i];    }    for (i = pos -1 + T.length, j = pos - 1; j < temp.length; i++, j++)    {        S.str[i] = temp.str[j];        printf("S.str[%d]=%c j=%d\n", i, S.str[i], j);    }    return S;}h_string string_strdelete(h_string S, int pos, int len){    /* pos,len与S.length间的关系     * 1 <= pos <= S.length;     * pos + len - 1 <= S.length     * len > 0    */    /* 判断子串起始索引号和长度是否满足要求 */    if(pos < 1 || pos > S.length || len > S.length + pos - 1 || len <= 0)        return S;    /* S删除子串之后的长度 */    int length = S.length - len;    if (!length)    {        free(S.str);        S.str = NULL;        S.length = 0;        return S;    }    else    {        h_string temp;        temp.str = (char *)malloc(sizeof(char) * length);        temp.length = length;        int i = 0;        int j = 0;        for (i = 0; i < pos - 1; i++)        {            temp.str[i] = S.str[i];        }        for (i = pos - 1, j = pos -1 + len; j < S.length; i++, j++)        {            temp.str[i] = S.str[j];        }        return temp;    }}void string_destroy(h_string *S){    free(S -> str);    S -> str = NULL;    S -> length = 0;}void string_traverse(h_string S){    if(!(S.length))        printf("字符串为空\n");    else    {        int i = 0;        for(i = 0; i < S.length; i++)        {            printf("%c",S.str[i]);        }        printf("\n");    }}

其中的int string_index()函数的采用的是暴力比较法,该算法最好情况的时间复杂度是O(n+m),最差情况时的时间复杂度为O(n*m),可以采用KMP算法改进,使得其时间复杂度为O(n+m),详细情况见下篇博文.

测试文件

int main(){    char *ch = "jiang";    h_string S;    S.length = 7;     S.str = (char *)malloc(sizeof(char) * S.length);    /* 赋值 */    string_assign(&S, ch);    string_traverse(S);    /* 复制  */    h_string T = string_copy(S);    string_traverse(T);    /* 判空 */    int value = string_empty(S);    printf("字符串判空=%d\n",value);    /* 字符串比较 */    char *str = "linyijiang";    string_assign(&T, str);    value = string_compare(S, T);    printf("字符串比较=%d\n",value);    /* 字符串长度 */    value = string_length(T);    printf("字符串长度=%d\n", value);    /* 清空字符串 */    //string_clear(&S);    //printf("字符串清空:");    //string_traverse(S);\    /* 字符串连接 */    h_string ST ;    ST.str = NULL;    string_contact(&ST, S, T);    string_traverse(ST);    /* 字串位置 */    string_traverse(T);    string_traverse(S);    value = string_index(T, S, 1);    printf("index=%d\n", value);    /* 返回长度为len的字符串 */    printf("返回长度为len的字符串\n");    string_traverse(T);    string_traverse(S);    value = string_substring(T, &S, 2, 9);    string_traverse(S);    /* 替换 */    //string_traverse(T);    //h_string V;    //V.str = "brother";    //V.length = 7;    //S.str = "i";    //S.length = 1;    //S = string_replace(&T, V, S);    //string_traverse(S);    /* 插入字符串 */    //printf("插入字符串\n");    //string_traverse(T);    //S = string_strinsert(T, V, 2);    //string_traverse(S);    /* 删除 */    //printf("删除\n");    //string_traverse(T);    //S = string_strdelete(T, 2, 6);    //string_traverse(S);}

运行结果

这里写图片描述

0 0
原创粉丝点击