21数据结构-串知识整理

串数据类型的定义

串的定义

串是由零个或多个字符组成的有限序列。串中的个数称为串的串的长度,含有零个元素的串叫做空串。

char str[] = "abcdef";
//输出字符直接
cout<<str;
#include <iostream>
using namespace std;
int  main() {
    //char *str = "0123456789";//也ok
    char *str;
    for(int i=0;i<10;++i){
        str[i] = i+'0';
    }
    str[10] = '\0';//莫失莫忘,仙寿恒昌!
    cout<<str;
    return 0;
}
//输出结果
//0123456789

字符串输出规则:

当我们写cout<<str;后,无论str是指针还是char数组,其实char *str,和char str[],就是同一个东西(还记得char的动态数组声明吗?char *str = new char[10];),编译器从str[0]开始输出,一直输出直到遇到‘\0’,才停下来。

char str[10]的越界输出:我们令str[9]='0',这样我们就抹除掉了,字符串结尾的'\0'这样编译器把整个str数组输出完之后,还会继续往后面输出,随机在某个位置停下来,当你的内存区的数字转为char类型恰好是‘\0'就停下来了(如果一直遇不到\0,就继续往后面走呗!)。

串的存储结构:

1. 定长顺序存储表示

本书(2021天勤)的定义:给串尾加上‘\0’结束标记,同时也设定length;

结构体定义:

typedef struct{
    //maxSize是串的最大长度,+1存放'\0'
    char str[maxSize+1];
    int length;
}Str;
2. 变长分配存储

也叫动态分配存储,特点是:执行过程根据需要动态分配。

结构体定义:

typedef struct{
    char *ch;
    int length;
}Str;

使用时需要用函数malloc()来分配一个长度为length、类型为char型的连续存储空间,分配的空间可以用函数free()释放掉。

(真的不是我要杠一下,我在串的定义写的char *str(就是文章开头),就没用malloc(),照样可以用,问题就是我的str没有分配空间会抹除掉其他空间的数据。还是按照标准的malloc这样分配连续的存储空间比较好。)

3. 串的基本操作

几种串的原子操作。(就是基石操作)

1.赋值操作

串的操作不能直接用“=”。因为串是一个数组。

string的比较:
(考试我不知道啊,但是比赛时建议用string,string不仅可以赋值还能判断是否相等。)
//头文件,<string.h>也可以,但cstring是新的库
#include<cstring>
string str = "123";
string str2 ="456";
str2 = str;//ok的
if(str2 == str)//为真
 cout<<"true";

必须对每个元素逐一赋值操作。

strassign(),将常量字符串赋值给str,操作成功返回1,否则返回0;

使用格式:

strassign(str,"test");

要点:

  • 检查str.ch的空间分配了没,如果以前就分配了(str.ch为真),就直接free(str.ch)。因为我们不知道以前分配的空间够不够。
  • 遍历ch得出它的长度,为str.ch的malloc准备。
  • str.ch分配空间时,检查空间是否分配成功,空间分配失败,直接返回赋值失败。
int strassign(Str &str,char* ch) {
    if(str.ch)
        free(str.ch);
    str.length = 0;
    //先求出ch字符串的长度,来分配str的连续内存空间
    char* c = ch;
    while(*c){
        ++str.length;
        ++c;
    }
    if(str.length == 0){
        str.ch = NULL;
        return 1;
    } else
    {
        str.ch = (char*)malloc(sizeof(char)*(str.length+1));
        //+1是为了存放'\0'。不离不弃,芳龄永继!
        //这个if是避免malloc分配失败
        if(str.ch==NULL)
            return 0;
        else{
         c = ch;
         for(int i=0;i<=str.length;++i,++c)
             str.ch[i] = *c;
            return 1;
        }
    }
}
2.串的比较操作
int strcompare(Str s1,Str s2){
	for(int i=0;i<s1.length && i<s2.length;++i)
		if(s1.ch[i]!=s2.ch[i])
            return s1.ch[i] - s2.ch[i];
    return s1.length - s2.length;
}
3.串连接操作
int concat(Str &str,Str str1,Str str2){
    if(str.ch){
        free(str.ch);
        str.ch = NULL;
    }
    str.ch = (char*)malloc(sizeof(char)*(str1.length+str.length+1));
    if(str.ch==NULL)
        return 0;
    int i=0;
    while(i<str1.length){
        str.ch[i] = str1.ch[i];
        ++i;
    }
    int j=0;
    while (j<=str2.length){
        //注意取"=",是为了复制str.ch最后的'\0';
        str.ch[i+j] = str2.ch[j];
        ++j;
    }
    str.length = str1.length + str2.length;
}
4.求子串操作

实现从str串的pos位置开始,长度为len的字串,由substr返回给用户。

int substring(Str& substr,Str str,int pos,int len){
    //对pos和len进行检查
    if(pos<0||pos>=str.length||len<0||len>str.length-pos){
        return 0;
    }
    //小心这种情况
    if(len==0){
        substr.length = 0;
        substr.ch = NULL;
        return 1;
    }else{
        substr.ch = (char*)malloc(sizeof(char)*(len+1));
        int i=pos;
        int j=0;
        while(j<pos+len){
            substr.ch[j] = str.ch[pos+j];
        }
        substr.ch[j]='\0';
        substr.length = len;
        return 1;
    }
}
5.串清空操作
int clearstring(Str& str){
    //我觉得不直接free(str.ch),是为了避免释放空指针(dangerous)。
    if(str.ch){
        free(str.ch);
        str.ch = NULL;
    }
    str.length = 0;
    return 1;
}

4.2 串的模式匹配算法

注意:本节中的字符存储在1~length的位置上,注意区分0~length-1的存储位置。

4.2.1 简单模式匹配算法

 (又称为幼稚模式匹配算法,后续kmp算法)

思想:从主串的第一位置起和模式串的第一个字符开始比较,如果相等就逐一比较后续字符;否则从第二个字符开始再重复前面的操作。

匹配成功返回模式串在主串中的位置;若匹配不成功,返回一个可区别于主串所有位置的标记,比如“0”;

int index(Str str,Str substr){
    int i=1,j=1,k=i;
 while (i<=str.length && j<=substr.length){
        if(str.ch[i]==substr.ch[j]){
            ++i;
            ++j;
        } else{
            j=1;
            i=++k;
        }
    }
    if(j>substr.length){
        return k;
    } else
        return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

jieshenai

为了遇见更好的文章

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值