前言
PS:本文相关头文件、预编译以及typedef如下,阅读一遍以便于下面的理解:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXSTRLEN 40 #define OK 1 #define ERROR 0 #define TURE 1 #define FALSE 0 #define OVERFLOW -2 typedef int Status; typedef char SString[MAXSTRLEN+1];
ADT
串是一个重要的数据结构,我在这里实现串的ADT如下:
串的结构概念图
我定义了一个数组,0位存储字符长度,1到MAX位存储字符。这和传统的gets();函数或者 scanf(%s,);函数实现的串是有区别的,所以我封装了一个串赋值函数去实现两种串结构之间的转化,代码如下:
/* 字符串赋值,当赋值字符串长度超过被赋值字符串时候截断,未超过时先将长度存入T[0],再逐位赋值 */ Status StrAssign(SString T,char *chars) { int i; if(strlen(chars)>MAXSTRLEN) { for(i = 1;i <= MAXSTRLEN;i++) { T[i] = *(chars + i - 1); } T[0] = MAXSTRLEN; //T[0]存入int 型数据,%s无法打印 } else { T[0] = strlen(chars); //T[0]存入的是chars的字符长度 for(i = 1;i <= strlen(chars);i++) { T[i] = *(chars + i - 1); } } return OK; }
功能函数算法难点
我认为其中的StrIndex();索引子串函数是相对难理解一些的。其函数功能是:索引子串,返回串T中第一个索引到与串S相同的子串的位置。算法思路图如下:
尤其要注意,当T[i] != S[j]时,需要将i指针置于上次相同时的下一个位置,代码实现为 i = i - j + 2,而不是i++
该模块函数封装代码如下:
/* 索引子串,返回串T中第一个索引到与串S相同的子串的位置 */ Status StrIndex(SString T,SString S,int *pos) { int i=1,j=1; while((i <= T[0]) && (j <= S[0])) { if(T[i] == S[j]) { i++; j++; } else { i = i - j + 2; j = 1; } } if(j > S[0]) { *pos = i - j + 1; printf("Found,position is %d ",*pos); return OK; } else { printf("NOT find child string yet. "); return ERROR; } }
其次,StrInsert();插入函数中也比较难想,因为其需要讨论插入位置以及插入后长度是否越界问题,设计算法时易漏了其中某一个情况。
该模块函数封装代码如下:
/* 在串T的第pos个位置后插入子串S */ Status StrInsert(SString T,SString S,int pos) { int i; if(pos > T[0]) { pos = T[0] +1; } if(T[0] + S[0] <= MAXSTRLEN) { for(i = 1; i <= pos;i++) T[T[0] + S[0] - i +1] = T[T[0] + S[0] - i -pos]; for(i = 1;i <= S[0];i++) T[pos + i] = S[i]; T[0] = T[0] + S[0]; return OK; } if(T[0] + S[0] > MAXSTRLEN) { for(i = 1;i <= (MAXSTRLEN - pos);i++) T[i + pos] = S[i]; //超出部分被删除 T[0] = MAXSTRLEN; return ERROR; } }
代码
/************************************************************************* > File Name: String fuctions > Author: Bw98 > Mail: 786016746@qq.com > Blog: www.cnblogs.com/Bw98blogs/ > Created Time: SUN 23th Jul. 2017 ************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXSTRLEN 40 #define OK 1 #define ERROR 0 #define TURE 1 #define FALSE 0 #define OVERFLOW -2 typedef int Status; typedef char SString[MAXSTRLEN+1]; Status StrEmpty(SString S); Status StrAssign(SString T,char *chars); Status StrCopy(SString T,SString S); Status StrLength(SString T); Status StrPrint(SString T); Status StrClear(SString S); Status StrConcat(SString T,SString S1,SString S2); Status StrIndex(SString T,SString S,int *pos); Status StrInsert(SString T,SString S,int pos); Status StrDelete(SString T,int pos,int len); int main() { /* 根据功能自行调用 */ return 0; } /* 字符串赋值,当赋值字符串长度超过被赋值字符串时候截断,未超过时先将长度存入T[0],再逐位赋值 */ Status StrAssign(SString T,char *chars) { int i; if(strlen(chars)>MAXSTRLEN) { for(i = 1;i <= MAXSTRLEN;i++) { T[i] = *(chars + i - 1); } T[0] = MAXSTRLEN; //T[0]存入int 型数据,%s无法打印 } else { T[0] = strlen(chars); //T[0]存入的是chars的字符长度 for(i = 1;i <= strlen(chars);i++) { T[i] = *(chars + i - 1); } } return OK; } /* 字符串拷贝,逐个字符拷贝(仅拷贝长度范围内的) */ Status StrCopy(SString T,SString S) { int i; for(i = 1;i <= S[0];i++) { T[i] = S[i]; } T[0] = S[0]; return OK; } /* 字符串判空,S[0] == 0时为空 */ Status StrEmpty(SString T) { if(T[0] == 0) { printf("The string is empty! "); return TURE; } else { printf("The string is NOT empty! "); return FALSE; } } /* 返回该字符串的长度 */ Status StrLength(SString T) { return T[0]; } /* 打印字符串 */ Status StrPrint(SString T) { int i; for(i = 1;i <= T[0];i++) printf("%c",T[i]); printf(" "); return OK; } /* 清除字符串,即长度清空 */ Status StrClear(SString S) { S[0] = 0; return OK; } /* 字符串联接,通过T来存储结果,S2连接而成的新串,若未截断则返回TRUE,截断返回FAlSE,注意字符串数组越界问题 */ Status StrConcat(SString T,SString S1,SString S2) { int i; if(S1[0]+S2[0] <= MAXSTRLEN) { for(i = 1;i <= S1[0];i++) { T[i] = S1[i]; } for(i = 1;i <= S2[0];i++) { T[S1[0]+i] = S2[i]; } T[0] = S1[0] + S2[0]; return TURE; } else { for(i = 1;i <= S1[0];i++) { T[i] = S1[i]; } for(i = 1;i <= (MAXSTRLEN-S1[0]);i++) { T[S1[0]+i] = S2[i]; } T[0] = MAXSTRLEN; return FALSE; } } /* 索引子串,返回串T中第一个索引到与串S相同的子串的位置 */ Status StrIndex(SString T,SString S,int *pos) { int i=1,j=1; while((i <= T[0]) && (j <= S[0])) { if(T[i] == S[j]) { i++; j++; } else { i = i - j + 2; j = 1; } } if(j > S[0]) { *pos = i - j + 1; printf("Found,position is %d ",*pos); return OK; } else { printf("NOT find child string yet. "); return ERROR; } } /* 在串T的第pos个位置后插入子串S */ Status StrInsert(SString T,SString S,int pos) { int i; if(pos > T[0]) { pos = T[0] +1; } if(T[0] + S[0] <= MAXSTRLEN) { for(i = 1; i <= pos;i++) T[T[0] + S[0] - i +1] = T[T[0] + S[0] - i -pos]; for(i = 1;i <= S[0];i++) T[pos + i] = S[i]; T[0] = T[0] + S[0]; return OK; } if(T[0] + S[0] > MAXSTRLEN) { for(i = 1;i <= (MAXSTRLEN - pos);i++) T[i + pos] = S[i]; //超出部分被删除 T[0] = MAXSTRLEN; return ERROR; } } /* 删除串T的第pos个位置起,长为len的子串 */ Status StrDelete(SString T,int pos,int len) { int i; if(pos > T[0]) return ERROR; if(len > T[0]) len = T[0] - pos + 1; for(i = len + pos;i <= T[0];i++) T[i - len] =T[i]; T[0] = T[0] - len; return OK; }