概念
串是由0个或者多个字符组成的有限序列,串中字符的个数称为串的长度,含有0个元素的串叫做空串。(某个字符在串中的序号称为这个字符的位置。)
char str[] = “abcdef”; //串通常用一个字符数组表示,数组str内存储的字符为"a",“b”,“c”,“d”,“e”,“f”,"\0",其中"\0"作为编译器识别串结束标记,不算实际字符,因此数组str的长度为7,串str的长度为6。
- 子串:串中任意连续的字符组成的子序列称为该串的子串。
- 主串:包含子串的串称为主串。
- 空格串:由一个或多个空格组成的串称为空格串。
串的存储结构
1.定长顺序存储
定长顺序存储就是事先指定串的长度并分配存储空间,定义如下:
typedef struct
{
char str[maxsize+1];
int length; //字符串长度
}Str;
maxsize表示串的最大长度,maxsize+1表示字符数组的长度,多出来的一个长度是用来存储\0标识符的。
2.变长分配存储
变长分配存储是在程序执行过程中根据需要动态分配串的长度以及空间,定义如下:
typedef struct
{
char *ch; //指向动态分配存储区首地址的字符指针
int length; //串长度
}Str;
这种存储方式在使用时需要用函数malloc()来分配一个长度为length、类型为char型的连续存储空间。用函数malloc()分配存储空间,如果成功,则返回一个指向起始地址的指针,作为串的基地址,这个地址由ch指针指向。
串的基本操作
1、赋值操作
因为串是一个数组,对于数值赋值到另一个数组需要对数组中的每一个元素进行逐一赋值操作。
Status strassign(Str& str,char* ch)//生成其值等于串常量为ch的串str
{
if(str.ch)
free(str.ch); //释放
int len = 0;
char *c = ch;
while(*c) //求串ch的长度
{
++len; //字符串长度+1
++c; //指针向后移动1
}
if(len == 0) //如果ch串长度为0,即为空串,直接返回空串
{
str.ch = NULL;
str.length = 0;
return 1;
}
else
{
str.ch = (char*)malloc(sizeof(char)*(len+1)); //动态分配存储,如果分配成功则返回具体指针,负责返回0
if(str.ch == NULL) //分配失败
return 0;
else
{
c = ch
for (int i = 0;i <= len;++i,++c) //将ch最后的"\0"一起赋值给新串作为结尾标记符
str.ch[i] = *c;
str.length = len;
return 1;
}
}
}
函数strassign()函数使用时格式为:
strassign(str,char[]);//char[]="abcd"
2、取串长度操作
如果字符串数组给出了串的长度,取字符串的长度就比较简单,具体代码如下:
int strlength(Str str)
{
return str.length
}
如果字符串数组没有给出串的长度,那么直接去遍历字符串中每个元素,依次将length加1,最后就是字符串长度,具体代码如下:
int len = 0;
char *c = ch;
while(*c) //求串ch的长度
{
++len; //字符串长度+1
++c; //指针向后移动1
}
3、串比较操作
两个字符串比较,对于等长的两个字符串依次将两个字符串中的每一个对应的数据元素去做对比,比较数据元素的ASCII码值。对于不等长的字符串,字符串较短的串比较小。
Status 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;
}
return 1;
}
4、串连接操作
串连接就是将两个字符串首尾进行连接,合并成一个新的字符串,其实具体的赋值原理就是分别将俩个串以先后顺序赋值给同一个新串。具体实现代码如下:
Status concat(Str& str,Str str1,Str str2)
{
if (str.ch)
{
free(str.ch);//释放原串的空间
str.ch=NULL;
}
str.ch=(char*)malloc(sizeof(char)*(str1.length+str2.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[i+j]=str2.ch[j];
++j;
}
str.length=str1.length+str2.length;
return 1;
}
5、求子串操作
求从某一位置开始,另一位置结束的串的操作称为求子串操作。现在要从字符串str中的pos位置开始,获取长度为len的子串,子串由substr返回。具体代码如下:
Status substring(Str& substr,Str str,int pos,int len)//从substr返回串str的第pos个字符起长度为len的子串
{
if(pos < 0 || pos >=str.length || len < 0 || len > str.length - pos)
return 0;
if(substr.ch)
{
free(substr.ch);
substr.ch == NULL;
}
if(len == 0)
{
substr.ch = NULL;
substr.length = 0;
return 1;
}
else
{
substr.ch = (char*)malloc(sizeof(char) * (len + 1));
int i = pos, j = 0;
while(i < pos + len)
{
substr.ch[j] = str.ch[i];
++i;
++j;
}
substr.ch[j] = '\0';
substr.length = len;
return 1;
}
}
6、串清空操作
Status clearstring(Str& str)//串清空
{
if (str.ch)
{
free(str.ch);
str.ch=NULL;
}
str.length=0;
return 1;
}
代码实现的头文件
init.h
#ifndef _INIT_H
#define _INIT_H
#define TRUE 1
#define FASLE 0
#define OK 1
#define ERROR -1
#define OVERFLOW -2
typedef int Status;
#endif
string.h
#ifndef STRING_H
#define STRING_H
typedef struct
{
char *ch;//指向动态分配存储去首地址的字符指针
int length;//串长度
}Str;
void StrInit(Str &str);
Status strassign(Str& str,char* ch);
Status strlength(Str str);
Status strcompare(Str s1,Str s2);
Status concat(Str& str,Str str1,Str str2);
Status substring(Str& substr,Str str,int pos,int len);
Status clearstring(Str& str);
#endif
demo.cpp
#include "init.h"
#include "string.h"
#include <iostream>
using namespace std;
int main()
{
Str str1, str2, str3,substr;
StrInit(str1);
StrInit(str2);
StrInit(str3);
StrInit(substr);
char ch1[] = " love";
char ch2[] = "eat and";
char ch3[] = "sleep well";
strassign(str1, ch1);
strassign(str2, ch2);
strassign(str3, ch3);
cout<<str1.ch<<endl;
cout<<str2.ch<<endl;
cout<<str3.ch<<endl;
concat(str1,str2,str3) ;
substring(substr,str1,2,8);
cout<<str1.ch<<endl;
cout<<substr.ch<<endl;
system("pause");
getchar();
return 0;
}
此次的数据结构分享就到这里,欢迎大家指导指正~ 我是爱吃肉的小白yyyloki,如果你觉得不错的话点个赞👍吧!我们下次见~886
晚安~