mirror of
https://github.com/kangjianwei/Data-Structure.git
synced 2026-02-06 00:07:05 +08:00
💡 <04 串>习题代码
This commit is contained in:
35
CLion/ExerciseBook/04.10/04.10.c
Normal file
35
CLion/ExerciseBook/04.10/04.10.c
Normal 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;
|
||||
}
|
||||
|
||||
7
CLion/ExerciseBook/04.10/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.10/CMakeLists.txt
Normal 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)
|
||||
151
CLion/ExerciseBook/04.10/String.c
Normal file
151
CLion/ExerciseBook/04.10/String.c
Normal 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);
|
||||
}
|
||||
43
CLion/ExerciseBook/04.10/String.h
Normal file
43
CLion/ExerciseBook/04.10/String.h
Normal 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
|
||||
69
CLion/ExerciseBook/04.11/04.11.c
Normal file
69
CLion/ExerciseBook/04.11/04.11.c
Normal 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;
|
||||
}
|
||||
7
CLion/ExerciseBook/04.11/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.11/CMakeLists.txt
Normal 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)
|
||||
151
CLion/ExerciseBook/04.11/String.c
Normal file
151
CLion/ExerciseBook/04.11/String.c
Normal 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);
|
||||
}
|
||||
43
CLion/ExerciseBook/04.11/String.h
Normal file
43
CLion/ExerciseBook/04.11/String.h
Normal 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
|
||||
56
CLion/ExerciseBook/04.12/04.12.c
Normal file
56
CLion/ExerciseBook/04.12/04.12.c
Normal 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;
|
||||
}
|
||||
7
CLion/ExerciseBook/04.12/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.12/CMakeLists.txt
Normal 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)
|
||||
151
CLion/ExerciseBook/04.12/String.c
Normal file
151
CLion/ExerciseBook/04.12/String.c
Normal 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);
|
||||
}
|
||||
43
CLion/ExerciseBook/04.12/String.h
Normal file
43
CLion/ExerciseBook/04.12/String.h
Normal 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
|
||||
41
CLion/ExerciseBook/04.13/04.13.c
Normal file
41
CLion/ExerciseBook/04.13/04.13.c
Normal 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;
|
||||
}
|
||||
7
CLion/ExerciseBook/04.13/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.13/CMakeLists.txt
Normal 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)
|
||||
151
CLion/ExerciseBook/04.13/String.c
Normal file
151
CLion/ExerciseBook/04.13/String.c
Normal 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);
|
||||
}
|
||||
43
CLion/ExerciseBook/04.13/String.h
Normal file
43
CLion/ExerciseBook/04.13/String.h
Normal 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
|
||||
92
CLion/ExerciseBook/04.14/04.14.c
Normal file
92
CLion/ExerciseBook/04.14/04.14.c
Normal 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);
|
||||
}
|
||||
7
CLion/ExerciseBook/04.14/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.14/CMakeLists.txt
Normal 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)
|
||||
89
CLion/ExerciseBook/04.14/SqStack.c
Normal file
89
CLion/ExerciseBook/04.14/SqStack.c
Normal 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;
|
||||
}
|
||||
61
CLion/ExerciseBook/04.14/SqStack.h
Normal file
61
CLion/ExerciseBook/04.14/SqStack.h
Normal 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
|
||||
151
CLion/ExerciseBook/04.14/String.c
Normal file
151
CLion/ExerciseBook/04.14/String.c
Normal 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);
|
||||
}
|
||||
43
CLion/ExerciseBook/04.14/String.h
Normal file
43
CLion/ExerciseBook/04.14/String.h
Normal 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
|
||||
92
CLion/ExerciseBook/04.15-04.17/04.15-04.17.c
Normal file
92
CLion/ExerciseBook/04.15-04.17/04.15-04.17.c
Normal 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);
|
||||
}
|
||||
7
CLion/ExerciseBook/04.15-04.17/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.15-04.17/CMakeLists.txt
Normal 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)
|
||||
406
CLion/ExerciseBook/04.15-04.17/SString.c
Normal file
406
CLion/ExerciseBook/04.15-04.17/SString.c
Normal 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");
|
||||
}
|
||||
179
CLion/ExerciseBook/04.15-04.17/SString.h
Normal file
179
CLion/ExerciseBook/04.15-04.17/SString.h
Normal 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
|
||||
62
CLion/ExerciseBook/04.18/04.18.c
Normal file
62
CLion/ExerciseBook/04.18/04.18.c
Normal 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;
|
||||
}
|
||||
7
CLion/ExerciseBook/04.18/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.18/CMakeLists.txt
Normal 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)
|
||||
406
CLion/ExerciseBook/04.18/SString.c
Normal file
406
CLion/ExerciseBook/04.18/SString.c
Normal 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");
|
||||
}
|
||||
179
CLion/ExerciseBook/04.18/SString.h
Normal file
179
CLion/ExerciseBook/04.18/SString.h
Normal 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
|
||||
77
CLion/ExerciseBook/04.19/04.19.c
Normal file
77
CLion/ExerciseBook/04.19/04.19.c
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
7
CLion/ExerciseBook/04.19/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.19/CMakeLists.txt
Normal 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)
|
||||
406
CLion/ExerciseBook/04.19/SString.c
Normal file
406
CLion/ExerciseBook/04.19/SString.c
Normal 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");
|
||||
}
|
||||
179
CLion/ExerciseBook/04.19/SString.h
Normal file
179
CLion/ExerciseBook/04.19/SString.h
Normal 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
|
||||
47
CLion/ExerciseBook/04.20/04.20.c
Normal file
47
CLion/ExerciseBook/04.20/04.20.c
Normal 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;
|
||||
}
|
||||
7
CLion/ExerciseBook/04.20/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.20/CMakeLists.txt
Normal 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)
|
||||
406
CLion/ExerciseBook/04.20/SString.c
Normal file
406
CLion/ExerciseBook/04.20/SString.c
Normal 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");
|
||||
}
|
||||
179
CLion/ExerciseBook/04.20/SString.h
Normal file
179
CLion/ExerciseBook/04.20/SString.h
Normal 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
|
||||
336
CLion/ExerciseBook/04.21/04.21.c
Normal file
336
CLion/ExerciseBook/04.21/04.21.c
Normal 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");
|
||||
}
|
||||
7
CLion/ExerciseBook/04.21/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.21/CMakeLists.txt
Normal 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)
|
||||
59
CLion/ExerciseBook/04.22/04.22.c
Normal file
59
CLion/ExerciseBook/04.22/04.22.c
Normal 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);
|
||||
}
|
||||
}
|
||||
7
CLion/ExerciseBook/04.22/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.22/CMakeLists.txt
Normal 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)
|
||||
747
CLion/ExerciseBook/04.22/LString.c
Normal file
747
CLion/ExerciseBook/04.22/LString.c
Normal file
File diff suppressed because it is too large
Load Diff
169
CLion/ExerciseBook/04.22/LString.h
Normal file
169
CLion/ExerciseBook/04.22/LString.h
Normal 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的块可能为:ABCD -> EFGH -> IJKL -> MN\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
|
||||
107
CLion/ExerciseBook/04.23/04.23.c
Normal file
107
CLion/ExerciseBook/04.23/04.23.c
Normal 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;
|
||||
}
|
||||
}
|
||||
7
CLion/ExerciseBook/04.23/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.23/CMakeLists.txt
Normal 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)
|
||||
748
CLion/ExerciseBook/04.23/LString.c
Normal file
748
CLion/ExerciseBook/04.23/LString.c
Normal file
File diff suppressed because it is too large
Load Diff
169
CLion/ExerciseBook/04.23/LString.h
Normal file
169
CLion/ExerciseBook/04.23/LString.h
Normal 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的块可能为:ABCD -> EFGH -> IJKL -> MN\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
|
||||
101
CLion/ExerciseBook/04.24-04.26/04.24-04.26.c
Normal file
101
CLion/ExerciseBook/04.24-04.26/04.24-04.26.c
Normal 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);
|
||||
}
|
||||
7
CLion/ExerciseBook/04.24-04.26/CMakeLists.txt
Normal file
7
CLion/ExerciseBook/04.24-04.26/CMakeLists.txt
Normal 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
Reference in New Issue
Block a user