💡 <04 串>习题代码

This commit is contained in:
康建伟
2019-11-12 23:47:30 +08:00
parent f127e5cc2e
commit d2818b244f
244 changed files with 31894 additions and 0 deletions

View File

@@ -0,0 +1,35 @@
#include <stdio.h>
#include "String.h" //**字符串**//
/*
* 字符串逆置将T逆置为R。
*/
StringType Algo_4_10(StringType T) {
int i;
StringType R = "", Sub;
// 从后向前截取字符
for(i = StrLength(T); i >= 1; i--) {
Sub = SubString(T, i, 1);
R = Concat(R, Sub);
}
return R;
}
int main(int argc, char* argv[]) {
char* s = "0123456789";
StringType T, R;
printf("逆置前T = ");
StrAssign(&T, s);
StrPrint(T);
printf("逆置后R = ");
R = Algo_4_10(T);
StrPrint(R);
return 0;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.10 String.h String.c 04.10.c)
# 链接公共库
target_link_libraries(04.10 Scanf_lib)

View File

@@ -0,0 +1,151 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#include "String.h"
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s) {
if(s == NULL) {
*t = "";
}
*t = (char*) malloc((strlen(s) + 1) * sizeof(char));
strcpy(*t, s);
}
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t) {
return strcmp(s, t);
}
// 计数返回字符串s的长度
int StrLength(StringType s) {
return (int) strlen(s);
}
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t) {
StringType r;
if(s == NULL) {
s = "";
}
if(t == NULL) {
t = "";
}
r = (char*) malloc((strlen(s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
strcat(r, s);
strcat(r, t);
return r;
}
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len) {
int n;
char* sub;
n = (int) strlen(s);
if(start < 1 || start > n || start + len - 1 > n || len < 0) {
return "";
}
sub = (char*) malloc((len + 1) * sizeof(char));
strncpy(sub, s + start - 1, len);
sub[len] = '\0';
return sub;
}
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos) {
int m, n, i;
StringType sub;
// 失败情形提前处理
if(pos < 1 || pos > StrLength(s) || StrLength(t) == 0) {
return 0;
}
n = StrLength(s);
m = StrLength(t);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
sub = SubString(s, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, t) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t) {
StringType r;
StringType s1, s2;
if(pos < 1 || pos > StrLength(*s) + 1) {
return ERROR;
}
r = (StringType) malloc((strlen(*s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
// 如果待插入的串为空,则提前返回
if(StrLength(t) == 0) {
return OK;
}
s1 = SubString(*s, 1, pos - 1);
s2 = SubString(*s, pos, (int) strlen(*s) - pos + 1);
strcat(r, s1);
strcat(r, t);
strcat(r, s2);
*s = r;
return OK;
}
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len) {
StringType r;
if(pos < 1 || pos + len - 1 > StrLength(*s) || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
r = (StringType) malloc((StrLength(*s) - len + 1) * sizeof(char));
strncpy(r, *s, pos - 1);
strcpy(r + pos - 1, *s + pos + len - 1);
*s = r;
return OK;
}
// 输出字符串
void StrPrint(StringType s) {
printf("%s\n", s);
}

View File

@@ -0,0 +1,43 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#ifndef STRING_H
#define STRING_H
#include <stdlib.h>
#include <string.h> // 提供 strlen 原型
#include "Status.h" //**▲01 绪论**//
/* 字符串类型 */
typedef char* StringType;
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s);
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t);
// 计数返回字符串s的长度
int StrLength(StringType s);
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t);
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len);
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos);
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t);
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len);
// 输出字符串
void StrPrint(StringType s);
#endif

View File

@@ -0,0 +1,69 @@
#include <stdio.h>
#include <stdlib.h>
#include "String.h" //**字符串**//
/*
* R=S-S∩T数组a存储R中每个字符在S中第一次出现的位置
*
* 注数组a的0号单元存储的是a中元素的个数
*/
void Algo_4_11(StringType* R, StringType S, StringType T, int** a) {
int i, p;
StringType ch;
*a = (int*) malloc((StrLength(S) + 1) * sizeof(int));
StrAssign(R, "");
for(i = 1, (*a)[0] = 0; i <= StrLength(S); i++) {
// 取出字符进行判断
ch = SubString(S, i, 1);
// 获取S[i]在T中的位置
p = Index(T, ch, 1);
// 如果S[i]不在T中
if(p == 0) {
// 获取S[i]在R中的位置
p = Index(*R, ch, 1);
}
// 如果S[i]既不在T中又没在R中出现过
if(p == 0) {
(*a)[0]++;
(*a)[(*a)[0]] = i;
// 向R中添加S[i]
StrInsert(R, (*a)[0], ch);
}
}
}
int main(int argc, char* argv[]) {
char* s = "amdhcjgfdlpinbefcopgkqikeb";
char* t = "mhjlpinopkqik";
int* a;
StringType T, S, R;
int i;
printf("初始化S和T...\n");
StrAssign(&S, s);
StrAssign(&T, t);
printf("S = ");
StrPrint(S);
printf("T = ");
StrPrint(T);
Algo_4_11(&R, S, T, &a);
printf("R = ");
StrPrint(R);
printf("a = ");
for(i = 1; i <= a[0]; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.11 String.h String.c 04.11.c)
# 链接公共库
target_link_libraries(04.11 Scanf_lib)

View File

@@ -0,0 +1,151 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#include "String.h"
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s) {
if(s == NULL) {
*t = "";
}
*t = (char*) malloc((strlen(s) + 1) * sizeof(char));
strcpy(*t, s);
}
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t) {
return strcmp(s, t);
}
// 计数返回字符串s的长度
int StrLength(StringType s) {
return (int) strlen(s);
}
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t) {
StringType r;
if(s == NULL) {
s = "";
}
if(t == NULL) {
t = "";
}
r = (char*) malloc((strlen(s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
strcat(r, s);
strcat(r, t);
return r;
}
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len) {
int n;
char* sub;
n = (int) strlen(s);
if(start < 1 || start > n || start + len - 1 > n || len < 0) {
return "";
}
sub = (char*) malloc((len + 1) * sizeof(char));
strncpy(sub, s + start - 1, len);
sub[len] = '\0';
return sub;
}
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos) {
int m, n, i;
StringType sub;
// 失败情形提前处理
if(pos < 1 || pos > StrLength(s) || StrLength(t) == 0) {
return 0;
}
n = StrLength(s);
m = StrLength(t);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
sub = SubString(s, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, t) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t) {
StringType r;
StringType s1, s2;
if(pos < 1 || pos > StrLength(*s) + 1) {
return ERROR;
}
r = (StringType) malloc((strlen(*s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
// 如果待插入的串为空,则提前返回
if(StrLength(t) == 0) {
return OK;
}
s1 = SubString(*s, 1, pos - 1);
s2 = SubString(*s, pos, (int) strlen(*s) - pos + 1);
strcat(r, s1);
strcat(r, t);
strcat(r, s2);
*s = r;
return OK;
}
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len) {
StringType r;
if(pos < 1 || pos + len - 1 > StrLength(*s) || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
r = (StringType) malloc((StrLength(*s) - len + 1) * sizeof(char));
strncpy(r, *s, pos - 1);
strcpy(r + pos - 1, *s + pos + len - 1);
*s = r;
return OK;
}
// 输出字符串
void StrPrint(StringType s) {
printf("%s\n", s);
}

View File

@@ -0,0 +1,43 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#ifndef STRING_H
#define STRING_H
#include <stdlib.h>
#include <string.h> // 提供 strlen 原型
#include "Status.h" //**▲01 绪论**//
/* 字符串类型 */
typedef char* StringType;
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s);
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t);
// 计数返回字符串s的长度
int StrLength(StringType s);
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t);
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len);
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos);
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t);
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len);
// 输出字符串
void StrPrint(StringType s);
#endif

View File

@@ -0,0 +1,56 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "String.h" //**字符串**//
/*
* 替换Replace
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串
*/
Status Algo_4_12(StringType* S, StringType T, StringType V) {
int i;
if(StrLength(*S) == 0 || StrLength(T) == 0) {
return ERROR;
}
i = 1;
// 在主串S中寻找模式串T第一次出现的位置
while((i = Index(*S, T, i)) != 0) {
StrDelete(S, i, StrLength(T)); // 从S中删除T
StrInsert(S, i, V); // 向S中插入V
i += StrLength(V); // i切换到下一个位置
}
return OK;
}
int main(int argc, char* argv[]) {
char* s = "----***--*-**-****-*****-----";
char* t = "**";
char* v = "^^";
StringType T, S, V;
printf("替换前...\n");
StrAssign(&S, s);
StrAssign(&T, t);
StrAssign(&V, v);
printf("S = ");
StrPrint(S);
printf("T = ");
StrPrint(T);
printf("V = ");
StrPrint(V);
printf("替换后...\n");
printf("S = ");
Algo_4_12(&S, T, V);
StrPrint(S);
return 0;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.12 String.h String.c 04.12.c)
# 链接公共库
target_link_libraries(04.12 Scanf_lib)

