数据结构(c语言)——串

首先是前期准备:定义的常量以及串的结构体;

#include <stdio.h>
#define STRINGMAX 100
typedef struct
{
    char vec[STRINGMAX];
    int len;//储存串的实际数据的长度而不是下标;
        /**(顺便提示一句:往往需要在字符串的末尾加一个结束标志'\0'而这个标志在操作中不算做实际数据,
        除在某些操作中作为循环结束条件,其它都将这个标志看为空的;)**/
}str;//定义一个串结构的结构体;

串链接函数:顾名思义就是将两个串r1和r2首尾相连(r1的尾,r2的首)成一个新串r1,即r1=r1+r2;基本思路是:首先判断r1加r2的长度是否超过了r1的最大长度,然后利用循环(循环的条件是r2的长度)将r2的字符逐个赋值给r1(赋值的位置从r1的尾部开始;)

void Concarstr(str *r1,str *r2)//串链接;
{
    int i;
    printf("\n\t\tr1=%s \t\t  r2=%s",r1->vec,r2->vec);
    if(r1->len+r2->len>STRINGMAX)
    {
        printf("\n\t\t两个串太长,溢出!\n");
    }
    else
    {
        for(i=0;i<r2->len;i++)
        {
            r1->vec[r1->len+i]=r2->vec[i];//将r2的字符逐个赋值到r1的尾部;r1->len储存的不是实际数据而是结束标志'\0';
        }
        r1->vec[r1->len+i]='\0';//在新串的末尾加一个结束标志'\0',(链接时覆盖掉这个数据;)
        r1->len=r1->len+r2->len;
    }
}
求子串:在给定字符串r中从指定位置i开始连续取出j个字符构成子串r1;
基本思路:首先判断取的位置i加上需要取得的字符数j是否大于r的实际长度,即,i-1+j>r->len;(之所以i-1是因为位置和下标是不同的,下标从0开始计数而位置从1开始计数;)注:这句代码代表着允许子串取r->vec[r->len]即结束标志‘0’;如不希望其取‘0’需改为i-1+j>=len;
  
void Substr(str *r,int i,int j)//求子串;
{
    int k;
    str a;//因为下面的指针r1需要一个空间;
    str *r1=&a;

    if(i+j-1>r->len)
    {
        printf("\n\t\t子串超界!\n");
    }
    else
    {
        for(k=0;k<j;k++)
        {
            r1->vec[k] = r->vec[i+k-1];//位置-1即为所需下标;
        }
        r1->len=j;
        r1->vec[r1->len] = '0';
        printf("\n\t\t取出字符为:");
        puts(r1->vec);
    }
}
删除子串:在给定字符串r中删除从指定位置i开始连续的j个字符;
基本思路:首先判断数据是否越界;然后利用双变量循环(一个从所需删除位置开始,一个从所有所需删除的数据位置之后开始)将所需删除的数据覆盖掉;
void Delstr(str *r,int i ,int j)//删除子串;
{
    int k;
    if(i-1+j>=r->len)//r->vec[r->len]储存了字符串的结束标志'0',并不算做实际数据,所以应当把这种情况算作越界;
    {
        printf("要删除的子串超界");
    }
    else
    {
        for(k=i-1-j;k<r->len;k++,i++)//i-1为位置i的坐标表示,k为需删除数据后面的数据;
        {
            r->vec[i-1] = r->vec[k];//用后面的数据覆盖前面需要删除的数据;
        }
        r->len = r->len-j;//设置字符串r的新长度;
        r->vec[r->len] = '0';//无论原串需删除的数据有没有被后面的数据完全覆盖(可能存在后面的数据不足完全覆盖需删除数据的情况);
                            //在新串的r->vec[r->len]赋值结束标志'0',这时无论后面还存不存需删除的数据,都等同于无;
    }
}
插入子串:在字符串r中IDE指定位置i插入子串r1;
基本思路:首先判断插入位置i是否合法再判断串r+串r1是否超过了r的最长长度;然后,利用循环将插入位置后面的数据后移r1->len-1个单位;在利用一个循环将子串插入相应位置;
str Insstr(str *r,str *r1,int i)
{
    int k;

    if(i>=r->len || r->len+r1->len>STRINGMAX)
    {
        printf("\n\t\t不能插入!\n");
    }
    else
    {
        for(k=r->len-1;k>=i-1;i--)
        {
            r->vec[r1->len-1+k] = r->vec[k];//利用循环从串r的最后一个实际元素开始,向后移动r1->len个单位;
        }
        for(k=0;k<r1->len;k++)
        {
            r->vec[i-1+k] = r1->vec[k];//从插入位置开始,利用循环将r1的实际元素逐个赋值给r;
        }
    }
}
模式匹配:即子串定位,设s和t是给定的两个串,在主串s中找到等于子串t的过程称为模式匹配;函数返回t在s中首次出现的储存位置(或序号)
        其中,被匹配的主串s称为目标串,匹配的子串t称为模式;
基本思路;用双重循环完成;外层循环控制主串s,然后拿着外层循环的位置i,内层循环开始于子串t匹配;若匹配成功则返回位置i结束循环,否则继续下一轮的判断;
int Indexstr(str *r,str *r1)
{
    int i,j,k;

    for(i=0;r->vec[i];i++)//主串的结束标志作为循环终止条件;
    {
        for(j=i,k=0;r->vec[j]==r1->vec[k];j++,i++)//将i值交给j用于保护i值,记录位置;把r->vec[j]==r1->vec[k];作为循环条件,若匹配则继续循环,否则退出内层循环;
        {
            if(!r1->vec[k+1])//利用结束标志,判断子串r1的实际数据是否完全与主串r匹配;
            {
                return i;//如果完全与主串匹配,怎返回位置i,结束函数;
            }
        }
    }
    return -1;
}







阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页