串的基本操作有:
StrAssign(&T,chars):赋值操作,把串T赋值为chars
StrCopy(&T,S):复制操作,由串S复制得到串T
StrEmpty(S):字符串的判空操作,若S为空串则返回True,否则返回false
StrLength(S):求串长,返回串S的元素个数。
ClearString(&S):清空操作,将S清为空串。
DestoryString(&S):销毁串,将串S销毁(回收存储空间)
Concat(&T,S1,S2):串连接,用T返回由S1、S2连接而成的新串。
SubString(&Sub,S,pos,len):求子串,用Sub返回串S的第pos个字符起长度为len的子串。
StrCompare(S,T);比较操作,若S>T,则返回值大于0,若S=T,则返回值等于0,若S<T,返回值小于0。
Index(S,T):定位操作,若主串S中存在与串T值相同的子串,则返回他在主串S中第一次出现的位置,否则返回0 。
代码实现以及结果测试:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MaxSize 255 //该字符数组的最大容量
//串的静态数组实现方式结点定义
typedef struct{
char data[MaxSize];
int length; //该字符数组中实际长度
}SString;
//串的动态数组实现方式
typedef struct{
char *ch;
int length ; //该字符数组中的实际长度
}DString; //此种方式实现的字符串如果当存储空间不够时,可以通过realloc函数动态扩容。 非常适合于Concat拼接字符串函数。
//串的单链表实现方式1
typedef struct LString{
char ch; //1B
struct LString *next; // 4B
}LString; //此种方式存储密度低,非常浪费存储空间,并且不支持随机存取。
//串的单链表存储方式2
typedef struct LLString {
char ch[4]; //4B
struct LLString *next; //4B
}LLString; //此种方式存储密度较第一种显著提升。
/*
链表各节点存储数据的个数如何确定?
1、如果串很长,并且存储空间有限,尽可能的让各节点存储更多的数据,提高空间的利用率(每多一个结点,就要多一个指针域的空间)
2、如果程序中针对此字符串要做大量的插入和删除操作, 则应尽可能减少各节点存储数据的量。
*/
//赋值操作
void StrAssign(SString &str,char chars[],int length){
for(int i = 0 ;i<length;i++){
str.data[i]=chars[i];
}
str.length=length;
}
//字符串判空
bool StrEmpty(SString str){
return str.length==0;
}
//字符串求串长
int StrLength(SString str){
return str.length;
}
//字符串的初始化、清空操作
void ClearString(SString &str){
str.length=0;
}
//字符串的销毁操作
void DestoryString(SString &str){
//由于我们是在栈空间开辟的字符串的存储空间,无需手动销毁,当函数调用结束时,字符串会随着函数弹栈而被自动销毁。
}
//复制操作 由串S得到串T。
bool StrCopy(SString *t,SString s){
if(s.length == 0){
return false;
}
for(int i=0;i<s.length;i++){
t->data[i]=s.data[i];
}
t->length=s.length;
return true;
}
//字符串的连接操作 t=s1+s2;
bool Concat(SString &t,SString s1,SString s2){
if(s1.length+s2.length>MaxSize || (s1.length==0 && s2.length==0)){
return false;
}
for(int i = 0;i<s1.length;i++){
t.data[i]=s1.data[i];
}
for(int j = 0;j<s2.length;j++){
t.data[j+s1.length]=s2.data[j];
}
t.length=s1.length+s2.length;
return true;
}
//打印字符串
void printString(SString t){
for(int i = 0;i<t.length;i++){
printf("%c",t.data[i]);
}
}
//求子串 用sub返回串S的第pos个字符起长度为len的子串。
bool SubString(SString &sub,SString s,int pos ,int len){
if(s.length==0 ||(pos+len-1)>s.length){
return false;
}
for(int i = 0;i<len;i++){
sub.data[i]=s.data[pos-1+i];
}
sub.length=len;
return true;
}
//字符串比较 s>t 返回值大于0 , s=t 返回值等于0, s<t 返回值小于0
int StrCompare(SString s,SString t){
//
for(int i = 0;i<s.length && i<t.length;i++){
if(s.data[i]!=t.data[i]){
return s.data[i]-t.data[i];
}
}
return s.length-t.length;
}
//查找串S中,是否存在与strSon相同的子串,若存在返回首次出现的位置,若不存在,返回0
int Index(SString str,SString strSon){
//先求母串的长度
int mother = StrLength(str);
//再求子串的长度
int son = StrLength(strSon);
int i = 1;
SString sub;
//在母串中截取和子串相同的长度,然后进行元素的比较
while(i<=mother-son+1){
SubString(sub,str,i,son);
if(StrCompare(sub,strSon) != 0) i++;
else return i;
}
//while循环完了还没找到子串,返回0,
return 0;
}
int main(int argc, char *argv[])
{
//这就是串的定长顺序存储。
//长度20的字符数组只能存储19个字符,因为最后一个字符要存储'\0'结束标志位。
char string[]="nihao,shujvjiegou!";
SString t;
//字符串的初始化操作
ClearString(t);
//将string中的内容赋值给t
StrAssign(t,string,strlen(string));
printString(t);
printf("\n");
//判空操作
bool flag = StrEmpty(t);
printf("该字符串为空吗?%d\n",flag);
//求字符串串长
int len = StrLength(t);
printf("这个字符串的串长是%d\n",len);
SString s;
//字符串的copy操作
StrCopy(&s,t);
printString(s);
printf("\n");
//字符串的连接操作
char s1[] = "hello,world!";
char s2[] = "I'm your father!";
SString ss1;
SString ss2;
StrAssign(ss1,s1,strlen(s1));
StrAssign(ss2,s2,strlen(s2));
SString end;
Concat(end,ss1,ss2);
printString(end);
printf("\n");
//字符串的截取子串操作
SString sub;
SubString(sub,end,1,2);
printString(sub);
printf("\n");
//字符串的比较
char s3[] = "htllo,world!";
char s4[] = "hallo,world!s";
SString ss3;
SString ss4;
StrAssign(ss3,s3,strlen(s3));
StrAssign(ss4,s4,strlen(s4));
int value = StrCompare(ss3,ss4);
if(value > 0){
printf("ss3的值更大\n");
}else if(value < 0){
printf("ss4的值更大\n");
}else{
printf("ss3和ss4一样大\n");
}
char s5[]="fengzhijia";
char s6[]="ijia";
SString ss5;
StrAssign(ss5,s5,strlen(s5));
SString ss6;
StrAssign(ss6,s6,strlen(s6));
int index = Index(ss5,ss6);
printf("子串在母串中出现的位置是%d\n",index);
return 0;
}
注意:
concat函数实现两个串的拼接生成一个新串,虽然使用静态数组方式可以实现,但是静态数组的特性无法扩容。所以有可能这两个函数拼接之后容量超了静态数组的容量。
所以实现concat这种类似拼接字符串的函数,最好是使用动态数组分配的方式。