View File

@@ -0,0 +1,151 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#include "String.h"
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s) {
if(s == NULL) {
*t = "";
}
*t = (char*) malloc((strlen(s) + 1) * sizeof(char));
strcpy(*t, s);
}
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t) {
return strcmp(s, t);
}
// 计数返回字符串s的长度
int StrLength(StringType s) {
return (int) strlen(s);
}
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t) {
StringType r;
if(s == NULL) {
s = "";
}
if(t == NULL) {
t = "";
}
r = (char*) malloc((strlen(s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
strcat(r, s);
strcat(r, t);
return r;
}
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len) {
int n;
char* sub;
n = (int) strlen(s);
if(start < 1 || start > n || start + len - 1 > n || len < 0) {
return "";
}
sub = (char*) malloc((len + 1) * sizeof(char));
strncpy(sub, s + start - 1, len);
sub[len] = '\0';
return sub;
}
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos) {
int m, n, i;
StringType sub;
// 失败情形提前处理
if(pos < 1 || pos > StrLength(s) || StrLength(t) == 0) {
return 0;
}
n = StrLength(s);
m = StrLength(t);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
sub = SubString(s, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, t) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t) {
StringType r;
StringType s1, s2;
if(pos < 1 || pos > StrLength(*s) + 1) {
return ERROR;
}
r = (StringType) malloc((strlen(*s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
// 如果待插入的串为空,则提前返回
if(StrLength(t) == 0) {
return OK;
}
s1 = SubString(*s, 1, pos - 1);
s2 = SubString(*s, pos, (int) strlen(*s) - pos + 1);
strcat(r, s1);
strcat(r, t);
strcat(r, s2);
*s = r;
return OK;
}
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len) {
StringType r;
if(pos < 1 || pos + len - 1 > StrLength(*s) || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
r = (StringType) malloc((StrLength(*s) - len + 1) * sizeof(char));
strncpy(r, *s, pos - 1);
strcpy(r + pos - 1, *s + pos + len - 1);
*s = r;
return OK;
}
// 输出字符串
void StrPrint(StringType s) {
printf("%s\n", s);
}

View File

@@ -0,0 +1,43 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#ifndef STRING_H
#define STRING_H
#include <stdlib.h>
#include <string.h> // 提供 strlen 原型
#include "Status.h" //**▲01 绪论**//
/* 字符串类型 */
typedef char* StringType;
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s);
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t);
// 计数返回字符串s的长度
int StrLength(StringType s);
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t);
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len);
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos);
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t);
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len);
// 输出字符串
void StrPrint(StringType s);
#endif

View File

@@ -0,0 +1,41 @@
#include <stdio.h>
#include "String.h" //**字符串**//
/*
* 删除S中包含的T
*/
Status Algo_4_13(StringType* S, StringType T) {
int i;
// 在S中查找T如果找到就删除
while((i = Index(*S, T, 1)) != 0) {
if(StrDelete(S, i, StrLength(T)) == ERROR) {
return ERROR;
}
}
return OK;
}
int main(int argc, char* argv[]) {
char* s = "----***--*-**-****-*****-----";
char* t = "**";
StringType T, S;
printf("删除前...\n");
StrAssign(&S, s);
StrAssign(&T, t);
printf("S = ");
StrPrint(S);
printf("T = ");
StrPrint(T);
printf("删除后...\n");
printf("S = ");
Algo_4_13(&S, T);
StrPrint(S);
return 0;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.13 String.h String.c 04.13.c)
# 链接公共库
target_link_libraries(04.13 Scanf_lib)

View File

@@ -0,0 +1,151 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#include "String.h"
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s) {
if(s == NULL) {
*t = "";
}
*t = (char*) malloc((strlen(s) + 1) * sizeof(char));
strcpy(*t, s);
}
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t) {
return strcmp(s, t);
}
// 计数返回字符串s的长度
int StrLength(StringType s) {
return (int) strlen(s);
}
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t) {
StringType r;
if(s == NULL) {
s = "";
}
if(t == NULL) {
t = "";
}
r = (char*) malloc((strlen(s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
strcat(r, s);
strcat(r, t);
return r;
}
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len) {
int n;
char* sub;
n = (int) strlen(s);
if(start < 1 || start > n || start + len - 1 > n || len < 0) {
return "";
}
sub = (char*) malloc((len + 1) * sizeof(char));
strncpy(sub, s + start - 1, len);
sub[len] = '\0';
return sub;
}
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos) {
int m, n, i;
StringType sub;
// 失败情形提前处理
if(pos < 1 || pos > StrLength(s) || StrLength(t) == 0) {
return 0;
}
n = StrLength(s);
m = StrLength(t);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
sub = SubString(s, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, t) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t) {
StringType r;
StringType s1, s2;
if(pos < 1 || pos > StrLength(*s) + 1) {
return ERROR;
}
r = (StringType) malloc((strlen(*s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
// 如果待插入的串为空,则提前返回
if(StrLength(t) == 0) {
return OK;
}
s1 = SubString(*s, 1, pos - 1);
s2 = SubString(*s, pos, (int) strlen(*s) - pos + 1);
strcat(r, s1);
strcat(r, t);
strcat(r, s2);
*s = r;
return OK;
}
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len) {
StringType r;
if(pos < 1 || pos + len - 1 > StrLength(*s) || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
r = (StringType) malloc((StrLength(*s) - len + 1) * sizeof(char));
strncpy(r, *s, pos - 1);
strcpy(r + pos - 1, *s + pos + len - 1);
*s = r;
return OK;
}
// 输出字符串
void StrPrint(StringType s) {
printf("%s\n", s);
}

View File

@@ -0,0 +1,43 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#ifndef STRING_H
#define STRING_H
#include <stdlib.h>
#include <string.h> // 提供 strlen 原型
#include "Status.h" //**▲01 绪论**//
/* 字符串类型 */
typedef char* StringType;
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s);
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t);
// 计数返回字符串s的长度
int StrLength(StringType s);
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t);
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len);
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos);
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t);
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len);
// 输出字符串
void StrPrint(StringType s);
#endif

View File

@@ -0,0 +1,92 @@
#include <stdio.h>
#include <string.h>
#include "SqStack.h" //**▲03 栈和队列**//
#include "String.h" //**字符串**//
/*
* 将前缀表达式prefix转换为后缀表达式
*
*【注】
* 未对前缀表达式的正确性进行验证
*/
Status Algo_4_14(const char* prefix, char** suffix) {
StringType P, S;
StringType Operator; // 运算符
SqStack stack; // 表达式栈
StringType e; // 栈顶元素
StringType o; // 靠近栈顶的运算符
int i, len;
int readStr; // 是否需要读取字符串
len = (int) strlen(prefix);
if(len == 0) {
*suffix = NULL;
return ERROR;
}
// 运算符和操作数
StrAssign(&Operator, "+-*/");
// 前缀表达式
StrAssign(&P, prefix);
// 后缀表达式栈
InitStack(&stack);
readStr = 1;
i = 1;
// 遍历前缀表达式,逐个获取元素
while(TRUE) {
if(readStr == 1) {
S = SubString(P, i++, 1);
}
// 如果遇到了运算符,则直接入栈
if(Index(Operator, S, 1) != 0) {
Push(&stack, S);
readStr = 1;
// 如果遇到了操作数
} else {
// 获取栈顶元素如果栈已经为空则S中存储了后缀表达式
if(GetTop(stack, &e) == ERROR) {
break;
}
// 如果栈顶元素是运算符,则将操作数直接入栈
if(Index(Operator, e, 1) != 0) {
Push(&stack, S);
readStr = 1;
// 否则栈顶也是操作数,需要进行简单运算
} else {
Pop(&stack, &e); // 弹出栈顶操作数
Pop(&stack, &o); // 弹出靠近栈顶的运算符
S = Concat(e, S);
S = Concat(S, o);
// 此种情形下不需要读取字符串而需要判断刚刚计算出的Sub
readStr = 0;
}
}
}
// 获取后缀表达式
*suffix = S;
return OK;
}
int main(int argc, char* argv[]) {
char* prefix = "-+a*bc/de"; // 其后缀表达式为abc*+de/-
char* suffix;
Algo_4_14(prefix, &suffix);
printf("前缀表达式:%s\n", prefix);
printf("后缀表达式:%s\n", suffix);
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.14 SqStack.h SqStack.c String.h String.c 04.14.c)
# 链接公共库
target_link_libraries(04.14 Scanf_lib)

View File

