#ifndef STRINGADT_H_
#define STRINGADT_H_
#include <stdbool.h>
#define FOLWOVER -1
struct StringADT;
typedef struct StringADT String;
struct StringADT
{
char * ch;
int length;
};
//为S开辟合适空间,储存输入的chars
void StrAssign(String &S, char * chars);
//利用S2覆盖S1
void StrCopy(String &S1, String &S2);
//串空返回true
bool StrIsEmpty(String &S);
//若S1>S2,返回1,以此类推
int StringCompare(String &S1, String &S2);
//返回字符串的长度
int StrLength(String &S);
//清空串S
void ClearString(String &S);
//将S2接在S1后面,赋值给T
void StrConcat(String &T, String &S1, String &S2);
//将S第pos个字符起,共len个字符另外组成一个字符串赋值给Sub
void SubString(String &Sub, String &S, int pos, int len);
//KMP算法,从第pos个字符算起,若T是S的子串,返回T第一次出现的位置
int Index(String &S, String &T, int pos);
//若T是S的子串,用V替代所有的T
void Replace(String &S, String &T, String &V);
//在串S的第pos个字符之前插入串T
void StrInsert(String &S, int pos, String &T);
//删除串S第pos个字符开始长度为len的字符串
void StrDelete(String &S, int pos, int len);
//打印出String,包括回车
void PrintfString(String &S);
#endif
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "stringadt.h"
void StrAssign(String &S, char * chars)
{
int i, lenChars = 0;//储存chars变量的长度
while (*chars != '\0'){ //计算长度
lenChars++;
chars++;
}
S.ch = (char *)malloc(lenChars * sizeof(char));//为字符串分配内存,这里不多开辟一个空间给'\0'
if (S.ch == NULL) //是因为有length来替代'\0'指示字符串的结尾
exit(FOLWOVER);
chars = chars - lenChars; //指针指回字符串的第一个值
S.length = lenChars;
for (i = 0; i < lenChars; i++)
S.ch[i] = chars[i];
}
void StrCopy(String &S1, String &S2)
{//用S2覆盖S1
free(S1.ch);
S1.ch = (char *)malloc(sizeof(char) * S2.length);
for (int i = 0; i < S2.length; i++){
S1.ch[i] = S2.ch[i];
}
S1.length = S2.length;
}
bool StrIsEmpty(String &S)
{
if (S.length == 0)
return true;
else
return false;
}
int StringCompare(String &S1, String &S2)
{
int i = 0, result = 0;
while (i < S1.length && i < S2.length){
if (S1.ch[i] > S2.ch[i]){
result = 1;
break;
}
else if (S1.ch[i] < S2.ch[i]){
result = -1;
break;
}
else
i++;
}
return result;
}
int StrLength(String &S)
{
return S.length;
}
void ClearString(String &S)
{
free(S.ch);//这样是删除,是删除所有字符
S.length = 0;
}
void StrConcat(String &T, String &S1, String &S2)
{//将S2接在S1后面存在T中
T.ch = (char *)malloc(sizeof(char) * (S1.length + S2.length));
for (int i = 0; i < S1.length; i++){
T.ch[i] = S1.ch[i];
}
for (int i = S1.length, j = 0; i < S2.length + S1.length; i++, j++){
T.ch[i] = S2.ch[j];
}
T.length = S1.length + S2.length;
}
void SubString(String &Sub, String &S, int pos, int len)
{//将S第pos个字符起,共len个字符另外组成一个字符串赋值给Sub
if (len + pos > S.length){
printf("超过字符串长度!");
}
else{
Sub.length = len;
Sub.ch = (char *)malloc(sizeof(char) * len);
for (int i = pos - 1, j = 0; i < pos + len - 1; i++, j++){
Sub.ch[j] = S.ch[i];
}
}
}
void nextInit(String &T, int next[])//检测无误
{//next数组初始化,next[j]的值表示第0到j-1构成的字符串中最长的 前缀后缀相同 的长度
int i = -1, j = 0;//i指向前缀,j指向后缀,
next[0] = -1;//用-1标记递归结束点
while (j < T.length - 1){
if (i == -1 || T.ch[i] == T.ch[j]){//当前缀后缀匹配失败后,i = -1,next[j] = 0
i++; //当匹配成功,即T.ch[i] == T.ch[j],next[j] = i
j++;//j指向后缀,不回溯
next[j] = i;
}
else{
i = next[i];//当i回溯到i = -1时,表示前缀后缀匹配失败
}
}
}
int Index(String &S, String &T, int pos)//验证无误
{//KMP算法,从第pos个字符算起,若T是S的子串,返回T第一次出现的位置(下标)
int i = 0, j = pos - 1;//i指向模式串,j指向主串
int * next;
int index = -1;
if (j + T.length > S.length - 1){
return index;
}
next = (int *)malloc(sizeof(int) * T.length);
nextInit(T, next);//初始化next数组
while (j < S.length){
if (i == -1 || T.ch[i] == S.ch[j]){
if (i == T.length - 1){//匹配完毕,index赋值,退出
index = j - i;
break;
}
i++;
j++;
}
else{
i = next[i];
}
}
return index;//匹配成功返回下标值,失败则返回-1
}
void Replace(String &S, String &T, String &V)
{//若T是S的子串,用V替代所有的T
int tempIndex;//记录T出现时的下标
tempIndex = Index(S, T, 1);
if (tempIndex == -1){
printf("不是子串!\n");
}
else{
while (tempIndex != -1){
StrDelete(S, tempIndex + 1, T.length);
StrInsert(S, tempIndex + 1, V);
tempIndex = Index(S, T, tempIndex + V.length + 1);
}
}
}
void StrInsert(String &S, int pos, String &T)//验证无误
{//在串S的第pos个字符之前插入串T
S.ch = (char *)realloc(S.ch, S.length + T.length);
for (int i = S.length - 1, j = T.length - 1; i >= pos - 1; i--, j--){
S.ch[i + T.length] = S.ch[i];//S.ch[pos - 1]开始的数据右移,腾出空间
}
for (int i = pos - 1, j = 0; j < T.length; i++, j++){
S.ch[i] = T.ch[j];//腾出的空间插入T.ch[]中的值
}
S.length = S.length + T.length;
}
void StrDelete(String &S, int pos, int len)//验证无误
{//删除串S第pos个字符开始长度为len的字符串
if (pos + len - 2 > S.length){
printf("字符串下标越界!\n");
}
else{
char * tempCharArray;
tempCharArray = (char *)malloc(sizeof(char) * (S.length - len));
for (int i = 0; i < pos - 1; i++){
tempCharArray[i] = S.ch[i];
}
for (int i = pos + len - 1, j = pos - 1; i < S.length; i++, j++){
tempCharArray[j] = S.ch[i];
}
free(S.ch);
S.ch = tempCharArray;
S.length = S.length - len;
}
}
void PrintfString(String &S)
{//打印出String,输出完后不换行
for (int i = 0; i < S.length; i++){
printf("%c", S.ch[i]);
}
printf("\n");
}
#include <stdio.h>
#include <stdlib.h>
#include "stringadt.h"
int main()
{
String testSS1;
String testST1;
String testSV1;
StrAssign(testSS1, "qwer");
StrAssign(testST1, "zxcvv");
PrintfString(testSS1);
PrintfString(testST1);
StrCopy(testST1, testSS1);
PrintfString(testST1);
int x = StringCompare(testSS1, testST1);
printf("x = %d\n", x);
int length = StrLength(testSS1);
printf("length = %d\n", length);
StrConcat(testSV1, testSS1, testST1);
PrintfString(testSV1);
SubString(testSS1, testST1, 2, 2);
PrintfString(testSS1);
String testSS;
String testST;
String testSV;
StrAssign(testSS, "qwerabaqwerqwerabab");
StrAssign(testST, "abab");
StrAssign(testSV, "AB");
PrintfString(testSS);
PrintfString(testST);
PrintfString(testSV);
//以下四选一轮流调试
//Replace(testSS, testST, testSV);
//PrintfString(testSS);
//StrInsert(testST, 2, testSV);
//PrintfString(testST);
//printf("%d\n", testST.length);
//StrDelete(testSS, 16, 4);
//PrintfString(testSS);
//int temp = Index(testSS, testST, 1);
//printf("%d\n", temp);
system("pause");
}