mirror of
https://github.com/kangjianwei/Data-Structure.git
synced 2026-02-06 08:21:44 +08:00
💡 顺序串、堆串、块链串
This commit is contained in:
7
CLion/CourseBook/0401_SString/CMakeLists.txt
Normal file
7
CLion/CourseBook/0401_SString/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# 包含公共库
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Status)
|
||||
|
||||
# 生成可执行文件
|
||||
add_executable(SString SString.h SString.c SString-main.c)
|
||||
# 链接公共库
|
||||
target_link_libraries(SString Scanf_lib)
|
||||
137
CLion/CourseBook/0401_SString/SString-main.c
Normal file
137
CLion/CourseBook/0401_SString/SString-main.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include "SString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(SString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
SString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为顺序串 S 赋值...\n");
|
||||
StrAssign(S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index_1(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
StrAssign(V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
SString Tmp, S1, S2;
|
||||
|
||||
StrAssign(S1, "+++++");
|
||||
StrAssign(S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(SString S) {
|
||||
int i;
|
||||
|
||||
for(i = 1; i <= S[0]; i++) {
|
||||
printf("%c", S[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
395
CLion/CourseBook/0401_SString/SString.c
Normal file
395
CLion/CourseBook/0401_SString/SString.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/*=============================
|
||||
* 串的定长顺序存储表示(顺序串)
|
||||
*
|
||||
* 包含算法: 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;
|
||||
}
|
||||
176
CLion/CourseBook/0401_SString/SString.h
Normal file
176
CLion/CourseBook/0401_SString/SString.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*=============================
|
||||
* 串的定长顺序存储表示(顺序串)
|
||||
*
|
||||
* 包含算法: 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);
|
||||
|
||||
#endif
|
||||
7
CLion/CourseBook/0402_HString/CMakeLists.txt
Normal file
7
CLion/CourseBook/0402_HString/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# 包含公共库
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Status)
|
||||
|
||||
# 生成可执行文件
|
||||
add_executable(HString HString.h HString.c HString-main.c)
|
||||
# 链接公共库
|
||||
target_link_libraries(HString Scanf_lib)
|
||||
137
CLion/CourseBook/0402_HString/HString-main.c
Normal file
137
CLion/CourseBook/0402_HString/HString-main.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include "HString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(HString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
HString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为堆串 S 赋值...\n");
|
||||
StrAssign(&S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(&T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(&S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(&sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
StrAssign(&V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(&S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(&S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(&S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
HString Tmp, S1, S2;
|
||||
|
||||
StrAssign(&S1, "+++++");
|
||||
StrAssign(&S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(&Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(HString S) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i <= S.length-1; i++) {
|
||||
printf("%c", S.ch[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
367
CLion/CourseBook/0402_HString/HString.c
Normal file
367
CLion/CourseBook/0402_HString/HString.c
Normal file
@@ -0,0 +1,367 @@
|
||||
/*=========================
|
||||
* 串的堆分配存储表示(堆串)
|
||||
*
|
||||
* 包含算法: 4.4
|
||||
==========================*/
|
||||
|
||||
#include "HString.h" //**▲04 串**//
|
||||
|
||||
/*
|
||||
* 初始化
|
||||
*
|
||||
* 构造一个值为chars的串T。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrAssign(HString* T, const char* chars) {
|
||||
int i, j;
|
||||
|
||||
// 求chars的长度
|
||||
i = (int) strlen(chars);
|
||||
|
||||
// 没有有效元素
|
||||
if(i == 0) {
|
||||
(*T).ch = NULL;
|
||||
(*T).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 存在有效元素时,需要分配存储空间
|
||||
(*T).ch = (char*) malloc(i * sizeof(char));
|
||||
if(!((*T).ch)) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
for(j = 0; j < i; j++) {
|
||||
(*T).ch[j] = chars[j];
|
||||
}
|
||||
|
||||
(*T).length = i;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 销毁
|
||||
*
|
||||
* 将串S销毁。
|
||||
*
|
||||
*【注】
|
||||
* 堆串的结构可以销毁,但不是在销毁操作中
|
||||
*/
|
||||
Status DestroyString(HString* S) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 清空
|
||||
*
|
||||
* 将串S清空。
|
||||
*/
|
||||
Status ClearString(HString* S) {
|
||||
// 没有有效元素时,销毁堆串结构
|
||||
if((*S).ch != 0) {
|
||||
free((*S).ch);
|
||||
(*S).ch = NULL;
|
||||
}
|
||||
|
||||
(*S).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 判空
|
||||
*
|
||||
* 判断串S中是否包含有效数据。
|
||||
*
|
||||
* 返回值:
|
||||
* TRUE : 串S为空
|
||||
* FALSE: 串S不为空
|
||||
*/
|
||||
Status StrEmpty(HString S) {
|
||||
return S.length == 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 计数
|
||||
*
|
||||
* 返回串S中元素的个数。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
int StrLength(HString S) {
|
||||
return S.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* 求子串
|
||||
*
|
||||
* 用Sub返回S[pos, pos+len-1]。
|
||||
* 返回值指示是否截取成功。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status SubString(HString* Sub, HString S, int pos, int len) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos > S.length || len < 0 || pos + len - 1 > S.length) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果是截取0个字符,不需要分配空间
|
||||
if(len == 0) {
|
||||
(*Sub).ch = NULL;
|
||||
(*Sub).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
(*Sub).ch = (char*) malloc(len * sizeof(char));
|
||||
if(!(*Sub).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 复制元素
|
||||
for(i = 0; i < len; i++) {
|
||||
(*Sub).ch[i] = S.ch[i + pos - 1];
|
||||
}
|
||||
|
||||
// 确定新长度
|
||||
(*Sub).length = len;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 查找
|
||||
*
|
||||
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
|
||||
* 如果查找成功,返回匹配的位置。
|
||||
*
|
||||
*【注】
|
||||
* 1.此实现需要依赖串的最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
int Index(HString S, HString T, int pos) {
|
||||
int i, s, t;
|
||||
HString sub;
|
||||
|
||||
if(pos < 1 || pos > S.length || StrEmpty(T)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = S.length;
|
||||
t = T.length;
|
||||
i = pos;
|
||||
|
||||
// 保证长度不越界
|
||||
while(i + t - 1 <= s) {
|
||||
// 获取S[i, i+t-1]
|
||||
SubString(&sub, S, i, t);
|
||||
|
||||
// 如果子串与模式串不匹配,则需要继续推进
|
||||
if(StrCompare(sub, T) != 0) {
|
||||
++i;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ████████ 算法4.4 ████████
|
||||
*
|
||||
* 插入
|
||||
*
|
||||
* 将串T插入到主串S的pos位置处。
|
||||
*/
|
||||
Status StrInsert(HString* S, int pos, HString T) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos > (*S).length + 1) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果待插入的串为空,则提前返回
|
||||
if(StrEmpty(T)) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 分配新空间,会将旧元素一起复制过去
|
||||
(*S).ch = (char*) realloc((*S).ch, ((*S).length + T.length) * sizeof(char));
|
||||
if(!(*S).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 在S中腾出位置,为插入T做准备
|
||||
for(i = (*S).length - 1; i >= pos - 1; i--) {
|
||||
// 从后向前遍历,将前面的元素挪到后面
|
||||
(*S).ch[i + T.length] = (*S).ch[i];
|
||||
}
|
||||
|
||||
// 将串T插入在S中腾出的位置上
|
||||
for(i = pos - 1; i <= pos + T.length - 2; i++) {
|
||||
(*S).ch[i] = T.ch[i - pos + 1];
|
||||
}
|
||||
|
||||
// 长度增加
|
||||
(*S).length += T.length;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 删除
|
||||
*
|
||||
* 删除S[pos, pos+len-1]。
|
||||
*/
|
||||
Status StrDelete(HString* S, int pos, int len) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos + len - 1 > (*S).length || len < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果待删除的长度为0,则提前返回
|
||||
if(len == 0) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 把后面的元素挪到前面,覆盖掉被删除的元素
|
||||
for(i = pos + len - 1; i <= (*S).length - 1; i++) {
|
||||
(*S).ch[i - len] = (*S).ch[i];
|
||||
}
|
||||
|
||||
// 长度减少
|
||||
(*S).length -= len;
|
||||
|
||||
// 缩减分配的空间(如果长度减少为0,这里会返回空指针)
|
||||
(*S).ch = (char*) realloc((*S).ch, (*S).length * sizeof(char));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 比较
|
||||
*
|
||||
* 比较串S和串T,返回比较结果。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrCompare(HString S, HString T) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < S.length && i < T.length; i++) {
|
||||
// 遇到不同的字符时,比较其大小
|
||||
if(S.ch[i] != T.ch[i]) {
|
||||
return S.ch[i] - T.ch[i];
|
||||
}
|
||||
}
|
||||
|
||||
return S.length - T.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* 复制
|
||||
*
|
||||
* 将串S复制到串T。
|
||||
*/
|
||||
Status StrCopy(HString* T, HString S) {
|
||||
int i;
|
||||
|
||||
if(StrEmpty(S)) {
|
||||
(*T).ch = NULL;
|
||||
(*T).length = 0;
|
||||
} else {
|
||||
// 分配空间
|
||||
(*T).ch = (char*) malloc(S.length * sizeof(char));
|
||||
if(!(*T).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 复制元素
|
||||
for(i = 0; i < S.length; i++) {
|
||||
(*T).ch[i] = S.ch[i];
|
||||
}
|
||||
|
||||
// 复制长度信息
|
||||
(*T).length = S.length;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 替换
|
||||
*
|
||||
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
|
||||
*
|
||||
*【注】
|
||||
* 1.该操作依赖最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
Status Replace(HString* S, HString T, HString V) {
|
||||
int i;
|
||||
|
||||
if(StrEmpty(*S) || StrEmpty(T)) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 在主串S中寻找模式串T第一次出现的位置
|
||||
i = Index(*S, T, 1);
|
||||
|
||||
// 如果存在匹配的字符串
|
||||
while(i != 0) {
|
||||
StrDelete(S, i, StrLength(T)); // 从S中删除T
|
||||
StrInsert(S, i, V); // 向S中插入V
|
||||
|
||||
i += StrLength(V); // i切换到下一个位置
|
||||
|
||||
i = Index(*S, T, i); // 查找下一个匹配的字符串
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 串联接
|
||||
*
|
||||
* 联接S1和S2,并存储到T中返回。如果联接后的长度溢出,则只保留未溢出的部分。
|
||||
* 返回值表示联接后的串是否完整。
|
||||
* 堆串的空间被认为是无限的,因此这里总是返回TRUE,指示串不会被裁剪。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status Concat(HString* T, HString S1, HString S2) {
|
||||
int i;
|
||||
|
||||
// 确定新长度
|
||||
(*T).length = S1.length + S2.length;
|
||||
|
||||
// 分配空间
|
||||
(*T).ch = (char*) malloc((*T).length * sizeof(char));
|
||||
if(!(*T).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 先把S1的内容拷贝出来
|
||||
for(i = 0; i < S1.length; i++) {
|
||||
(*T).ch[i] = S1.ch[i];
|
||||
}
|
||||
|
||||
// 再拷贝S2的内容
|
||||
for(i = 0; i < S2.length; i++) {
|
||||
(*T).ch[S1.length + i] = S2.ch[i];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
156
CLion/CourseBook/0402_HString/HString.h
Normal file
156
CLion/CourseBook/0402_HString/HString.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*=========================
|
||||
* 串的堆分配存储表示(堆串)
|
||||
*
|
||||
* 包含算法: 4.4
|
||||
==========================*/
|
||||
|
||||
#ifndef HSTRING
|
||||
#define HSTRING
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
|
||||
#include <string.h> // 提供strlen原型
|
||||
#include "Status.h" //**▲01 绪论**//
|
||||
|
||||
/*
|
||||
* 串的堆存储表示
|
||||
*
|
||||
* 注:有效元素从ch的0号单元开始存储
|
||||
*/
|
||||
typedef struct {
|
||||
char* ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
|
||||
int length;
|
||||
} HString;
|
||||
|
||||
|
||||
/*
|
||||
* ████ 提示 ████
|
||||
*
|
||||
* 遵循教材的书写习惯,pos指示字符的位序(不是索引),从1开始计数
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 初始化
|
||||
*
|
||||
* 构造一个值为chars的串T。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrAssign(HString* T, const char* chars);
|
||||
|
||||
/*
|
||||
* 销毁
|
||||
*
|
||||
* 将串S销毁。
|
||||
*/
|
||||
Status DestroyString(HString* S);
|
||||
|
||||
/*
|
||||
* 清空
|
||||
*
|
||||
* 将串S清空。
|
||||
*/
|
||||
Status ClearString(HString* S);
|
||||
|
||||
/*
|
||||
* 判空
|
||||
*
|
||||
* 判断串S中是否包含有效数据。
|
||||
*
|
||||
* 返回值:
|
||||
* TRUE : 串S为空
|
||||
* FALSE: 串S不为空
|
||||
*/
|
||||
Status StrEmpty(HString S);
|
||||
|
||||
/*
|
||||
* 计数
|
||||
*
|
||||
* 返回串S中元素的个数。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
int StrLength(HString S);
|
||||
|
||||
/*
|
||||
* 求子串
|
||||
*
|
||||
* 用Sub返回S[pos, pos+len-1]。
|
||||
* 返回值指示是否截取成功。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status SubString(HString* Sub, HString S, int pos, int len);
|
||||
|
||||
/*
|
||||
* 查找
|
||||
*
|
||||
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
|
||||
* 如果查找成功,返回匹配的位置。
|
||||
*
|
||||
*【注】
|
||||
* 1.此实现需要依赖串的最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
int Index(HString S, HString T, int pos);
|
||||
|
||||
/*
|
||||
* ████████ 算法4.4 ████████
|
||||
*
|
||||
* 插入
|
||||
*
|
||||
* 将串T插入到主串S的pos位置处。
|
||||
*/
|
||||
Status StrInsert(HString* S, int pos, HString T);
|
||||
|
||||
/*
|
||||
* 删除
|
||||
*
|
||||
* 删除S[pos, pos+len-1]。
|
||||
*/
|
||||
Status StrDelete(HString* S, int pos, int len);
|
||||
|
||||
/*
|
||||
* 比较
|
||||
*
|
||||
* 比较串S和串T,返回比较结果。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrCompare(HString S, HString T);
|
||||
|
||||
/*
|
||||
* 复制
|
||||
*
|
||||
* 将串S复制到串T。
|
||||
*/
|
||||
Status StrCopy(HString* T, HString S);
|
||||
|
||||
/*
|
||||
* 替换
|
||||
*
|
||||
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
|
||||
*
|
||||
*【注】
|
||||
* 1.该操作依赖最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
Status Replace(HString* S, HString T, HString V);
|
||||
|
||||
/*
|
||||
* 串联接
|
||||
*
|
||||
* 联接S1和S2,并存储到T中返回。如果联接后的长度溢出,则只保留未溢出的部分。
|
||||
* 返回值表示联接后的串是否完整。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status Concat(HString* T, HString S1, HString S2);
|
||||
|
||||
#endif
|
||||
7
CLion/CourseBook/0403_LString/CMakeLists.txt
Normal file
7
CLion/CourseBook/0403_LString/CMakeLists.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
# 包含公共库
|
||||
include_directories(${CMAKE_SOURCE_DIR}/Status)
|
||||
|
||||
# 生成可执行文件
|
||||
add_executable(LString LString.h LString.c LString-main.c)
|
||||
# 链接公共库
|
||||
target_link_libraries(LString Scanf_lib)
|
||||
152
CLion/CourseBook/0403_LString/LString-main.c
Normal file
152
CLion/CourseBook/0403_LString/LString-main.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include "LString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(LString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
LString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为块链串 S 赋值...\n");
|
||||
StrAssign(&S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(&T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(&S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(&sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
StrAssign(&V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(&S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(&S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(&S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
LString Tmp, S1, S2;
|
||||
|
||||
StrAssign(&S1, "+++++");
|
||||
StrAssign(&S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(&Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(LString S) {
|
||||
int i = 0;
|
||||
Chunk* p = S.head;
|
||||
|
||||
if(S.curlen == 0 || S.head == NULL || S.tail == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while(p != NULL) {
|
||||
// 遇到非串值符号时结束遍历
|
||||
if(p->ch[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%c", p->ch[i]);
|
||||
|
||||
i = (i + 1) % CHUNKSIZE;
|
||||
|
||||
if(i == 0) {
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
719
CLion/CourseBook/0403_LString/LString.c
Normal file
719
CLion/CourseBook/0403_LString/LString.c
Normal file
File diff suppressed because it is too large
Load Diff
166
CLion/CourseBook/0403_LString/LString.h
Normal file
166
CLion/CourseBook/0403_LString/LString.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*=============================
|
||||
* 串的块链分配存储表示(块链串)
|
||||
==============================*/
|
||||
|
||||
#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);
|
||||
|
||||
#endif
|
||||
@@ -19,3 +19,7 @@ add_subdirectory(0306_Hanoi)
|
||||
add_subdirectory(0307_LinkQueue)
|
||||
add_subdirectory(0308_SqQueue)
|
||||
add_subdirectory(0309_BankQueuing)
|
||||
|
||||
add_subdirectory(0401_SString)
|
||||
add_subdirectory(0402_HString)
|
||||
add_subdirectory(0403_LString)
|
||||
|
||||
137
Dev-C++/CourseBook/0401_SString/SString-main.cpp
Normal file
137
Dev-C++/CourseBook/0401_SString/SString-main.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include "SString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(SString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
SString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为顺序串 S 赋值...\n");
|
||||
StrAssign(S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index_1(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
StrAssign(V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
SString Tmp, S1, S2;
|
||||
|
||||
StrAssign(S1, "+++++");
|
||||
StrAssign(S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(SString S) {
|
||||
int i;
|
||||
|
||||
for(i = 1; i <= S[0]; i++) {
|
||||
printf("%c", S[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
395
Dev-C++/CourseBook/0401_SString/SString.cpp
Normal file
395
Dev-C++/CourseBook/0401_SString/SString.cpp
Normal file
@@ -0,0 +1,395 @@
|
||||
/*=============================
|
||||
* 串的定长顺序存储表示(顺序串)
|
||||
*
|
||||
* 包含算法: 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;
|
||||
}
|
||||
82
Dev-C++/CourseBook/0401_SString/SString.dev
Normal file
82
Dev-C++/CourseBook/0401_SString/SString.dev
Normal file
@@ -0,0 +1,82 @@
|
||||
[Project]
|
||||
FileName=SString.dev
|
||||
Name=SString
|
||||
Type=1
|
||||
Ver=2
|
||||
ObjFiles=
|
||||
Includes=
|
||||
Libs=
|
||||
PrivateResource=
|
||||
ResourceIncludes=
|
||||
MakeIncludes=
|
||||
Compiler=
|
||||
CppCompiler=
|
||||
Linker=
|
||||
IsCpp=0
|
||||
Icon=
|
||||
ExeOutput=
|
||||
ObjectOutput=
|
||||
LogOutput=
|
||||
LogOutputEnabled=0
|
||||
OverrideOutput=0
|
||||
OverrideOutputName=
|
||||
HostApplication=
|
||||
UseCustomMakefile=0
|
||||
CustomMakefile=
|
||||
CommandLine=
|
||||
Folders=
|
||||
IncludeVersionInfo=0
|
||||
SupportXPThemes=0
|
||||
CompilerSet=1
|
||||
CompilerSettings=0000000000000000001000000
|
||||
UnitCount=3
|
||||
|
||||
[VersionInfo]
|
||||
Major=1
|
||||
Minor=0
|
||||
Release=0
|
||||
Build=0
|
||||
LanguageID=1033
|
||||
CharsetID=1252
|
||||
CompanyName=
|
||||
FileVersion=
|
||||
FileDescription=Developed using the Dev-C++ IDE
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=
|
||||
AutoIncBuildNr=0
|
||||
SyncProduct=1
|
||||
|
||||
[Unit3]
|
||||
FileName=SString-main.cpp
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit1]
|
||||
FileName=SString.cpp
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit2]
|
||||
FileName=SString.h
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
176
Dev-C++/CourseBook/0401_SString/SString.h
Normal file
176
Dev-C++/CourseBook/0401_SString/SString.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*=============================
|
||||
* 串的定长顺序存储表示(顺序串)
|
||||
*
|
||||
* 包含算法: 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);
|
||||
|
||||
#endif
|
||||
137
Dev-C++/CourseBook/0402_HString/HString-main.cpp
Normal file
137
Dev-C++/CourseBook/0402_HString/HString-main.cpp
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include "HString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(HString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
HString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为堆串 S 赋值...\n");
|
||||
StrAssign(&S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(&T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(&S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(&sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
StrAssign(&V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(&S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(&S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(&S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
HString Tmp, S1, S2;
|
||||
|
||||
StrAssign(&S1, "+++++");
|
||||
StrAssign(&S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(&Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(HString S) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i <= S.length-1; i++) {
|
||||
printf("%c", S.ch[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
367
Dev-C++/CourseBook/0402_HString/HString.cpp
Normal file
367
Dev-C++/CourseBook/0402_HString/HString.cpp
Normal file
@@ -0,0 +1,367 @@
|
||||
/*=========================
|
||||
* 串的堆分配存储表示(堆串)
|
||||
*
|
||||
* 包含算法: 4.4
|
||||
==========================*/
|
||||
|
||||
#include "HString.h" //**▲04 串**//
|
||||
|
||||
/*
|
||||
* 初始化
|
||||
*
|
||||
* 构造一个值为chars的串T。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrAssign(HString* T, const char* chars) {
|
||||
int i, j;
|
||||
|
||||
// 求chars的长度
|
||||
i = (int) strlen(chars);
|
||||
|
||||
// 没有有效元素
|
||||
if(i == 0) {
|
||||
(*T).ch = NULL;
|
||||
(*T).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 存在有效元素时,需要分配存储空间
|
||||
(*T).ch = (char*) malloc(i * sizeof(char));
|
||||
if(!((*T).ch)) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
for(j = 0; j < i; j++) {
|
||||
(*T).ch[j] = chars[j];
|
||||
}
|
||||
|
||||
(*T).length = i;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 销毁
|
||||
*
|
||||
* 将串S销毁。
|
||||
*
|
||||
*【注】
|
||||
* 堆串的结构可以销毁,但不是在销毁操作中
|
||||
*/
|
||||
Status DestroyString(HString* S) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 清空
|
||||
*
|
||||
* 将串S清空。
|
||||
*/
|
||||
Status ClearString(HString* S) {
|
||||
// 没有有效元素时,销毁堆串结构
|
||||
if((*S).ch != 0) {
|
||||
free((*S).ch);
|
||||
(*S).ch = NULL;
|
||||
}
|
||||
|
||||
(*S).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 判空
|
||||
*
|
||||
* 判断串S中是否包含有效数据。
|
||||
*
|
||||
* 返回值:
|
||||
* TRUE : 串S为空
|
||||
* FALSE: 串S不为空
|
||||
*/
|
||||
Status StrEmpty(HString S) {
|
||||
return S.length == 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 计数
|
||||
*
|
||||
* 返回串S中元素的个数。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
int StrLength(HString S) {
|
||||
return S.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* 求子串
|
||||
*
|
||||
* 用Sub返回S[pos, pos+len-1]。
|
||||
* 返回值指示是否截取成功。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status SubString(HString* Sub, HString S, int pos, int len) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos > S.length || len < 0 || pos + len - 1 > S.length) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果是截取0个字符,不需要分配空间
|
||||
if(len == 0) {
|
||||
(*Sub).ch = NULL;
|
||||
(*Sub).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
(*Sub).ch = (char*) malloc(len * sizeof(char));
|
||||
if(!(*Sub).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 复制元素
|
||||
for(i = 0; i < len; i++) {
|
||||
(*Sub).ch[i] = S.ch[i + pos - 1];
|
||||
}
|
||||
|
||||
// 确定新长度
|
||||
(*Sub).length = len;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 查找
|
||||
*
|
||||
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
|
||||
* 如果查找成功,返回匹配的位置。
|
||||
*
|
||||
*【注】
|
||||
* 1.此实现需要依赖串的最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
int Index(HString S, HString T, int pos) {
|
||||
int i, s, t;
|
||||
HString sub;
|
||||
|
||||
if(pos < 1 || pos > S.length || StrEmpty(T)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = S.length;
|
||||
t = T.length;
|
||||
i = pos;
|
||||
|
||||
// 保证长度不越界
|
||||
while(i + t - 1 <= s) {
|
||||
// 获取S[i, i+t-1]
|
||||
SubString(&sub, S, i, t);
|
||||
|
||||
// 如果子串与模式串不匹配,则需要继续推进
|
||||
if(StrCompare(sub, T) != 0) {
|
||||
++i;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ████████ 算法4.4 ████████
|
||||
*
|
||||
* 插入
|
||||
*
|
||||
* 将串T插入到主串S的pos位置处。
|
||||
*/
|
||||
Status StrInsert(HString* S, int pos, HString T) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos > (*S).length + 1) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果待插入的串为空,则提前返回
|
||||
if(StrEmpty(T)) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 分配新空间,会将旧元素一起复制过去
|
||||
(*S).ch = (char*) realloc((*S).ch, ((*S).length + T.length) * sizeof(char));
|
||||
if(!(*S).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 在S中腾出位置,为插入T做准备
|
||||
for(i = (*S).length - 1; i >= pos - 1; i--) {
|
||||
// 从后向前遍历,将前面的元素挪到后面
|
||||
(*S).ch[i + T.length] = (*S).ch[i];
|
||||
}
|
||||
|
||||
// 将串T插入在S中腾出的位置上
|
||||
for(i = pos - 1; i <= pos + T.length - 2; i++) {
|
||||
(*S).ch[i] = T.ch[i - pos + 1];
|
||||
}
|
||||
|
||||
// 长度增加
|
||||
(*S).length += T.length;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 删除
|
||||
*
|
||||
* 删除S[pos, pos+len-1]。
|
||||
*/
|
||||
Status StrDelete(HString* S, int pos, int len) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos + len - 1 > (*S).length || len < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果待删除的长度为0,则提前返回
|
||||
if(len == 0) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 把后面的元素挪到前面,覆盖掉被删除的元素
|
||||
for(i = pos + len - 1; i <= (*S).length - 1; i++) {
|
||||
(*S).ch[i - len] = (*S).ch[i];
|
||||
}
|
||||
|
||||
// 长度减少
|
||||
(*S).length -= len;
|
||||
|
||||
// 缩减分配的空间(如果长度减少为0,这里会返回空指针)
|
||||
(*S).ch = (char*) realloc((*S).ch, (*S).length * sizeof(char));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 比较
|
||||
*
|
||||
* 比较串S和串T,返回比较结果。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrCompare(HString S, HString T) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < S.length && i < T.length; i++) {
|
||||
// 遇到不同的字符时,比较其大小
|
||||
if(S.ch[i] != T.ch[i]) {
|
||||
return S.ch[i] - T.ch[i];
|
||||
}
|
||||
}
|
||||
|
||||
return S.length - T.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* 复制
|
||||
*
|
||||
* 将串S复制到串T。
|
||||
*/
|
||||
Status StrCopy(HString* T, HString S) {
|
||||
int i;
|
||||
|
||||
if(StrEmpty(S)) {
|
||||
(*T).ch = NULL;
|
||||
(*T).length = 0;
|
||||
} else {
|
||||
// 分配空间
|
||||
(*T).ch = (char*) malloc(S.length * sizeof(char));
|
||||
if(!(*T).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 复制元素
|
||||
for(i = 0; i < S.length; i++) {
|
||||
(*T).ch[i] = S.ch[i];
|
||||
}
|
||||
|
||||
// 复制长度信息
|
||||
(*T).length = S.length;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 替换
|
||||
*
|
||||
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
|
||||
*
|
||||
*【注】
|
||||
* 1.该操作依赖最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
Status Replace(HString* S, HString T, HString V) {
|
||||
int i;
|
||||
|
||||
if(StrEmpty(*S) || StrEmpty(T)) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 在主串S中寻找模式串T第一次出现的位置
|
||||
i = Index(*S, T, 1);
|
||||
|
||||
// 如果存在匹配的字符串
|
||||
while(i != 0) {
|
||||
StrDelete(S, i, StrLength(T)); // 从S中删除T
|
||||
StrInsert(S, i, V); // 向S中插入V
|
||||
|
||||
i += StrLength(V); // i切换到下一个位置
|
||||
|
||||
i = Index(*S, T, i); // 查找下一个匹配的字符串
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 串联接
|
||||
*
|
||||
* 联接S1和S2,并存储到T中返回。如果联接后的长度溢出,则只保留未溢出的部分。
|
||||
* 返回值表示联接后的串是否完整。
|
||||
* 堆串的空间被认为是无限的,因此这里总是返回TRUE,指示串不会被裁剪。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status Concat(HString* T, HString S1, HString S2) {
|
||||
int i;
|
||||
|
||||
// 确定新长度
|
||||
(*T).length = S1.length + S2.length;
|
||||
|
||||
// 分配空间
|
||||
(*T).ch = (char*) malloc((*T).length * sizeof(char));
|
||||
if(!(*T).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 先把S1的内容拷贝出来
|
||||
for(i = 0; i < S1.length; i++) {
|
||||
(*T).ch[i] = S1.ch[i];
|
||||
}
|
||||
|
||||
// 再拷贝S2的内容
|
||||
for(i = 0; i < S2.length; i++) {
|
||||
(*T).ch[S1.length + i] = S2.ch[i];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
82
Dev-C++/CourseBook/0402_HString/HString.dev
Normal file
82
Dev-C++/CourseBook/0402_HString/HString.dev
Normal file
@@ -0,0 +1,82 @@
|
||||
[Project]
|
||||
FileName=HString.dev
|
||||
Name=HString
|
||||
Type=1
|
||||
Ver=2
|
||||
ObjFiles=
|
||||
Includes=
|
||||
Libs=
|
||||
PrivateResource=
|
||||
ResourceIncludes=
|
||||
MakeIncludes=
|
||||
Compiler=
|
||||
CppCompiler=
|
||||
Linker=
|
||||
IsCpp=0
|
||||
Icon=
|
||||
ExeOutput=
|
||||
ObjectOutput=
|
||||
LogOutput=
|
||||
LogOutputEnabled=0
|
||||
OverrideOutput=0
|
||||
OverrideOutputName=
|
||||
HostApplication=
|
||||
UseCustomMakefile=0
|
||||
CustomMakefile=
|
||||
CommandLine=
|
||||
Folders=
|
||||
IncludeVersionInfo=0
|
||||
SupportXPThemes=0
|
||||
CompilerSet=1
|
||||
CompilerSettings=0000000000000000001000000
|
||||
UnitCount=3
|
||||
|
||||
[VersionInfo]
|
||||
Major=1
|
||||
Minor=0
|
||||
Release=0
|
||||
Build=0
|
||||
LanguageID=1033
|
||||
CharsetID=1252
|
||||
CompanyName=
|
||||
FileVersion=
|
||||
FileDescription=Developed using the Dev-C++ IDE
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=
|
||||
AutoIncBuildNr=0
|
||||
SyncProduct=1
|
||||
|
||||
[Unit3]
|
||||
FileName=HString-main.cpp
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit1]
|
||||
FileName=HString.cpp
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit2]
|
||||
FileName=HString.h
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
156
Dev-C++/CourseBook/0402_HString/HString.h
Normal file
156
Dev-C++/CourseBook/0402_HString/HString.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*=========================
|
||||
* 串的堆分配存储表示(堆串)
|
||||
*
|
||||
* 包含算法: 4.4
|
||||
==========================*/
|
||||
|
||||
#ifndef HSTRING
|
||||
#define HSTRING
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
|
||||
#include <string.h> // 提供strlen原型
|
||||
#include "Status.h" //**▲01 绪论**//
|
||||
|
||||
/*
|
||||
* 串的堆存储表示
|
||||
*
|
||||
* 注:有效元素从ch的0号单元开始存储
|
||||
*/
|
||||
typedef struct {
|
||||
char* ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
|
||||
int length;
|
||||
} HString;
|
||||
|
||||
|
||||
/*
|
||||
* ████ 提示 ████
|
||||
*
|
||||
* 遵循教材的书写习惯,pos指示字符的位序(不是索引),从1开始计数
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 初始化
|
||||
*
|
||||
* 构造一个值为chars的串T。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrAssign(HString* T, const char* chars);
|
||||
|
||||
/*
|
||||
* 销毁
|
||||
*
|
||||
* 将串S销毁。
|
||||
*/
|
||||
Status DestroyString(HString* S);
|
||||
|
||||
/*
|
||||
* 清空
|
||||
*
|
||||
* 将串S清空。
|
||||
*/
|
||||
Status ClearString(HString* S);
|
||||
|
||||
/*
|
||||
* 判空
|
||||
*
|
||||
* 判断串S中是否包含有效数据。
|
||||
*
|
||||
* 返回值:
|
||||
* TRUE : 串S为空
|
||||
* FALSE: 串S不为空
|
||||
*/
|
||||
Status StrEmpty(HString S);
|
||||
|
||||
/*
|
||||
* 计数
|
||||
*
|
||||
* 返回串S中元素的个数。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
int StrLength(HString S);
|
||||
|
||||
/*
|
||||
* 求子串
|
||||
*
|
||||
* 用Sub返回S[pos, pos+len-1]。
|
||||
* 返回值指示是否截取成功。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status SubString(HString* Sub, HString S, int pos, int len);
|
||||
|
||||
/*
|
||||
* 查找
|
||||
*
|
||||
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
|
||||
* 如果查找成功,返回匹配的位置。
|
||||
*
|
||||
*【注】
|
||||
* 1.此实现需要依赖串的最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
int Index(HString S, HString T, int pos);
|
||||
|
||||
/*
|
||||
* ████████ 算法4.4 ████████
|
||||
*
|
||||
* 插入
|
||||
*
|
||||
* 将串T插入到主串S的pos位置处。
|
||||
*/
|
||||
Status StrInsert(HString* S, int pos, HString T);
|
||||
|
||||
/*
|
||||
* 删除
|
||||
*
|
||||
* 删除S[pos, pos+len-1]。
|
||||
*/
|
||||
Status StrDelete(HString* S, int pos, int len);
|
||||
|
||||
/*
|
||||
* 比较
|
||||
*
|
||||
* 比较串S和串T,返回比较结果。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrCompare(HString S, HString T);
|
||||
|
||||
/*
|
||||
* 复制
|
||||
*
|
||||
* 将串S复制到串T。
|
||||
*/
|
||||
Status StrCopy(HString* T, HString S);
|
||||
|
||||
/*
|
||||
* 替换
|
||||
*
|
||||
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
|
||||
*
|
||||
*【注】
|
||||
* 1.该操作依赖最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
Status Replace(HString* S, HString T, HString V);
|
||||
|
||||
/*
|
||||
* 串联接
|
||||
*
|
||||
* 联接S1和S2,并存储到T中返回。如果联接后的长度溢出,则只保留未溢出的部分。
|
||||
* 返回值表示联接后的串是否完整。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status Concat(HString* T, HString S1, HString S2);
|
||||
|
||||
#endif
|
||||
152
Dev-C++/CourseBook/0403_LString/LString-main.cpp
Normal file
152
Dev-C++/CourseBook/0403_LString/LString-main.cpp
Normal file
@@ -0,0 +1,152 @@
|
||||
#include "LString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(LString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
LString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为块链串 S 赋值...\n");
|
||||
StrAssign(&S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(&T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(&S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(&sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
StrAssign(&V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(&S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(&S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(&S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
LString Tmp, S1, S2;
|
||||
|
||||
StrAssign(&S1, "+++++");
|
||||
StrAssign(&S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(&Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(LString S) {
|
||||
int i = 0;
|
||||
Chunk* p = S.head;
|
||||
|
||||
if(S.curlen == 0 || S.head == NULL || S.tail == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while(p != NULL) {
|
||||
// 遇到非串值符号时结束遍历
|
||||
if(p->ch[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%c", p->ch[i]);
|
||||
|
||||
i = (i + 1) % CHUNKSIZE;
|
||||
|
||||
if(i == 0) {
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
719
Dev-C++/CourseBook/0403_LString/LString.cpp
Normal file
719
Dev-C++/CourseBook/0403_LString/LString.cpp
Normal file
File diff suppressed because it is too large
Load Diff
82
Dev-C++/CourseBook/0403_LString/LString.dev
Normal file
82
Dev-C++/CourseBook/0403_LString/LString.dev
Normal file
@@ -0,0 +1,82 @@
|
||||
[Project]
|
||||
FileName=LString.dev
|
||||
Name=LString
|
||||
Type=1
|
||||
Ver=2
|
||||
ObjFiles=
|
||||
Includes=
|
||||
Libs=
|
||||
PrivateResource=
|
||||
ResourceIncludes=
|
||||
MakeIncludes=
|
||||
Compiler=
|
||||
CppCompiler=
|
||||
Linker=
|
||||
IsCpp=0
|
||||
Icon=
|
||||
ExeOutput=
|
||||
ObjectOutput=
|
||||
LogOutput=
|
||||
LogOutputEnabled=0
|
||||
OverrideOutput=0
|
||||
OverrideOutputName=
|
||||
HostApplication=
|
||||
UseCustomMakefile=0
|
||||
CustomMakefile=
|
||||
CommandLine=
|
||||
Folders=
|
||||
IncludeVersionInfo=0
|
||||
SupportXPThemes=0
|
||||
CompilerSet=1
|
||||
CompilerSettings=0000000000000000001000000
|
||||
UnitCount=3
|
||||
|
||||
[VersionInfo]
|
||||
Major=1
|
||||
Minor=0
|
||||
Release=0
|
||||
Build=0
|
||||
LanguageID=1033
|
||||
CharsetID=1252
|
||||
CompanyName=
|
||||
FileVersion=
|
||||
FileDescription=Developed using the Dev-C++ IDE
|
||||
InternalName=
|
||||
LegalCopyright=
|
||||
LegalTrademarks=
|
||||
OriginalFilename=
|
||||
ProductName=
|
||||
ProductVersion=
|
||||
AutoIncBuildNr=0
|
||||
SyncProduct=1
|
||||
|
||||
[Unit3]
|
||||
FileName=LString-main.cpp
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit1]
|
||||
FileName=LString.cpp
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
[Unit2]
|
||||
FileName=LString.h
|
||||
CompileCpp=0
|
||||
Folder=
|
||||
Compile=1
|
||||
Link=1
|
||||
Priority=1000
|
||||
OverrideBuildCmd=0
|
||||
BuildCmd=
|
||||
|
||||
166
Dev-C++/CourseBook/0403_LString/LString.h
Normal file
166
Dev-C++/CourseBook/0403_LString/LString.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*=============================
|
||||
* 串的块链分配存储表示(块链串)
|
||||
==============================*/
|
||||
|
||||
#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);
|
||||
|
||||
#endif
|
||||
@@ -114,3 +114,6 @@ Commit信息中的`emoji`参考来源:
|
||||
| | LinkQueue | 链列 | | 链式存储结构 |
|
||||
| | SqQueue | 顺序队列 | | 循环队列,顺序存储结构 |
|
||||
| | BankQueuing | 模拟银行排队 | 3.6、3.7 | 队列的应用 |
|
||||
| 04 串 | SString | 顺序串 | 4.1、4.2、4.3、4.5 | 顺序存储 |
|
||||
| | HString | 堆串 | 4.4 | 顺序存储,动态分配内存 |
|
||||
| | LString | 块链串 | | 顺序存储+链式存储 |
|
||||
|
||||
76
VisualC++/CourseBook/0401_SString/0401_SString.vcxproj
Normal file
76
VisualC++/CourseBook/0401_SString/0401_SString.vcxproj
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{7D94FA2D-43E5-4EA0-AEBF-119C156C98FF}</ProjectGuid>
|
||||
<RootNamespace>My0401_SString</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Status;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(SolutionDir)\..\Status\Status.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SString.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SString-main.c" />
|
||||
<ClCompile Include="SString.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="SString.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="SString.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SString-main.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
</Project>
|
||||
137
VisualC++/CourseBook/0401_SString/SString-main.c
Normal file
137
VisualC++/CourseBook/0401_SString/SString-main.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include "SString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(SString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
SString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为顺序串 S 赋值...\n");
|
||||
StrAssign(S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index_1(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(T, "*****");
|
||||
StrAssign(V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
SString Tmp, S1, S2;
|
||||
|
||||
StrAssign(S1, "+++++");
|
||||
StrAssign(S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(SString S) {
|
||||
int i;
|
||||
|
||||
for(i = 1; i <= S[0]; i++) {
|
||||
printf("%c", S[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
395
VisualC++/CourseBook/0401_SString/SString.c
Normal file
395
VisualC++/CourseBook/0401_SString/SString.c
Normal file
@@ -0,0 +1,395 @@
|
||||
/*=============================
|
||||
* 串的定长顺序存储表示(顺序串)
|
||||
*
|
||||
* 包含算法: 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;
|
||||
}
|
||||
176
VisualC++/CourseBook/0401_SString/SString.h
Normal file
176
VisualC++/CourseBook/0401_SString/SString.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*=============================
|
||||
* 串的定长顺序存储表示(顺序串)
|
||||
*
|
||||
* 包含算法: 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);
|
||||
|
||||
#endif
|
||||
76
VisualC++/CourseBook/0402_HString/0402_HString.vcxproj
Normal file
76
VisualC++/CourseBook/0402_HString/0402_HString.vcxproj
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{A1D8A416-186E-4691-B8E7-ED7DE605AA4C}</ProjectGuid>
|
||||
<RootNamespace>My0402_HString</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Status;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(SolutionDir)\..\Status\Status.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="HString-main.c" />
|
||||
<ClCompile Include="HString.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="HString.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="HString.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="HString-main.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="HString.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
</Project>
|
||||
137
VisualC++/CourseBook/0402_HString/HString-main.c
Normal file
137
VisualC++/CourseBook/0402_HString/HString-main.c
Normal file
@@ -0,0 +1,137 @@
|
||||
#include <stdio.h>
|
||||
#include "HString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(HString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
HString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为堆串 S 赋值...\n");
|
||||
StrAssign(&S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(&T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(&S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(&sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
StrAssign(&V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(&S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(&S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(&S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
HString Tmp, S1, S2;
|
||||
|
||||
StrAssign(&S1, "+++++");
|
||||
StrAssign(&S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(&Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(HString S) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i <= S.length-1; i++) {
|
||||
printf("%c", S.ch[i]);
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
367
VisualC++/CourseBook/0402_HString/HString.c
Normal file
367
VisualC++/CourseBook/0402_HString/HString.c
Normal file
@@ -0,0 +1,367 @@
|
||||
/*=========================
|
||||
* 串的堆分配存储表示(堆串)
|
||||
*
|
||||
* 包含算法: 4.4
|
||||
==========================*/
|
||||
|
||||
#include "HString.h" //**▲04 串**//
|
||||
|
||||
/*
|
||||
* 初始化
|
||||
*
|
||||
* 构造一个值为chars的串T。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrAssign(HString* T, const char* chars) {
|
||||
int i, j;
|
||||
|
||||
// 求chars的长度
|
||||
i = (int) strlen(chars);
|
||||
|
||||
// 没有有效元素
|
||||
if(i == 0) {
|
||||
(*T).ch = NULL;
|
||||
(*T).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 存在有效元素时,需要分配存储空间
|
||||
(*T).ch = (char*) malloc(i * sizeof(char));
|
||||
if(!((*T).ch)) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
for(j = 0; j < i; j++) {
|
||||
(*T).ch[j] = chars[j];
|
||||
}
|
||||
|
||||
(*T).length = i;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 销毁
|
||||
*
|
||||
* 将串S销毁。
|
||||
*
|
||||
*【注】
|
||||
* 堆串的结构可以销毁,但不是在销毁操作中
|
||||
*/
|
||||
Status DestroyString(HString* S) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 清空
|
||||
*
|
||||
* 将串S清空。
|
||||
*/
|
||||
Status ClearString(HString* S) {
|
||||
// 没有有效元素时,销毁堆串结构
|
||||
if((*S).ch != 0) {
|
||||
free((*S).ch);
|
||||
(*S).ch = NULL;
|
||||
}
|
||||
|
||||
(*S).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 判空
|
||||
*
|
||||
* 判断串S中是否包含有效数据。
|
||||
*
|
||||
* 返回值:
|
||||
* TRUE : 串S为空
|
||||
* FALSE: 串S不为空
|
||||
*/
|
||||
Status StrEmpty(HString S) {
|
||||
return S.length == 0 ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* 计数
|
||||
*
|
||||
* 返回串S中元素的个数。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
int StrLength(HString S) {
|
||||
return S.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* 求子串
|
||||
*
|
||||
* 用Sub返回S[pos, pos+len-1]。
|
||||
* 返回值指示是否截取成功。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status SubString(HString* Sub, HString S, int pos, int len) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos > S.length || len < 0 || pos + len - 1 > S.length) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果是截取0个字符,不需要分配空间
|
||||
if(len == 0) {
|
||||
(*Sub).ch = NULL;
|
||||
(*Sub).length = 0;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
(*Sub).ch = (char*) malloc(len * sizeof(char));
|
||||
if(!(*Sub).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 复制元素
|
||||
for(i = 0; i < len; i++) {
|
||||
(*Sub).ch[i] = S.ch[i + pos - 1];
|
||||
}
|
||||
|
||||
// 确定新长度
|
||||
(*Sub).length = len;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 查找
|
||||
*
|
||||
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
|
||||
* 如果查找成功,返回匹配的位置。
|
||||
*
|
||||
*【注】
|
||||
* 1.此实现需要依赖串的最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
int Index(HString S, HString T, int pos) {
|
||||
int i, s, t;
|
||||
HString sub;
|
||||
|
||||
if(pos < 1 || pos > S.length || StrEmpty(T)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
s = S.length;
|
||||
t = T.length;
|
||||
i = pos;
|
||||
|
||||
// 保证长度不越界
|
||||
while(i + t - 1 <= s) {
|
||||
// 获取S[i, i+t-1]
|
||||
SubString(&sub, S, i, t);
|
||||
|
||||
// 如果子串与模式串不匹配,则需要继续推进
|
||||
if(StrCompare(sub, T) != 0) {
|
||||
++i;
|
||||
} else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* ████████ 算法4.4 ████████
|
||||
*
|
||||
* 插入
|
||||
*
|
||||
* 将串T插入到主串S的pos位置处。
|
||||
*/
|
||||
Status StrInsert(HString* S, int pos, HString T) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos > (*S).length + 1) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果待插入的串为空,则提前返回
|
||||
if(StrEmpty(T)) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 分配新空间,会将旧元素一起复制过去
|
||||
(*S).ch = (char*) realloc((*S).ch, ((*S).length + T.length) * sizeof(char));
|
||||
if(!(*S).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 在S中腾出位置,为插入T做准备
|
||||
for(i = (*S).length - 1; i >= pos - 1; i--) {
|
||||
// 从后向前遍历,将前面的元素挪到后面
|
||||
(*S).ch[i + T.length] = (*S).ch[i];
|
||||
}
|
||||
|
||||
// 将串T插入在S中腾出的位置上
|
||||
for(i = pos - 1; i <= pos + T.length - 2; i++) {
|
||||
(*S).ch[i] = T.ch[i - pos + 1];
|
||||
}
|
||||
|
||||
// 长度增加
|
||||
(*S).length += T.length;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 删除
|
||||
*
|
||||
* 删除S[pos, pos+len-1]。
|
||||
*/
|
||||
Status StrDelete(HString* S, int pos, int len) {
|
||||
int i;
|
||||
|
||||
if(pos < 1 || pos + len - 1 > (*S).length || len < 0) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 如果待删除的长度为0,则提前返回
|
||||
if(len == 0) {
|
||||
return OK;
|
||||
}
|
||||
|
||||
// 把后面的元素挪到前面,覆盖掉被删除的元素
|
||||
for(i = pos + len - 1; i <= (*S).length - 1; i++) {
|
||||
(*S).ch[i - len] = (*S).ch[i];
|
||||
}
|
||||
|
||||
// 长度减少
|
||||
(*S).length -= len;
|
||||
|
||||
// 缩减分配的空间(如果长度减少为0,这里会返回空指针)
|
||||
(*S).ch = (char*) realloc((*S).ch, (*S).length * sizeof(char));
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 比较
|
||||
*
|
||||
* 比较串S和串T,返回比较结果。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrCompare(HString S, HString T) {
|
||||
int i;
|
||||
|
||||
for(i = 0; i < S.length && i < T.length; i++) {
|
||||
// 遇到不同的字符时,比较其大小
|
||||
if(S.ch[i] != T.ch[i]) {
|
||||
return S.ch[i] - T.ch[i];
|
||||
}
|
||||
}
|
||||
|
||||
return S.length - T.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* 复制
|
||||
*
|
||||
* 将串S复制到串T。
|
||||
*/
|
||||
Status StrCopy(HString* T, HString S) {
|
||||
int i;
|
||||
|
||||
if(StrEmpty(S)) {
|
||||
(*T).ch = NULL;
|
||||
(*T).length = 0;
|
||||
} else {
|
||||
// 分配空间
|
||||
(*T).ch = (char*) malloc(S.length * sizeof(char));
|
||||
if(!(*T).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 复制元素
|
||||
for(i = 0; i < S.length; i++) {
|
||||
(*T).ch[i] = S.ch[i];
|
||||
}
|
||||
|
||||
// 复制长度信息
|
||||
(*T).length = S.length;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 替换
|
||||
*
|
||||
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
|
||||
*
|
||||
*【注】
|
||||
* 1.该操作依赖最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
Status Replace(HString* S, HString T, HString V) {
|
||||
int i;
|
||||
|
||||
if(StrEmpty(*S) || StrEmpty(T)) {
|
||||
return ERROR;
|
||||
}
|
||||
|
||||
// 在主串S中寻找模式串T第一次出现的位置
|
||||
i = Index(*S, T, 1);
|
||||
|
||||
// 如果存在匹配的字符串
|
||||
while(i != 0) {
|
||||
StrDelete(S, i, StrLength(T)); // 从S中删除T
|
||||
StrInsert(S, i, V); // 向S中插入V
|
||||
|
||||
i += StrLength(V); // i切换到下一个位置
|
||||
|
||||
i = Index(*S, T, i); // 查找下一个匹配的字符串
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* 串联接
|
||||
*
|
||||
* 联接S1和S2,并存储到T中返回。如果联接后的长度溢出,则只保留未溢出的部分。
|
||||
* 返回值表示联接后的串是否完整。
|
||||
* 堆串的空间被认为是无限的,因此这里总是返回TRUE,指示串不会被裁剪。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status Concat(HString* T, HString S1, HString S2) {
|
||||
int i;
|
||||
|
||||
// 确定新长度
|
||||
(*T).length = S1.length + S2.length;
|
||||
|
||||
// 分配空间
|
||||
(*T).ch = (char*) malloc((*T).length * sizeof(char));
|
||||
if(!(*T).ch) {
|
||||
exit(OVERFLOW);
|
||||
}
|
||||
|
||||
// 先把S1的内容拷贝出来
|
||||
for(i = 0; i < S1.length; i++) {
|
||||
(*T).ch[i] = S1.ch[i];
|
||||
}
|
||||
|
||||
// 再拷贝S2的内容
|
||||
for(i = 0; i < S2.length; i++) {
|
||||
(*T).ch[S1.length + i] = S2.ch[i];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
156
VisualC++/CourseBook/0402_HString/HString.h
Normal file
156
VisualC++/CourseBook/0402_HString/HString.h
Normal file
@@ -0,0 +1,156 @@
|
||||
/*=========================
|
||||
* 串的堆分配存储表示(堆串)
|
||||
*
|
||||
* 包含算法: 4.4
|
||||
==========================*/
|
||||
|
||||
#ifndef HSTRING
|
||||
#define HSTRING
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // 提供malloc、realloc、free、exit原型
|
||||
#include <string.h> // 提供strlen原型
|
||||
#include "Status.h" //**▲01 绪论**//
|
||||
|
||||
/*
|
||||
* 串的堆存储表示
|
||||
*
|
||||
* 注:有效元素从ch的0号单元开始存储
|
||||
*/
|
||||
typedef struct {
|
||||
char* ch; // 若是非空串,则按串长分配存储区,否则ch为NULL
|
||||
int length;
|
||||
} HString;
|
||||
|
||||
|
||||
/*
|
||||
* ████ 提示 ████
|
||||
*
|
||||
* 遵循教材的书写习惯,pos指示字符的位序(不是索引),从1开始计数
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* 初始化
|
||||
*
|
||||
* 构造一个值为chars的串T。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrAssign(HString* T, const char* chars);
|
||||
|
||||
/*
|
||||
* 销毁
|
||||
*
|
||||
* 将串S销毁。
|
||||
*/
|
||||
Status DestroyString(HString* S);
|
||||
|
||||
/*
|
||||
* 清空
|
||||
*
|
||||
* 将串S清空。
|
||||
*/
|
||||
Status ClearString(HString* S);
|
||||
|
||||
/*
|
||||
* 判空
|
||||
*
|
||||
* 判断串S中是否包含有效数据。
|
||||
*
|
||||
* 返回值:
|
||||
* TRUE : 串S为空
|
||||
* FALSE: 串S不为空
|
||||
*/
|
||||
Status StrEmpty(HString S);
|
||||
|
||||
/*
|
||||
* 计数
|
||||
*
|
||||
* 返回串S中元素的个数。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
int StrLength(HString S);
|
||||
|
||||
/*
|
||||
* 求子串
|
||||
*
|
||||
* 用Sub返回S[pos, pos+len-1]。
|
||||
* 返回值指示是否截取成功。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status SubString(HString* Sub, HString S, int pos, int len);
|
||||
|
||||
/*
|
||||
* 查找
|
||||
*
|
||||
* 从pos处开始搜索模式串T在主串S中首次出现的位置,如果不存在,则返回0。
|
||||
* 如果查找成功,返回匹配的位置。
|
||||
*
|
||||
*【注】
|
||||
* 1.此实现需要依赖串的最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
int Index(HString S, HString T, int pos);
|
||||
|
||||
/*
|
||||
* ████████ 算法4.4 ████████
|
||||
*
|
||||
* 插入
|
||||
*
|
||||
* 将串T插入到主串S的pos位置处。
|
||||
*/
|
||||
Status StrInsert(HString* S, int pos, HString T);
|
||||
|
||||
/*
|
||||
* 删除
|
||||
*
|
||||
* 删除S[pos, pos+len-1]。
|
||||
*/
|
||||
Status StrDelete(HString* S, int pos, int len);
|
||||
|
||||
/*
|
||||
* 比较
|
||||
*
|
||||
* 比较串S和串T,返回比较结果。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status StrCompare(HString S, HString T);
|
||||
|
||||
/*
|
||||
* 复制
|
||||
*
|
||||
* 将串S复制到串T。
|
||||
*/
|
||||
Status StrCopy(HString* T, HString S);
|
||||
|
||||
/*
|
||||
* 替换
|
||||
*
|
||||
* 用V替换主串S中出现的所有与T相等的且不重叠的子串。
|
||||
*
|
||||
*【注】
|
||||
* 1.该操作依赖最小操作子集
|
||||
* 2.该实现比较低效
|
||||
*/
|
||||
Status Replace(HString* S, HString T, HString V);
|
||||
|
||||
/*
|
||||
* 串联接
|
||||
*
|
||||
* 联接S1和S2,并存储到T中返回。如果联接后的长度溢出,则只保留未溢出的部分。
|
||||
* 返回值表示联接后的串是否完整。
|
||||
*
|
||||
*【注】
|
||||
* 该操作属于最小操作子集
|
||||
*/
|
||||
Status Concat(HString* T, HString S1, HString S2);
|
||||
|
||||
#endif
|
||||
76
VisualC++/CourseBook/0403_LString/0403_LString.vcxproj
Normal file
76
VisualC++/CourseBook/0403_LString/0403_LString.vcxproj
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}</ProjectGuid>
|
||||
<RootNamespace>My0403_LString</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<IncludePath>$(SolutionDir)\..\Status;$(IncludePath)</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>$(SolutionDir)\..\Status\Status.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<SubSystem>Console</SubSystem>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="LString-main.c" />
|
||||
<ClCompile Include="LString.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="LString.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="源文件">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="头文件">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="资源文件">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="LString.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LString-main.c">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="LString.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
</Project>
|
||||
152
VisualC++/CourseBook/0403_LString/LString-main.c
Normal file
152
VisualC++/CourseBook/0403_LString/LString-main.c
Normal file
@@ -0,0 +1,152 @@
|
||||
#include "LString.h" //**▲04 串**//
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(LString S);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char* chars = "01234567899876543210";
|
||||
LString S, T, sub, V;
|
||||
int i;
|
||||
|
||||
printf("████████ StrAssign \n");
|
||||
{
|
||||
printf("█ 为块链串 S 赋值...\n");
|
||||
StrAssign(&S, chars);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrEmpty \n");
|
||||
{
|
||||
StrEmpty(S) ? printf("█ S 为空!!\n") : printf("█ S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrLength \n");
|
||||
{
|
||||
i = StrLength(S);
|
||||
printf("█ S 的长度为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCopy \n");
|
||||
{
|
||||
printf("█ 复制 S 到 T ...\n");
|
||||
StrCopy(&T, S);
|
||||
printf("█ T = ");
|
||||
PrintElem(T);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrCompare \n");
|
||||
{
|
||||
printf("█ 比较字符串 S 和 T ...\n");
|
||||
i = StrCompare(S, T);
|
||||
i == 0 ? printf("█ S==T\n") : (i < 0 ? printf("█ S<T\n") : printf("█ S>T\n"));
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrInsert \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 将 \"*****\" 插入到串 S 的第 11 个位置处... \n");
|
||||
StrInsert(&S, 11, T);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Index \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
printf("█ 获取 \"*****\" 在串 S 中的第一次出现的位置...\n");
|
||||
i = Index(S, T, 1);
|
||||
printf("█ 串 \"*****\" 在 S 中第一次出现的位置为 %d \n", i);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ SubString \n");
|
||||
{
|
||||
printf("█ 用 sub 返回 S 中第 11 个字符起的 5 个字符...\n");
|
||||
SubString(&sub, S, 11, 5);
|
||||
printf("█ Sub = ");
|
||||
PrintElem(sub);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Replace \n");
|
||||
{
|
||||
StrAssign(&T, "*****");
|
||||
StrAssign(&V, "#####@@@@@");
|
||||
printf("█ 用 \"#####@@@@@\" 替换S中的 \"*****\" ...\n");
|
||||
Replace(&S, T, V);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ StrDelete \n");
|
||||
{
|
||||
printf("█ 删除 S 中第 16 个字符起的 5 个字符...\n");
|
||||
StrDelete(&S, 16, 5);
|
||||
printf("█ S = ");
|
||||
PrintElem(S);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ ClearString \n");
|
||||
{
|
||||
printf("█ 清空 S 前:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
|
||||
ClearString(&S);
|
||||
|
||||
printf("█ 清空 S 后:");
|
||||
StrEmpty(S) ? printf(" S 为空!!\n") : printf(" S 不为空!\n");
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
printf("████████ Concat \n");
|
||||
{
|
||||
LString Tmp, S1, S2;
|
||||
|
||||
StrAssign(&S1, "+++++");
|
||||
StrAssign(&S2, "-----");
|
||||
|
||||
printf("█ 联接 \"+++++\" 和 \"-----\" 形成 Tmp ...\n");
|
||||
Concat(&Tmp, S1, S2);
|
||||
printf("█ Tmp = ");
|
||||
PrintElem(Tmp);
|
||||
}
|
||||
PressEnterToContinue();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 测试函数,打印字符串
|
||||
void PrintElem(LString S) {
|
||||
int i = 0;
|
||||
Chunk* p = S.head;
|
||||
|
||||
if(S.curlen == 0 || S.head == NULL || S.tail == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
while(p != NULL) {
|
||||
// 遇到非串值符号时结束遍历
|
||||
if(p->ch[i] == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
printf("%c", p->ch[i]);
|
||||
|
||||
i = (i + 1) % CHUNKSIZE;
|
||||
|
||||
if(i == 0) {
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
719
VisualC++/CourseBook/0403_LString/LString.c
Normal file
719
VisualC++/CourseBook/0403_LString/LString.c
Normal file
File diff suppressed because it is too large
Load Diff
166
VisualC++/CourseBook/0403_LString/LString.h
Normal file
166
VisualC++/CourseBook/0403_LString/LString.h
Normal file
@@ -0,0 +1,166 @@
|
||||
/*=============================
|
||||
* 串的块链分配存储表示(块链串)
|
||||
==============================*/
|
||||
|
||||
#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);
|
||||
|
||||
#endif
|
||||
Binary file not shown.
@@ -41,6 +41,12 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0308_SqQueue", "0308_SqQueu
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0309_BankQueuing", "0309_BankQueuing\0309_BankQueuing.vcxproj", "{C44F604C-F8CD-498E-A3EF-04FCF37AA303}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0401_SString", "0401_SString\0401_SString.vcxproj", "{7D94FA2D-43E5-4EA0-AEBF-119C156C98FF}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0402_HString", "0402_HString\0402_HString.vcxproj", "{A1D8A416-186E-4691-B8E7-ED7DE605AA4C}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "0403_LString", "0403_LString\0403_LString.vcxproj", "{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
@@ -127,6 +133,18 @@ Global
|
||||
{C44F604C-F8CD-498E-A3EF-04FCF37AA303}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{C44F604C-F8CD-498E-A3EF-04FCF37AA303}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{C44F604C-F8CD-498E-A3EF-04FCF37AA303}.Release|Win32.Build.0 = Release|Win32
|
||||
{7D94FA2D-43E5-4EA0-AEBF-119C156C98FF}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{7D94FA2D-43E5-4EA0-AEBF-119C156C98FF}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{7D94FA2D-43E5-4EA0-AEBF-119C156C98FF}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{7D94FA2D-43E5-4EA0-AEBF-119C156C98FF}.Release|Win32.Build.0 = Release|Win32
|
||||
{A1D8A416-186E-4691-B8E7-ED7DE605AA4C}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{A1D8A416-186E-4691-B8E7-ED7DE605AA4C}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{A1D8A416-186E-4691-B8E7-ED7DE605AA4C}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{A1D8A416-186E-4691-B8E7-ED7DE605AA4C}.Release|Win32.Build.0 = Release|Win32
|
||||
{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{6D29CF1A-DFF3-4730-A587-EEEA5B3673F2}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user