@@ -0,0 +1,89 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#include "SqStack.h" //**▲03 栈和队列**//
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S) {
if(S == NULL) {
return ERROR;
}
(*S).base = (SElemType*) malloc(STACK_INIT_SIZE * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW);
}
(*S).top = (*S).base;
(*S).stacksize = STACK_INIT_SIZE;
return OK;
}
/*
* 取值
*
* 返回栈顶元素并用e接收。
*/
Status GetTop(SqStack S, SElemType* e) {
if(S.base == NULL || S.top == S.base) {
return ERROR;
}
// 不会改变栈中元素
*e = *(S.top - 1);
return OK;
}
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
// 栈满时,追加存储空间
if((*S).top - (*S).base >= (*S).stacksize) {
(*S).base = (SElemType*) realloc((*S).base, ((*S).stacksize + STACKINCREMENT) * sizeof(SElemType));
if((*S).base == NULL) {
exit(OVERFLOW); // 存储分配失败
}
(*S).top = (*S).base + (*S).stacksize;
(*S).stacksize += STACKINCREMENT;
}
// 进栈先赋值,栈顶指针再自增
*(S->top++) = e;
return OK;
}
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e) {
if(S == NULL || (*S).base == NULL) {
return ERROR;
}
if((*S).top == (*S).base) {
return ERROR;
}
// 出栈栈顶指针先递减,再赋值
*e = *(--(*S).top);
return OK;
}

View File

@@ -0,0 +1,61 @@
/*=========================
* 栈的顺序存储结构(顺序栈)
==========================*/
#ifndef SQSTACK_H
#define SQSTACK_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include "Status.h" //**▲01 绪论**//
#include "String.h" //**▲04 串**//
/* 宏定义 */
#define STACK_INIT_SIZE 100 // 顺序栈存储空间的初始分配量
#define STACKINCREMENT 10 // 顺序栈存储空间的分配增量
/*
* 顺序栈元素类型定义
*
*【注】
* 这里的元素类型为字符串
*/
typedef StringType SElemType;
// 顺序栈元素结构
typedef struct {
SElemType* base; // 栈底指针
SElemType* top; // 栈顶指针
int stacksize; // 当前已分配的存储空间,以元素为单位
} SqStack;
/*
* 初始化
*
* 构造一个空栈。初始化成功则返回OK否则返回ERROR。
*/
Status InitStack(SqStack* S);
/*
* 取值
*
* 返回栈顶元素并用e接收。
*/
Status GetTop(SqStack S, SElemType* e);
/*
* 入栈
*
* 将元素e压入到栈顶。
*/
Status Push(SqStack* S, SElemType e);
/*
* 出栈
*
* 将栈顶元素弹出并用e接收。
*/
Status Pop(SqStack* S, SElemType* e);
#endif

View File

@@ -0,0 +1,151 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#include "String.h"
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s) {
if(s == NULL) {
*t = "";
}
*t = (char*) malloc((strlen(s) + 1) * sizeof(char));
strcpy(*t, s);
}
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t) {
return strcmp(s, t);
}
// 计数返回字符串s的长度
int StrLength(StringType s) {
return (int) strlen(s);
}
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t) {
StringType r;
if(s == NULL) {
s = "";
}
if(t == NULL) {
t = "";
}
r = (char*) malloc((strlen(s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
strcat(r, s);
strcat(r, t);
return r;
}
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len) {
int n;
char* sub;
n = (int) strlen(s);
if(start < 1 || start > n || start + len - 1 > n || len < 0) {
return "";
}
sub = (char*) malloc((len + 1) * sizeof(char));
strncpy(sub, s + start - 1, len);
sub[len] = '\0';
return sub;
}
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos) {
int m, n, i;
StringType sub;
// 失败情形提前处理
if(pos < 1 || pos > StrLength(s) || StrLength(t) == 0) {
return 0;
}
n = StrLength(s);
m = StrLength(t);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
sub = SubString(s, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, t) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t) {
StringType r;
StringType s1, s2;
if(pos < 1 || pos > StrLength(*s) + 1) {
return ERROR;
}
r = (StringType) malloc((strlen(*s) + strlen(t) + 1) * sizeof(char));
r[0] = '\0';
// 如果待插入的串为空,则提前返回
if(StrLength(t) == 0) {
return OK;
}
s1 = SubString(*s, 1, pos - 1);
s2 = SubString(*s, pos, (int) strlen(*s) - pos + 1);
strcat(r, s1);
strcat(r, t);
strcat(r, s2);
*s = r;
return OK;
}
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len) {
StringType r;
if(pos < 1 || pos + len - 1 > StrLength(*s) || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
r = (StringType) malloc((StrLength(*s) - len + 1) * sizeof(char));
strncpy(r, *s, pos - 1);
strcpy(r + pos - 1, *s + pos + len - 1);
*s = r;
return OK;
}
// 输出字符串
void StrPrint(StringType s) {
printf("%s\n", s);
}

View File

@@ -0,0 +1,43 @@
/*===========================
* 习题4.10~4.14中使用的字符串
============================*/
#ifndef STRING_H
#define STRING_H
#include <stdlib.h>
#include <string.h> // 提供 strlen 原型
#include "Status.h" //**▲01 绪论**//
/* 字符串类型 */
typedef char* StringType;
// 初始化构造一个值为s的串t
void StrAssign(StringType* t, const char* s);
// 比较返回s与t的大小如果大小一致返回0
int StrCompare(StringType s, StringType t);
// 计数返回字符串s的长度
int StrLength(StringType s);
// 联接返回由s与t联接后的串
StringType Concat(StringType s, StringType t);
// 求子串从s的start位置起截取len个字符后返回
StringType SubString(StringType s, int start, int len);
// 查找从s的pos位置起查找t如果找到返回其位置
int Index(StringType s, StringType t, int pos);
// 插入在s的pos处插入t
Status StrInsert(StringType* s, int pos, StringType t);
// 删除从s的pos位置起删除len个字符
Status StrDelete(StringType* s, int pos, int len);
// 输出字符串
void StrPrint(StringType s);
#endif

View File

@@ -0,0 +1,92 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SString.h" //**▲04 串**//
/*
* 初始化StrAssign
*
*【注】
* 该函数已在SString相关文件中定义
*/
Status Algo_4_15(SString T, char* chars);
/*
* 比较StrCompare
*
*【注】
* 该函数已在SString相关文件中定义
*/
int Algo_4_16(SString S, SString T);
/*
* 替换Replace
*
*【注】
* 该函数已在SString相关文件中定义
*/
Status Algo_4_17(SString S, SString T, SString V);
int main(int argc, char* argv[]) {
char* t = "ab**c*de***fg";
char* s = "ab**c*de***fh";
SString T, S, M1, M2;
int i;
printf("███题 4.15 验证...███\n");
Algo_4_15(T, t);
Algo_4_15(S, s);
printf("T = ");
StrPrint(T);
printf("S = ");
StrPrint(S);
printf("███题 4.16 验证...███\n");
i = Algo_4_16(S, T);
if(i > 0) {
printf("S > T\n");
} else if(i < 0) {
printf("S < T\n");
} else {
printf("S == T\n");
}
printf("███题 4.17 验证...███\n");
Algo_4_15(M1, "**");
Algo_4_15(M2, "^");
Algo_4_17(S, M1, M2);
printf("\"^\" 替换 \"**\" 后:\nS = ");
StrPrint(S);
return 0;
}
/*
* 初始化StrAssign
*
*【注】
* 该函数已在SString相关文件中定义
*/
Status Algo_4_15(SString T, char* chars) {
return StrAssign(T, chars);
}
/*
* 比较StrCompare
*
*【注】
* 该函数已在SString相关文件中定义
*/
int Algo_4_16(SString S, SString T) {
return StrCompare(S, T);
}
/*
* 替换Replace
*
*【注】
* 该函数已在SString相关文件中定义
*/
Status Algo_4_17(SString S, SString T, SString V) {
return Replace(S, T, V);
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.15-04.17 SString.h SString.c 04.15-04.17.c)
# 链接公共库
target_link_libraries(04.15-04.17 Scanf_lib)

View File

@@ -0,0 +1,406 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#include "SString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars) {
int i, len;
len = (int) strlen(chars);
// chars过长
if(len > MAXSTRLEN) {
return ERROR;
}
T[0] = len;
for(i = 1; i <= len; i++) {
T[i] = chars[i - 1];
}
return OK;
}
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S) {
return OK;
}
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S) {
// 只需要将长度置为0就可以
S[0] = 0;
return OK;
}
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S) {
return S[0] == 0 ? TRUE : FALSE;
}
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S) {
return S[0];
}
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len) {
int i;
if(pos < 1 || pos > S[0] || len < 0 || pos + len - 1 > S[0]) {
return ERROR;
}
// 复制元素
for(i = 1; i <= len; i++) {
Sub[i] = S[pos + i - 1];
}
// 确定新长度
Sub[0] = len;
return OK;
}
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos) {
int i, n, m; // 记录S和T的长度
SString sub;
/*
* 失败情形提前处理
* 这里与教材写法略微不同
*/
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
n = StrLength(S);
m = StrLength(T);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
SubString(sub, S, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, T) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos) {
int i = pos;
int j = 1;
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
while(i <= S[0] && j <= T[0]) {
// 遇到相同字符,则继续比较后继字符
if(S[i] == T[j]) {
i++;
j++;
// 遇到不同的字符,则游标需要回退,重新比较
} else {
i = i - (j - 1) + 1; // j-1代表徒劳地前进了j-1个元素在第j个元素上功亏一篑
j = 1; // 游标j回到串T的第一个位置
}
}
// 增加了一个T[0]>0的判断
if(j > T[0] && T[0] > 0) { // T不为空串
return i - T[0]; // 匹配成功
} else {
return 0;
}
}
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T) {
int i;
if(pos < 1 || pos > S[0] + 1 || S[0] + T[0] > MAXSTRLEN) {
return ERROR;
}
// 如果待插入的串为空,则提前返回
if(StrEmpty(T)) {
return OK;
}
// 在S中腾出位置为插入T做准备
for(i = S[0]; i >= pos; i--) {
// 从后向前遍历,将前面的元素挪到后面
S[i + T[0]] = S[i];
}
// 将串T插入在S中腾出的位置上
for(i = pos; i <= pos + T[0] - 1; i++) {
S[i] = T[i - pos + 1];
}
// 长度增加
S[0] += T[0];
return OK;
}
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len) {
int i;
if(pos < 1 || pos + len - 1 > S[0] || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
// 把后面的元素挪到前面,覆盖掉被删除的元素
for(i = pos + len; i <= S[0]; i++) {
S[i - len] = S[i];
}
// 长度减少
S[0] -= len;
return OK;
}
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T) {
int i = 1;
while(i <= S[0] && i <= T[0]) {
// 遇到不同的字符时,比较其大小
if(S[i] != T[i]) {
return S[i] - T[i];
}
i++;
}
return S[0] - T[0];
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S) {
int i;
// 连同长度信息一起复制
for(i = 0; i <= S[0]; i++) {
T[i] = S[i];
}
return OK;
}
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 1.该操作依赖最小操作子集
* 2.该实现比较低效
*/
Status Replace(SString S, SString T, SString V) {
int i;
if(StrEmpty(S) || StrEmpty(T)) {
return ERROR;
}
// 在主串S中寻找模式串T第一次出现的位置
i = Index_2(S, T, 1);
// 如果存在匹配的字符串,且可以被完全替换(替换后不溢出)
while(i != 0 && S[0] - T[0] + V[0] <= MAXSTRLEN) {
StrDelete(S, i, StrLength(T)); // 从S中删除T
StrInsert(S, i, V); // 向S中插入V
i += StrLength(V); // i切换到下一个位置
i = Index_2(S, T, i); // 查找下一个匹配的字符串
}
if(i == 0) { // S中的T已全部被替换
return OK;
} else { // S中尚有T但是V已经插不进去了
return ERROR;
}
}
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2) {
int i;
int uncut; // 新串是否完整
// 完全不需要裁剪
if(S1[0] + S2[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 复制S2到T中
for(i = S1[0] + 1; i <= S1[0] + S2[0]; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = S1[0] + S2[0];
// 未裁剪,完整
uncut = TRUE;
// 需要裁剪S2
} else if(S1[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 将S2的一部分复制到T中
for(i = S1[0] + 1; i <= MAXSTRLEN; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = MAXSTRLEN;
uncut = FALSE;
// 只需要复制S1的一部分
} else {
// 连同长度信息一起复制
for(i = 0; i <= MAXSTRLEN; i++) {
T[i] = S1[i];
}
uncut = FALSE;
}
return uncut;
}
// 输出:打印字符串
void StrPrint(SString S) {
int i;
for(i = 1; i<=S[0] ; i++) {
printf("%c", S[i]);
}
printf("\n");
}

View File

@@ -0,0 +1,179 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#ifndef SSTRING_H
#define SSTRING_H
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXSTRLEN 255 // 顺序串的最大串长
/*
* 串的顺序存储类型定义
*
* 注有效元素从SString的1号单元开始存储
* SString的0号单元用来存储其长度
*/
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
/*
* ████ 提示 ████
*
* 遵循教材的书写习惯pos指示字符的位序(不是索引)从1开始计数
*/
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars);
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S);
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S);
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S);
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S);
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len);
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos);
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos);
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T);
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len);
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S);
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 该操作依赖最小操作子集,效率较低。
*/
Status Replace(SString S, SString T, SString V);
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2);
// 输出:打印字符串
void StrPrint(SString S);
#endif

