串的定义
串(string)是由零格或多个字符组成的有限序列。
串是一种特殊的线性表,数据元素之间呈线性关系。
串的存储结构
顺序存储
//静态数组(定长顺序存储)
#define MAXLEN 255
typedef struct{
char ch[MAXLEN]; //每个分量存储一个字符
int length; //用一个额外的变量length来存放串的长度。
}SString; //函数结束,系统自动回收
//动态数组(堆分配存储 )堆分配存储表示仍然是一组地址连续的存储单元存放串值的字符序列,但是他们的存储空间是在程序执行过程中动态分配得到的。
typedef struct{
char *ch; //ch指向串的基地址
int length; //用一个额外的变量length来存放串的长度。
}HString;
HString S;
S.ch = (char *)malloc(MAXLEN*sizeof(char)); //malloc申请的空间在堆区(heap),手动free释放存储空间
S.length = 0;
链式存储
typedef struct StringNode{
char ch; //每个节点存1个字符 1B
struct StringNode *next; //4B
}StringNode , *String; //存储密度低(字符1B+指针4B)
//推荐:
typedef struct StringNode{
char ch[4]; //每个节点存4个字符 4B
struct StringNode *next; //4B
}StringNode , *String;
串的基本操作
StrAssign(&T,chars) | 赋值操作,把串T赋值为chars |
---|---|
StrCopy(&T,S) | 复制操作,由串S复制得到串T |
StrEmpty(S) | 判空操作,若S为空串,则返回True,否则返回False |
StrCompare(S,T) | 比较操作,若S>T,则返回值>0;若S=T,返回值=0;若S<T,返回值<0 |
StrLength(S) | 求串长,返回串S的元素个数 |
SubString(&Sub,S,pos,len) | 求子串,用Sub返回串S的第pos个字符起长度为len的子串 |
Concat(&T,S1,S2) | 串联接,用T返回由S1和S2联接而成的新串 |
Index(S,T) | 定位操作,若主串S中存在与串T值相同的子串,则返回它在主串S中第一次出现的位置,否则函数值为0 |
ClearString(&S) | 清空操作,将S清空为空串 |
DestroyString(&S) | 销毁串,将串S销毁 |
代码实现(堆串-舍去S->ch[0]单元)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define false 0
#define true 1
typedef struct {
char *ch; //字符数组,若是非空则指向起始地址,若为空则NULL
int len; //长度
}HString;
//初始化
int HInit(HString *s){
s->ch=NULL;
s->len=0;
}
//串赋值
int HStrAssign(HString *s,const char *chars){
int i=0;
while(chars[i]!='\0'){ //确定串长
i++;
}
s->len=i;
if(s->ch!=NULL){
free(s);
}else{
s->ch=(char *)malloc((s->len+1)*sizeof(char));//0号单元不用
if(s==NULL){
printf("空间申请失败!");
return false;
}
for( i=1;i<=s->len;i++){ //依次赋值
s->ch[i]=chars[i-1];
}
}
}
//串遍历
int HSbianli(HString *s){
if(s->len==0){
printf("串空!");
return false;
}else{
int i;
for(i=1;i<=s->len;i++){
printf("%c",s->ch[i]);
}
return true;
}
}
//串插入
int HStrInsert(HString *s,int pos,const HString t){
if(pos<1||pos>s->len){
printf("位置不合法!");
return false;
}
char *temp;
temp=(char *)malloc((s->len+t.len+1) *sizeof(char));
int i;
for(i=1;i<pos;i++){ //将s串pos之前(不含pos)的字符赋给temp
temp[i]=s->ch[i];
}
for(i=pos;i<pos+t.len;i++){ //将t串的元素赋给s
temp[i]=t.ch[i-pos+1];
}
for(i=0;i<=s->len-pos;i++){
temp[pos+t.len+i]=s->ch[i+pos];
}
free(s->ch);
s->ch=temp;
s->len=s->len+t.len;
return true;
}
//串删除
int HStrDelete(HString *s,int pos,int len){
if(s->len==0){
printf("串空!");
return false;
}else if(len>=s->len){
printf("非法位置!");
return false;
}else{
for(int i=pos;i<s->len-pos;i++){ //跨度为len的依次赋值
s->ch[i]=s->ch[i+len];
}
s->len=s->len-len;
return true;
}
}
//串连接
int HStrCon(HString *s,const HString t){
s->ch=(char *)realloc(s->ch,(s->len+t.len+1) *sizeof(char));
if(s==NULL){
printf("空间申请失败!");
return false;
}
if(s->len==0){
printf("串空!");
return false;
}else{
for(int i=1;i<=t.len;i++){
s->ch[i+s->len]=t.ch[i];
}
s->len=s->len+t.len;
return true;
}
}
//求字串
int HStrchild(HString *s,int pos,int len){
if(s->len==0){
printf("串空!");
return false;
}else{
for(int i=0;i<len;i++){
printf("%c",s->ch[i+pos]);
}
return true;
}
}
//模糊查询 暴力
int Index(HString S, HString T){
int i = 1, j = 1;
while(i <= S.len && j <= T.len){
if(S.ch[i] == T.ch[j]){
++i; ++j; //继续比较后继字符
}else{
//指针后退重新开始匹配
i = i-j+2;
j = 1;
}
}
if(j > T.len){
return i - T.len;
}else{
return 0;
}
}
void HStringPrint(HString S,int pos,int len){
if(pos==0)
printf("子串不存在!");
if(S.len==0){
printf("串空!");
}else{
int i;
for(i=1;i<=S.len;i++){ //检查是否存在子串并红色显示
if(i==pos){
for (i = pos;i < pos+len;i++) {
printf("\033[31m%c\033[0m",S.ch[i]);
}
printf("%c",S.ch[i]); //输出i=pos+len的值
}
else
printf("%c",S.ch[i]);
}
}
}
int main(){
HString s;
HString s1;
HString s2;
HInit(&s);
HInit(&s1);
HInit(&s2);
char a[]={"asabbaa"};
char b[]={"bbb"};
char c[]={"cc"};
HStrAssign(&s,a);
HStrAssign(&s1,b);
HStrAssign(&s2,c);
printf("-----将aaaaa赋值给s,bbb赋值给s1-----\n");
printf("此时串s为:");
HSbianli(&s);
printf("\n此时串s1为:");
HSbianli(&s1);
printf("\n此时串s2为:");
HSbianli(&s2);
printf("\n将串s1插入到s串的第二个位置:");
HStrInsert(&s,2,s1);
HSbianli(&s);
printf("\ns中是否存在s1:");
int p=Index(s, s1);
HStringPrint(s,p,s1.len);
printf("\ns中是否存在s2:");
HStringPrint(s,Index(s, s2),s2.len);
printf("\n再将插入的s1串删除:");
HStrDelete(&s,2,3);
HSbianli(&s);
printf("\ns1在第二个元素长度为2的子串为:");
HStrchild(&s,2,2);
}
运行结构: