零、说明
- 字符串就是用数组存储一连串用字符表示的信息
- 操作和其他数据结构不同,字符串的每个单位不是其他数据结构的节点,而是字符数组的每位,所以算法理解起来有一点难度。有些函数看起来还挺长的,不过慢慢理解之后会发现其实不难
- 由于并非必须,下列函数没有检测输入数据是否正确符合规范没有越界,需要输入自行确定
一、数据类型
typedef char String[MAXSIZE+1];
- 使用《大话数据结构》中的做法,String的第0位存储字符串长度,第1到第MAXSIZE位存储数据
- String[MAXSIZE-1]等同于*String,即typedef char *String,把char *叫做String
二、输入输出
还没输入之前,字符串为空,无法使用其他函数
- 输入:输入字符串S的内容
逐个读取字符,最后确定字符串长度,赋给S[0]
void Input(String S)
{
char Tentative;
int i;
cout<<"Please enter a string here:";
Tentative=getchar();
for(i=1;Tentative!='\n';i++)
{
S[i]=Tentative;
Tentative=getchar();
}
S[0]=i-1;
}
- 输出:打印字符串S
也是依次输出。不能用cout,因为cout不能输出空格,所以注意要包括stdio.h
void Output(String S)
{
int i;
for(i=1;i<=S[0];i++)
{
printf("%c",S[i]);
}
}
三、串间操作
- 复制:把字符串S复制到字符串T中
从第零位依次放入即可
void Copy(String S,String T)
{
int i;
for(i=0;i<=S[0];i++)
{
T[i]=S[i];
}
}
- 比较:比较字符串S和字符串T,返回S和T的差值(先后顺序)
按位比较,直到第一个不一样的字符出现;如果到某串结尾都相同,则差值是长度相减
int Compare(String S,String T)
{
int i;
for(i=1;i<=S[0]&&i<=T[0];i++)//计数首先逐个比较,其次使得比较在S和T中短的范围内
{
if(S[i]!=T[i])
{
return S[i]-T[i];//只要有一个字符不一样,字符串值的差别就在这个字符上了
}
}
return S[0]-T[0];//如果前min{S[0],T[0]}个都一样,那值的差别就在字符数上
}
- 连接:把T接在S后面,多了就截断T,只放一部分
void Connect(String S,String T)
{
int i,j;
j=(S[0]+T[0]<=MAXSIZE)?T[0]:(MAXSIZE-S[0]);//条件运算符,如果总长小于MAXSIZE,j就是T[0],如果大于,就是MAXSIZE-S[0]
//j的作用就是标志T中到底能放进去几位
for(i=1;i<=j;i++)
{
S[i+S[0]]=T[i];
}
S[0]=(S[0]+T[0]<=50)?(S[0]+T[0]):50;//作用同上,替代if/else
}
- 赋串:将S中第position个字符起length长的子串赋给T
void Getstring(String S,String T,int position,int length)
{
int i;
for(i=1;i<=length;i++)
{
T[i]=S[position+i-1];
}
T[0]=length;
}
四、串内操作
- 查找:从S中第position个字符起找是否有sub子串,返回它出现的第一个位置,如果没有,返回0
有两种思路:
①逐位比较
int Index1(String S,String Sub,int position)
{
int i,j;
i=position;//用于在主串中搜索
j=1;//用于在子串中搜索
while(i<=S[0]&&j<=Sub[0])//从循环中出来,要么子串没匹配到而主串到头了,要么主串没到头而子串匹配完了即符合想要的
{
if(S[i]==Sub[j])
{
i++;
j++;
}
else
{
i=i-j+2;//退到这次匹配第一位的下一位,i-(j-1)+1
}
}
if(j>Sub[0])
return i-Sub[0];
else
return 0;
}
②调用Compare
int Index2(String S,String Sub,int position)
{
int m,n,i;
String T;
m=S[0];
n=Sub[0];
i=position;
while(i<=m-n+1)
{
Getstring(S,T,i,n);
if(Compare(Sub,T)!=0)//如果不符合
{
i++;
}
else
{
return i;
}
}
return 0;
}
- 插入:在S中第position个字符前插入Sub
根据插入后总长可以分为两种情况
void Insert(String S,String T,int position)
{
int i;
if(S[0]+T[0]<=MAXSIZE)
{//完全插入
for(i=S[0];i>=position;i--)//后移
{
S[i+T[0]]=S[i];
}
for(i=position;i<=position+T[0]-1;i++)//插入
{
S[i]=T[i-position+1];//+1的原因是不加一就会从T[0]开始插入
}
S[0]=S[0]+T[0];//别忘了改
}
else
{//不完全插入,由于要把T全部插进去,势必会把S的后几位挤出去
for(i=MAXSIZE;i>=position+T[0];i--)//部分后移,本来就要挤出去的那几位就不用管了
{
S[i]=S[i-T[0]];
}
for(i=position;i<=position+T[0]-1;i++)//从position到position+T[0]-1即插入T的那些位
{
S[i]=T[i-position+1];
}
S[0]=MAXSIZE;//别忘了改
}
}
- 删除:删除S中position位后面length长的子串
就是简单的前移
void Delete(String S,int position,int length)
{
int i;
for(i=position+length;i<=S[0];i++)
{
S[i-length]=S[i];
}
S[0]=S[0]-length;
}
- 替换:将S中的Old串替换成New串
用Index搜索位置,用Delete删除Old,用Insert插入New
void Replace(String S,String Old,String New)
{
int i=1;
do
{
i=Index1(S,Old,i);
if(i)
{
Delete(S,i,Old[0]);
Insert(S,New,i);
i=i+New[0];
}
}while(i);
}