View File

@@ -0,0 +1,62 @@
#include <stdio.h>
#include <stdlib.h>
#include "SString.h" //**▲04 串**//
/*
* 统计字符串S中不同字符总数与每种字符的个数返回统计结果
*/
int* Algo_4_18(SString S);
int main(int argc, char* argv[]) {
char* s = "dbasydujhge638940[gptokljrsehgadcsbnmv,c.b'ng[p098437eywdghswqdecxvghju";
SString S;
int* total;
int i;
StrAssign(S, s);
printf("S = ");
StrPrint(S);
total = Algo_4_18(S);
printf(" S 中不同的字符共计 %d 个:\n", total[0]);
for(i = 1; i <= 127; i++) {
if(total[i] != 0) {
printf("字符 \'%c\' 有 %d 个.\n", i, total[i]);
}
}
printf("统计完毕...\n");
return 0;
}
/*
* 统计字符串S中不同字符总数与每种字符的个数返回统计结果
*/
int* Algo_4_18(SString S) {
int i;
int* total;
/*
* total长度设为128
* 0号单元存储不同字符的总数
* 其他单元存储各种不同字符的数量。
*
* 注:不统计空字符'\0'
*/
total = (int*) malloc(128 * sizeof(int));
memset(total, 0, 128 * sizeof(int));
for(i = 1; i <= S[0]; i++) {
// 如果遇到了新字符,则统计不同字符的数量
if(total[S[i]] == 0) {
total[0]++;
}
// 统计遇到的字符数量
total[S[i]]++;
}
return total;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.18 SString.h SString.c 04.18.c)
# 链接公共库
target_link_libraries(04.18 Scanf_lib)

View File

@@ -0,0 +1,406 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#include "SString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars) {
int i, len;
len = (int) strlen(chars);
// chars过长
if(len > MAXSTRLEN) {
return ERROR;
}
T[0] = len;
for(i = 1; i <= len; i++) {
T[i] = chars[i - 1];
}
return OK;
}
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S) {
return OK;
}
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S) {
// 只需要将长度置为0就可以
S[0] = 0;
return OK;
}
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S) {
return S[0] == 0 ? TRUE : FALSE;
}
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S) {
return S[0];
}
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len) {
int i;
if(pos < 1 || pos > S[0] || len < 0 || pos + len - 1 > S[0]) {
return ERROR;
}
// 复制元素
for(i = 1; i <= len; i++) {
Sub[i] = S[pos + i - 1];
}
// 确定新长度
Sub[0] = len;
return OK;
}
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos) {
int i, n, m; // 记录S和T的长度
SString sub;
/*
* 失败情形提前处理
* 这里与教材写法略微不同
*/
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
n = StrLength(S);
m = StrLength(T);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
SubString(sub, S, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, T) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos) {
int i = pos;
int j = 1;
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
while(i <= S[0] && j <= T[0]) {
// 遇到相同字符,则继续比较后继字符
if(S[i] == T[j]) {
i++;
j++;
// 遇到不同的字符,则游标需要回退,重新比较
} else {
i = i - (j - 1) + 1; // j-1代表徒劳地前进了j-1个元素在第j个元素上功亏一篑
j = 1; // 游标j回到串T的第一个位置
}
}
// 增加了一个T[0]>0的判断
if(j > T[0] && T[0] > 0) { // T不为空串
return i - T[0]; // 匹配成功
} else {
return 0;
}
}
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T) {
int i;
if(pos < 1 || pos > S[0] + 1 || S[0] + T[0] > MAXSTRLEN) {
return ERROR;
}
// 如果待插入的串为空,则提前返回
if(StrEmpty(T)) {
return OK;
}
// 在S中腾出位置为插入T做准备
for(i = S[0]; i >= pos; i--) {
// 从后向前遍历,将前面的元素挪到后面
S[i + T[0]] = S[i];
}
// 将串T插入在S中腾出的位置上
for(i = pos; i <= pos + T[0] - 1; i++) {
S[i] = T[i - pos + 1];
}
// 长度增加
S[0] += T[0];
return OK;
}
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len) {
int i;
if(pos < 1 || pos + len - 1 > S[0] || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
// 把后面的元素挪到前面,覆盖掉被删除的元素
for(i = pos + len; i <= S[0]; i++) {
S[i - len] = S[i];
}
// 长度减少
S[0] -= len;
return OK;
}
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T) {
int i = 1;
while(i <= S[0] && i <= T[0]) {
// 遇到不同的字符时,比较其大小
if(S[i] != T[i]) {
return S[i] - T[i];
}
i++;
}
return S[0] - T[0];
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S) {
int i;
// 连同长度信息一起复制
for(i = 0; i <= S[0]; i++) {
T[i] = S[i];
}
return OK;
}
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 1.该操作依赖最小操作子集
* 2.该实现比较低效
*/
Status Replace(SString S, SString T, SString V) {
int i;
if(StrEmpty(S) || StrEmpty(T)) {
return ERROR;
}
// 在主串S中寻找模式串T第一次出现的位置
i = Index_2(S, T, 1);
// 如果存在匹配的字符串,且可以被完全替换(替换后不溢出)
while(i != 0 && S[0] - T[0] + V[0] <= MAXSTRLEN) {
StrDelete(S, i, StrLength(T)); // 从S中删除T
StrInsert(S, i, V); // 向S中插入V
i += StrLength(V); // i切换到下一个位置
i = Index_2(S, T, i); // 查找下一个匹配的字符串
}
if(i == 0) { // S中的T已全部被替换
return OK;
} else { // S中尚有T但是V已经插不进去了
return ERROR;
}
}
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2) {
int i;
int uncut; // 新串是否完整
// 完全不需要裁剪
if(S1[0] + S2[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 复制S2到T中
for(i = S1[0] + 1; i <= S1[0] + S2[0]; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = S1[0] + S2[0];
// 未裁剪,完整
uncut = TRUE;
// 需要裁剪S2
} else if(S1[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 将S2的一部分复制到T中
for(i = S1[0] + 1; i <= MAXSTRLEN; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = MAXSTRLEN;
uncut = FALSE;
// 只需要复制S1的一部分
} else {
// 连同长度信息一起复制
for(i = 0; i <= MAXSTRLEN; i++) {
T[i] = S1[i];
}
uncut = FALSE;
}
return uncut;
}
// 输出:打印字符串
void StrPrint(SString S) {
int i;
for(i = 1; i<=S[0] ; i++) {
printf("%c", S[i]);
}
printf("\n");
}

View File

@@ -0,0 +1,179 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#ifndef SSTRING_H
#define SSTRING_H
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXSTRLEN 255 // 顺序串的最大串长
/*
* 串的顺序存储类型定义
*
* 注有效元素从SString的1号单元开始存储
* SString的0号单元用来存储其长度
*/
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
/*
* ████ 提示 ████
*
* 遵循教材的书写习惯pos指示字符的位序(不是索引)从1开始计数
*/
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars);
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S);
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S);
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S);
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S);
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len);
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos);
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos);
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T);
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len);
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S);
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 该操作依赖最小操作子集,效率较低。
*/
Status Replace(SString S, SString T, SString V);
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2);
// 输出:打印字符串
void StrPrint(SString S);
#endif

View File

@@ -0,0 +1,77 @@
#include <stdio.h>
#include <stdlib.h>
#include "SString.h" //**▲04 串**//
/*
* R=S-S∩T数组a存储R中每个字符在S中第一次出现的位置
*
* 注数组a的0号单元存储的是a中元素的个数
*/
void Algo_4_19(SString R, SString S, SString T, int** a);
int main(int argc, char* argv[]) {
char* s = "amdhcjgfdlpinbefcopgkqikeb";
char* t = "mhjlpinopkqik";
int* a;
SString T, S, R;
int i;
printf("初始化S和T...\n");
StrAssign(S, s);
StrAssign(T, t);
printf("S = ");
StrPrint(S);
printf("T = ");
StrPrint(T);
Algo_4_19(R, S, T, &a);
printf("R = ");
StrPrint(R);
printf("a = ");
for(i = 1; i <= a[0]; i++) {
printf("%d ", a[i]);
}
printf("\n");
return 0;
}
/*
* R=S-S∩T数组a存储R中每个字符在S中第一次出现的位置
*
* 注数组a的0号单元存储的是a中元素的个数
*/
void Algo_4_19(SString R, SString S, SString T, int** a) {
int i, p;
SString ch;
*a = (int*) malloc((StrLength(S) + 1) * sizeof(int));
StrAssign(R, "");
for(i = 1, (*a)[0] = 0; i <= StrLength(S); i++) {
// 取出字符进行判断
SubString(ch, S, i, 1);
// 获取S[i]在T中的位置
p = Index_2(T, ch, 1);
// 如果S[i]不在T中
if(p == 0) {
// 获取S[i]在R中的位置
p = Index_2(R, ch, 1);
}
// 如果S[i]既不在T中又没在R中出现过
if(p == 0) {
(*a)[0]++;
(*a)[(*a)[0]] = i;
// 向R中添加S[i]
StrInsert(R, (*a)[0], ch);
}
}
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.19 SString.h SString.c 04.19.c)
# 链接公共库
target_link_libraries(04.19 Scanf_lib)

View File

@@ -0,0 +1,406 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#include "SString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars) {
int i, len;
len = (int) strlen(chars);
// chars过长
if(len > MAXSTRLEN) {
return ERROR;
}
T[0] = len;
for(i = 1; i <= len; i++) {
T[i] = chars[i - 1];
}
return OK;
}
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S) {
return OK;
}
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S) {
// 只需要将长度置为0就可以
S[0] = 0;
return OK;
}
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S) {
return S[0] == 0 ? TRUE : FALSE;
}
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S) {
return S[0];
}
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len) {
int i;
if(pos < 1 || pos > S[0] || len < 0 || pos + len - 1 > S[0]) {
return ERROR;
}
// 复制元素
for(i = 1; i <= len; i++) {
Sub[i] = S[pos + i - 1];
}
// 确定新长度
Sub[0] = len;
return OK;
}
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos) {
int i, n, m; // 记录S和T的长度
SString sub;
/*
* 失败情形提前处理
* 这里与教材写法略微不同
*/
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
n = StrLength(S);
m = StrLength(T);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
SubString(sub, S, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, T) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos) {
int i = pos;
int j = 1;
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
while(i <= S[0] && j <= T[0]) {
// 遇到相同字符,则继续比较后继字符
if(S[i] == T[j]) {
i++;
j++;
// 遇到不同的字符,则游标需要回退,重新比较
} else {
i = i - (j - 1) + 1; // j-1代表徒劳地前进了j-1个元素在第j个元素上功亏一篑
j = 1; // 游标j回到串T的第一个位置
}
}
// 增加了一个T[0]>0的判断
if(j > T[0] && T[0] > 0) { // T不为空串
return i - T[0]; // 匹配成功
} else {
return 0;
}
}
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T) {
int i;
if(pos < 1 || pos > S[0] + 1 || S[0] + T[0] > MAXSTRLEN) {
return ERROR;
}
// 如果待插入的串为空,则提前返回
if(StrEmpty(T)) {
return OK;
}
// 在S中腾出位置为插入T做准备
for(i = S[0]; i >= pos; i--) {
// 从后向前遍历,将前面的元素挪到后面
S[i + T[0]] = S[i];
}
// 将串T插入在S中腾出的位置上
for(i = pos; i <= pos + T[0] - 1; i++) {
S[i] = T[i - pos + 1];
}
// 长度增加
S[0] += T[0];
return OK;
}
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len) {
int i;
if(pos < 1 || pos + len - 1 > S[0] || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
// 把后面的元素挪到前面,覆盖掉被删除的元素
for(i = pos + len; i <= S[0]; i++) {
S[i - len] = S[i];
}
// 长度减少
S[0] -= len;
return OK;
}
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T) {
int i = 1;
while(i <= S[0] && i <= T[0]) {
// 遇到不同的字符时,比较其大小
if(S[i] != T[i]) {
return S[i] - T[i];
}
i++;
}
return S[0] - T[0];
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S) {
int i;
// 连同长度信息一起复制
for(i = 0; i <= S[0]; i++) {
T[i] = S[i];
}
return OK;
}
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 1.该操作依赖最小操作子集
* 2.该实现比较低效
*/
Status Replace(SString S, SString T, SString V) {
int i;
if(StrEmpty(S) || StrEmpty(T)) {
return ERROR;
}
// 在主串S中寻找模式串T第一次出现的位置
i = Index_2(S, T, 1);
// 如果存在匹配的字符串,且可以被完全替换(替换后不溢出)
while(i != 0 && S[0] - T[0] + V[0] <= MAXSTRLEN) {
StrDelete(S, i, StrLength(T)); // 从S中删除T
StrInsert(S, i, V); // 向S中插入V
i += StrLength(V); // i切换到下一个位置
i = Index_2(S, T, i); // 查找下一个匹配的字符串
}
if(i == 0) { // S中的T已全部被替换
return OK;
} else { // S中尚有T但是V已经插不进去了
return ERROR;
}
}
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2) {
int i;
int uncut; // 新串是否完整
// 完全不需要裁剪
if(S1[0] + S2[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 复制S2到T中
for(i = S1[0] + 1; i <= S1[0] + S2[0]; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = S1[0] + S2[0];
// 未裁剪,完整
uncut = TRUE;
// 需要裁剪S2
} else if(S1[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 将S2的一部分复制到T中
for(i = S1[0] + 1; i <= MAXSTRLEN; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = MAXSTRLEN;
uncut = FALSE;
// 只需要复制S1的一部分
} else {
// 连同长度信息一起复制
for(i = 0; i <= MAXSTRLEN; i++) {
T[i] = S1[i];
}
uncut = FALSE;
}
return uncut;
}
// 输出:打印字符串
void StrPrint(SString S) {
int i;
for(i = 1; i<=S[0] ; i++) {
printf("%c", S[i]);
}
printf("\n");
}

View File

@@ -0,0 +1,179 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#ifndef SSTRING_H
#define SSTRING_H
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXSTRLEN 255 // 顺序串的最大串长
/*
* 串的顺序存储类型定义
*
* 注有效元素从SString的1号单元开始存储
* SString的0号单元用来存储其长度
*/
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
/*
* ████ 提示 ████
*
* 遵循教材的书写习惯pos指示字符的位序(不是索引)从1开始计数
*/
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars);
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S);
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S);
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S);
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S);
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len);
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos);
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos);
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T);
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len);
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S);
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 该操作依赖最小操作子集,效率较低。
*/
Status Replace(SString S, SString T, SString V);
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2);
// 输出:打印字符串
void StrPrint(SString S);
#endif

View File

@@ -0,0 +1,47 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "SString.h" //**▲04 串**//
/*
* 删除S中包含的T
*/
Status Algo_4_20(SString S, SString T);
int main(int argc, char* argv[]) {
char* s = "----***--*-**-****-*****-----";
char* t = "**";
SString T, S;
printf("删除前...\n");
StrAssign(S, s);
StrAssign(T, t);
printf("S = ");
StrPrint(S);
printf("T = ");
StrPrint(T);
printf("删除后...\n");
printf("S = ");
Algo_4_20(S, T);
StrPrint(S);
return 0;
}
/*
* 删除S中包含的T
*/
Status Algo_4_20(SString S, SString T) {
int i;
// 在S中查找T如果找到就删除
while((i = Index_2(S, T, 1)) != 0) {
if(StrDelete(S, i, StrLength(T)) == ERROR) {
return ERROR;
}
}
return OK;
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.20 SString.h SString.c 04.20.c)
# 链接公共库
target_link_libraries(04.20 Scanf_lib)

View File

@@ -0,0 +1,406 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#include "SString.h" //**▲04 串**//
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars) {
int i, len;
len = (int) strlen(chars);
// chars过长
if(len > MAXSTRLEN) {
return ERROR;
}
T[0] = len;
for(i = 1; i <= len; i++) {
T[i] = chars[i - 1];
}
return OK;
}
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S) {
return OK;
}
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S) {
// 只需要将长度置为0就可以
S[0] = 0;
return OK;
}
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S) {
return S[0] == 0 ? TRUE : FALSE;
}
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S) {
return S[0];
}
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len) {
int i;
if(pos < 1 || pos > S[0] || len < 0 || pos + len - 1 > S[0]) {
return ERROR;
}
// 复制元素
for(i = 1; i <= len; i++) {
Sub[i] = S[pos + i - 1];
}
// 确定新长度
Sub[0] = len;
return OK;
}
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos) {
int i, n, m; // 记录S和T的长度
SString sub;
/*
* 失败情形提前处理
* 这里与教材写法略微不同
*/
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
n = StrLength(S);
m = StrLength(T);
i = pos;
// 保证长度不越界
while(i <= n - m + 1) {
// 获取S[i, i+m-1]
SubString(sub, S, i, m);
// 如果子串与模式串不匹配,则需要继续推进
if(StrCompare(sub, T) != 0) {
++i;
} else {
return i;
}
}
return 0;
}
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos) {
int i = pos;
int j = 1;
if(pos < 1 || pos > S[0] || StrEmpty(T)) {
return 0;
}
while(i <= S[0] && j <= T[0]) {
// 遇到相同字符,则继续比较后继字符
if(S[i] == T[j]) {
i++;
j++;
// 遇到不同的字符,则游标需要回退,重新比较
} else {
i = i - (j - 1) + 1; // j-1代表徒劳地前进了j-1个元素在第j个元素上功亏一篑
j = 1; // 游标j回到串T的第一个位置
}
}
// 增加了一个T[0]>0的判断
if(j > T[0] && T[0] > 0) { // T不为空串
return i - T[0]; // 匹配成功
} else {
return 0;
}
}
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T) {
int i;
if(pos < 1 || pos > S[0] + 1 || S[0] + T[0] > MAXSTRLEN) {
return ERROR;
}
// 如果待插入的串为空,则提前返回
if(StrEmpty(T)) {
return OK;
}
// 在S中腾出位置为插入T做准备
for(i = S[0]; i >= pos; i--) {
// 从后向前遍历,将前面的元素挪到后面
S[i + T[0]] = S[i];
}
// 将串T插入在S中腾出的位置上
for(i = pos; i <= pos + T[0] - 1; i++) {
S[i] = T[i - pos + 1];
}
// 长度增加
S[0] += T[0];
return OK;
}
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len) {
int i;
if(pos < 1 || pos + len - 1 > S[0] || len < 0) {
return ERROR;
}
// 如果待删除的长度为0则提前返回
if(len == 0) {
return OK;
}
// 把后面的元素挪到前面,覆盖掉被删除的元素
for(i = pos + len; i <= S[0]; i++) {
S[i - len] = S[i];
}
// 长度减少
S[0] -= len;
return OK;
}
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T) {
int i = 1;
while(i <= S[0] && i <= T[0]) {
// 遇到不同的字符时,比较其大小
if(S[i] != T[i]) {
return S[i] - T[i];
}
i++;
}
return S[0] - T[0];
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S) {
int i;
// 连同长度信息一起复制
for(i = 0; i <= S[0]; i++) {
T[i] = S[i];
}
return OK;
}
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 1.该操作依赖最小操作子集
* 2.该实现比较低效
*/
Status Replace(SString S, SString T, SString V) {
int i;
if(StrEmpty(S) || StrEmpty(T)) {
return ERROR;
}
// 在主串S中寻找模式串T第一次出现的位置
i = Index_2(S, T, 1);
// 如果存在匹配的字符串,且可以被完全替换(替换后不溢出)
while(i != 0 && S[0] - T[0] + V[0] <= MAXSTRLEN) {
StrDelete(S, i, StrLength(T)); // 从S中删除T
StrInsert(S, i, V); // 向S中插入V
i += StrLength(V); // i切换到下一个位置
i = Index_2(S, T, i); // 查找下一个匹配的字符串
}
if(i == 0) { // S中的T已全部被替换
return OK;
} else { // S中尚有T但是V已经插不进去了
return ERROR;
}
}
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2) {
int i;
int uncut; // 新串是否完整
// 完全不需要裁剪
if(S1[0] + S2[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 复制S2到T中
for(i = S1[0] + 1; i <= S1[0] + S2[0]; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = S1[0] + S2[0];
// 未裁剪,完整
uncut = TRUE;
// 需要裁剪S2
} else if(S1[0] <= MAXSTRLEN) {
// 复制S1到T中
for(i = 1; i <= S1[0]; i++) {
T[i] = S1[i];
}
// 将S2的一部分复制到T中
for(i = S1[0] + 1; i <= MAXSTRLEN; i++) {
T[i] = S2[i - S1[0]];
}
// 设置新长度
T[0] = MAXSTRLEN;
uncut = FALSE;
// 只需要复制S1的一部分
} else {
// 连同长度信息一起复制
for(i = 0; i <= MAXSTRLEN; i++) {
T[i] = S1[i];
}
uncut = FALSE;
}
return uncut;
}
// 输出:打印字符串
void StrPrint(SString S) {
int i;
for(i = 1; i<=S[0] ; i++) {
printf("%c", S[i]);
}
printf("\n");
}

View File

@@ -0,0 +1,179 @@
/*=============================
* 串的定长顺序存储表示(顺序串)
*
* 包含算法: 4.1、4.2、4.3、4.5
==============================*/
#ifndef SSTRING_H
#define SSTRING_H
#include <stdio.h>
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define MAXSTRLEN 255 // 顺序串的最大串长
/*
* 串的顺序存储类型定义
*
* 注有效元素从SString的1号单元开始存储
* SString的0号单元用来存储其长度
*/
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
/*
* ████ 提示 ████
*
* 遵循教材的书写习惯pos指示字符的位序(不是索引)从1开始计数
*/
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(SString T, const char* chars);
/*
* 销毁
*
* 将串S销毁。
*
*【注】
* 顺序串的结构无法销毁
*/
Status DestroyString(SString S);
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(SString S);
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(SString S);
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(SString S);
/*
* ████████ 算法4.3 ████████
*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(SString Sub, SString S, int pos, int len);
/*
* ████████ 算法4.1 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_1(SString S, SString T, int pos);
/*
* ████████ 算法4.5 ████████
*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现不依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index_2(SString S, SString T, int pos);
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(SString S, int pos, SString T);
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(SString S, int pos, int len);
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
int StrCompare(SString S, SString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(SString T, SString S);
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 该操作依赖最小操作子集,效率较低。
*/
Status Replace(SString S, SString T, SString V);
/*
* ████████ 算法4.2 ████████
*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(SString T, SString S1, SString S2);
// 输出:打印字符串
void StrPrint(SString S);
#endif

View File

@@ -0,0 +1,336 @@
#include <stdio.h>
#include <stdlib.h> // 提供 malloc、realloc、free、exit 原型
#include <string.h>
#include "Status.h" //**▲01 绪论**//
/*
* 单链表元素类型定义
*
*【注】
* 这里的链表虽然用作字符串但是元素类型仍然用int原因是
* 1.需要借用头结点存储结点的数量所以用int比直接用char合适
* 2.char可以与int兼容所以结点虽然是int但也可以用来存储char
*/
typedef int ElemType;
/*
* 单链表结构
*
* 注:这里的单链表存在头结点
*/
typedef struct SNode {
ElemType data; // 数据结点
struct SNode* next; // 指向下一个结点的指针
} SNode;
// 指向单链表结点的指针,用作字符串类型
typedef SNode* String;
/*
* 初始化
*
* 构造一个值为chars的串T。
*/
Status StrAssign_4_21(String* S, char* chars);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy_4_21(String* S, String T);
/*
* 比较
*
* 比较串S和串T返回比较结果。
*/
int StrCompare_4_21(String S, String T);
/*
* 计数
*
* 返回串S中元素的个数。
*/
int StrLength_4_21(String S);
/*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*/
Status Concat_4_21(String* R, String S1, String S2);
/*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*/
Status SubString_4_21(String* Sub, String S, int pos, int len);
// 字符串输出
void StrPrint_4_21(String S);
int main(int argc, char* argv[]) {
char* chars = "0123456789";
String S, T;
int i;
printf("████████ StrAssign \n");
{
printf("█ 为顺序串 S 赋值...\n");
StrAssign_4_21(&S, chars);
printf("█ S = ");
StrPrint_4_21(S);
}
PressEnterToContinue();
printf("████████ StrLength \n");
{
i = StrLength_4_21(S);
printf("█ S 的长度为 %d \n", i);
}
PressEnterToContinue();
printf("████████ StrCopy \n");
{
printf("█ 复制 S 到 T ...\n");
StrCopy_4_21(&T, S);
printf("█ T = ");
StrPrint_4_21(T);
}
PressEnterToContinue();
printf("████████ StrCompare \n");
{
printf("█ 比较字符串 S 和 T ...\n");
i = StrCompare_4_21(S, T);
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
}
PressEnterToContinue();
printf("████████ SubString \n");
{
String Sub;
printf("█ 用 Sub 返回 S 中第 6 个字符起的 5 个字符...\n");
SubString_4_21(&Sub, S, 6, 5);
printf("█ Sub = ");
StrPrint_4_21(Sub);
}
PressEnterToContinue();
printf("████████ Concat \n");
{
String Tmp, S1, S2;
StrAssign_4_21(&S1, "+++++");
StrAssign_4_21(&S2, "-----");
printf("█ 联接 \"+++++\"\"-----\" 形成 Tmp ...\n");
Concat_4_21(&Tmp, S1, S2);
printf("█ Tmp = ");
StrPrint_4_21(Tmp);
}
PressEnterToContinue();
return 0;
}
/*
* 初始化
*
* 构造一个值为chars的串T。
*/
Status StrAssign_4_21(String* S, char* chars) {
int i, len;
String p;
if(S == NULL || chars == NULL) {
return ERROR;
}
len = (int) strlen(chars);
*S = (SNode*) malloc(sizeof(SNode));
(*S)->data = len;
p = *S;
for(i = 0; i < len; i++) {
p->next = (SNode*) malloc(sizeof(SNode));
p->next->data = chars[i];
p = p->next;
}
p->next = NULL;
return OK;
}
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy_4_21(String* S, String T) {
String p, r, t;
if(S == NULL || T == NULL) {
return ERROR;
}
for(t = T; t != NULL; t = t->next) {
r = (SNode*) malloc(sizeof(SNode));
r->data = t->data;
if(t == T) {
*S = r;
p = r;
} else {
p->next = r;
p = p->next;
}
}
p->next = NULL;
return OK;
}
/*
* 比较
*
* 比较串S和串T返回比较结果。
*/
int StrCompare_4_21(String S, String T) {
String s, t;
if(S == NULL || T == NULL) {
return StrLength_4_21(S) - StrLength_4_21(T);
}
s = S->next;
t = T->next;
while(s != NULL && t != NULL) {
if(s->data != t->data) {
return s->data - t->data;
}
s = s->next;
t = t->next;
}
if(s == NULL && t != NULL) {
return -1;
} else if(s != NULL && t == NULL) {
return 1;
} else {
return 0;
}
}
/*
* 计数
*
* 返回串S中元素的个数。
*/
int StrLength_4_21(String S) {
return S == NULL ? 0 : S->data;
}
/*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*/
Status Concat_4_21(String* R, String S1, String S2) {
String r, s, p;
if(R == NULL || S1 == NULL || S2 == NULL) {
return ERROR;
}
*R = (SNode*) malloc(sizeof(SNode));
(*R)->data = S1->data + S2->data;
r = *R;
for(s = S1->next; s != NULL; s = s->next) {
p = (SNode*) malloc(sizeof(SNode));
p->data = s->data;
r->next = p;
r = r->next;
}
for(s = S2->next; s != NULL; s = s->next) {
p = (SNode*) malloc(sizeof(SNode));
p->data = s->data;
r->next = p;
r = r->next;
}
r->next = NULL;
return OK;
}
/*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*/
Status SubString_4_21(String* Sub, String S, int pos, int len) {
int i, slen;
String sub, s, p;
slen = StrLength_4_21(S);
if(Sub == NULL || S == NULL || pos < 1 || pos > slen || len < 0 || pos + len - 1 > slen) {
return ERROR;
}
*Sub = (SNode*) malloc(sizeof(SNode));
(*Sub)->data = len;
for(i = 0, s = S; i < pos; i++, s = s->next) {
// 查找第pos个结点并用s指向它
}
sub = *Sub;
for(i = 0; i < len; i++) {
sub->next = (SNode*) malloc(sizeof(SNode));
sub->next->data = s->data;
sub = sub->next;
s = s->next;
}
sub->next = NULL;
return OK;
}
// 字符串输出
void StrPrint_4_21(String S) {
String p;
if(S == NULL) {
return;
}
for(p = S->next; p != NULL; p = p->next) {
printf("%c", p->data);
}
printf("\n");
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.21 04.21.c)
# 链接公共库
target_link_libraries(04.21 Scanf_lib)

View File

@@ -0,0 +1,59 @@
#include <stdio.h>
#include "LString.h" //**▲04 串**//
/*
* 将S插入到T中的字符c之后。
* 如果有多个c则将S插入到从左向右遍历T时遇到的首个c之后。
* 如果T在不存在c则将S插入到T的末尾。
*/
void Algo_4_22(LString* T, char ch, LString S);
int main(int argc, char* argv[]) {
char* t = "----***--*-**-**^**-*****-----";
char* s = "12345";
char ch = '^';
LString T, S;
StrAssign(&T, t);
StrAssign(&S, s);
printf("T = ");
StrPrint(T);
printf("S = ");
StrPrint(S);
Algo_4_22(&T, ch, S);
printf("T = ");
StrPrint(T);
return 0;
}
/*
* 将S插入到T中的字符c之后。
* 如果有多个c则将S插入到从左向右遍历T时遇到的首个c之后。
* 如果T在不存在c则将S插入到T的末尾。
*/
void Algo_4_22(LString* T, char c, LString S) {
int i;
char tmp[2];
LString Tmp;
// 构造目标串
tmp[0] = c;
tmp[1] = '\0';
StrAssign(&Tmp, tmp);
// 寻找字符c在T中的位置
i = Index((*T), Tmp, 1);
// 如果找到了c则将S插入到字符c之后
if(i != 0) {
StrInsert(T, i + 1, S);
// 如果没找到c则将S插入到T的末尾
} else {
StrInsert(T, (*T).curlen + 1, S);
}
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.22 LString.h LString.c 04.22.c)
# 链接公共库
target_link_libraries(04.22 Scanf_lib)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,169 @@
/*=============================
* 串的块链分配存储表示(块链串)
==============================*/
#ifndef LSTRING_H
#define LSTRING_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define CHUNKSIZE 3 // 块大小(自定义)
/* 串的块链存储结构 */
typedef struct Chunk {
char ch[CHUNKSIZE]; // 当前块中的内容
struct Chunk* next; // 指向下一个块
} Chunk;
/* 串的块链存储类型定义 */
typedef struct {
Chunk* head; //串的头指针
Chunk* tail; //串的尾指针
int curlen; //串的当前长度
} LString;
/*
* ████ 提示 ████
*
* 遵循教材的书写习惯pos指示字符的位序(不是索引)从1开始计数
*/
/*
* ████ 注意 ████
*
* 1.教材示例中使用#作为非串值字符而这里使用C语言中的\0作为非串值字符
* 2.教材中指出,块链的最后一个块中,末尾可能是用非串值字符填充的。
* 例如块大小为4长度为14的块可能为 -> -> -> \0\0
*/
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(LString* T, const char* chars);
/*
* 销毁
*
* 将串S销毁。
*/
Status DestroyString(LString* S);
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(LString* S);
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(LString S);
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(LString S);
/*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(LString* Sub, LString S, int pos, int len);
/*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index(LString S, LString T, int pos);
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(LString* S, int pos, LString T);
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(LString* S, int pos, int len);
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(LString S, LString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(LString* T, LString S);
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 1.该操作依赖最小操作子集
* 2.该实现比较低效
*/
Status Replace(LString* S, LString T, LString V);
/*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(LString* T, LString S1, LString S2);
// 测试函数,打印字符串
void StrPrint(LString S);
#endif

View File

@@ -0,0 +1,107 @@
#include <stdio.h>
#include "LString.h" //**▲04 串**//
/*
* 判断给定的串是否对称。
* 空串或单字符的串会被认为是对称的。
*/
Status Algo_4_23(LString T);
int main(int argc, char* argv[]) {
char* t = "abcdefgfedcba";
LString T;
StrAssign(&T, t);
printf("T = ");
StrPrint(T);
Algo_4_23(T) ? printf("T是对称串\n") : printf("T是非对称串\n");
return 0;
}
/*
* 判断给定的串是否对称。
* 空串或单字符的串会被认为是对称的。
*/
Status Algo_4_23(LString T) {
int len; // T的长度
int a1, b1; // T的前半部分边界
int a2, b2; // T的后半部分边界
int k; // 限制遍历T时需要经过的元素数量
int i; // 遍历T时的游标
Chunk* t;
char* stack; // 模拟栈
int top; // 栈游标
char c; // 从T中取出的字符
len = StrLength(T);
// 空串被认为是对称的
if(len == 0) {
return OK;
}
// 如果串的长度是偶数
if(len % 2 == 0) {
a1 = 0;
b1 = len / 2 - 1;
a2 = len / 2;
b2 = len - 1;
// 如果串的长度是奇数
} else {
a1 = 0;
b1 = len / 2 - 1;
a2 = len / 2 + 1;
b2 = len - 1;
}
stack = (char*) malloc(len * sizeof(char));
top = -1;
i = 0;
t = T.head;
// 对于串的前半部分,将其入栈
for(k = a1; k <= b1; k++) {
c = t->ch[i];
i = (i + 1) % CHUNKSIZE;
if(i == 0) {
t = t->next;
}
stack[++top] = c;
}
// 如果串长为奇数,需要跨过一个字符
if(len % 2 == 1) {
i = (i + 1) % CHUNKSIZE;
if(i == 0) {
t = t->next;
}
}
for(k = a2; k <= b2; k++) {
c = t->ch[i];
i = (i + 1) % CHUNKSIZE;
if(i == 0) {
t = t->next;
}
// 遇到了不对称的字符
if(stack[top--] != c) {
return ERROR;
}
}
if(top == -1) {
return OK;
} else {
return ERROR;
}
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.23 LString.h LString.c 04.23.c)
# 链接公共库
target_link_libraries(04.23 Scanf_lib)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,169 @@
/*=============================
* 串的块链分配存储表示(块链串)
==============================*/
#ifndef LSTRING_H
#define LSTRING_H
#include <stdio.h>
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
#include <string.h> // 提供strlen原型
#include "Status.h" //**▲01 绪论**//
/* 宏定义 */
#define CHUNKSIZE 3 // 块大小(自定义)
/* 串的块链存储结构 */
typedef struct Chunk {
char ch[CHUNKSIZE]; // 当前块中的内容
struct Chunk* next; // 指向下一个块
} Chunk;
/* 串的块链存储类型定义 */
typedef struct {
Chunk* head; //串的头指针
Chunk* tail; //串的尾指针
int curlen; //串的当前长度
} LString;
/*
* ████ 提示 ████
*
* 遵循教材的书写习惯pos指示字符的位序(不是索引)从1开始计数
*/
/*
* ████ 注意 ████
*
* 1.教材示例中使用#作为非串值字符而这里使用C语言中的\0作为非串值字符
* 2.教材中指出,块链的最后一个块中,末尾可能是用非串值字符填充的。
* 例如块大小为4长度为14的块可能为 -> -> -> \0\0
*/
/*
* 初始化
*
* 构造一个值为chars的串T。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrAssign(LString* T, const char* chars);
/*
* 销毁
*
* 将串S销毁。
*/
Status DestroyString(LString* S);
/*
* 清空
*
* 将串S清空。
*/
Status ClearString(LString* S);
/*
* 判空
*
* 判断串S中是否包含有效数据。
*
* 返回值:
* TRUE : 串S为空
* FALSE: 串S不为空
*/
Status StrEmpty(LString S);
/*
* 计数
*
* 返回串S中元素的个数。
*
*【注】
* 该操作属于最小操作子集
*/
int StrLength(LString S);
/*
* 求子串
*
* 用Sub返回S[pos, pos+len-1]。
* 返回值指示是否截取成功。
*
*【注】
* 该操作属于最小操作子集
*/
Status SubString(LString* Sub, LString S, int pos, int len);
/*
* 查找
*
* 从pos处开始搜索模式串T在主串S中首次出现的位置如果不存在则返回0。
* 如果查找成功,返回匹配的位置。
*
*【注】
* 1.此实现需要依赖串的最小操作子集
* 2.该实现比较低效
*/
int Index(LString S, LString T, int pos);
/*
* 插入
*
* 将串T插入到主串S的pos位置处。
*/
Status StrInsert(LString* S, int pos, LString T);
/*
* 删除
*
* 删除S[pos, pos+len-1]。
*/
Status StrDelete(LString* S, int pos, int len);
/*
* 比较
*
* 比较串S和串T返回比较结果。
*
*【注】
* 该操作属于最小操作子集
*/
Status StrCompare(LString S, LString T);
/*
* 复制
*
* 将串S复制到串T。
*/
Status StrCopy(LString* T, LString S);
/*
* 替换
*
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
*
*【注】
* 1.该操作依赖最小操作子集
* 2.该实现比较低效
*/
Status Replace(LString* S, LString T, LString V);
/*
* 串联接
*
* 联接S1和S2并存储到T中返回。如果联接后的长度溢出则只保留未溢出的部分。
* 返回值表示联接后的串是否完整。
*
*【注】
* 该操作属于最小操作子集
*/
Status Concat(LString* T, LString S1, LString S2);
// 测试函数,打印字符串
void StrPrint(LString S);
#endif

View File

@@ -0,0 +1,101 @@
#include <stdio.h>
#include "Status.h" //**▲01 绪论**//
#include "HString.h" //**▲04 串**//
/*
* 联接Concat
*
*【注】
* 该函数已在HString相关文件中定义
*/
Status Algo_4_24(HString* T, HString S1, HString S2);
/*
* 替换Replace
*
*【注】
* 该函数已在HString相关文件中定义
*/
Status Algo_4_25(HString* S, HString T, HString V);
/*
* 插入StrInsert
*
*【注】
* 该函数已在HString相关文件中定义
*/
Status Algo_4_26(HString* S, int pos, HString T);
int main(int argc, char* argv[]) {
char* s = "---*^***^*^*^*---";
char* s1 = "*";
char* s2 = "^*";
char* v = "*_*";
HString S1, S2, T, V, S;
StrAssign(&S1, s1);
StrAssign(&S2, s2);
StrAssign(&V, v);
StrAssign(&S, s);
printf("S1 = ");
StrPrint(S1);
printf("S2 = ");
StrPrint(S2);
printf("V = ");
StrPrint(V);
printf("S = ");
StrPrint(S);
printf("███题 4.24 验证...███\n");
printf("连接S1和S2为T...\n");
Algo_4_24(&T, S1, S2);
printf("T = ");
StrPrint(T);
printf("███题 4.25 验证...███\n");
printf("用 V 替换 S 中的 T...\n");
Algo_4_25(&S, T, V);
printf("S = ");
StrPrint(S);
printf("███题 4.26 验证...███\n");
printf("将 T 插入到 S 的第 2 个位置...\n");
Algo_4_26(&S, 2, T);
printf("S = ");
StrPrint(S);
return 0;
}
/*
* 联接Concat
*
*【注】
* 该函数已在HString相关文件中定义
*/
Status Algo_4_24(HString* T, HString S1, HString S2) {
return Concat(T, S1, S2);
}
/*
* 替换Replace
*
*【注】
* 该函数已在HString相关文件中定义
*/
Status Algo_4_25(HString* S, HString T, HString V) {
return Replace(S, T, V);
}
/*
* 插入StrInsert
*
*【注】
* 该函数已在HString相关文件中定义
*/
Status Algo_4_26(HString* S, int pos, HString T) {
return StrInsert(S, pos, T);
}

View File

@@ -0,0 +1,7 @@
# 包含公共库
include_directories(${CMAKE_SOURCE_DIR}/Status)
# 生成可执行文件
add_executable(04.24-04.26 HString.h HString.c 04.24-04.26.c)
# 链接公共库
target_link_libraries(04.24-04.26 Scanf_lib)

Some files were not shown because too many files have changed in this diff Show More