1. 背景说明
串采用定长顺序存储结构实现的方式和字符串的区别在于字符串以字符 '\0' 作为字符结尾的标志,而顺序串采用长度来判断结尾。
2. 示例代码
1) status.h
/* DataStructure 预定义常量和类型头文件 */
#ifndef STATUS_H
#define STATUS_H
#define CHECK_NULL(pointer) if (!(pointer)) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_NULL_PTR); \
return NULL; \
}
#define CHECK_RET(ret) if (ret != RET_OK) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ret); \
return ret; \
}
#define CHECK_VALUE(value, ERR_CODE) if (value) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \
return ERR_CODE; \
}
#define CHECK_FALSE(value, ERR_CODE) if (!(value)) { \
printf("FuncName: %-15s Line: %-5d ErrorCode: %-3d\n", __func__, __LINE__, ERR_CODE); \
return FALSE; \
}
/* 函数结果状态码 */
#define TRUE 1 /* 返回值为真 */
#define FALSE 0 /* 返回值为假 */
#define RET_OK 0 /* 返回值正确 */
#define INFEASIABLE 2 /* 返回值未知 */
#define ERR_MEMORY 3 /* 访问内存错 */
#define ERR_NULL_PTR 4 /* 空指针错误 */
#define ERR_MEMORY_ALLOCATE 5 /* 内存分配错 */
#define ERR_NULL_STACK 6 /* 栈元素为空 */
#define ERR_PARA 7 /* 函数参数错 */
#define ERR_OPEN_FILE 8 /* 打开文件错 */
#define ERR_NULL_QUEUE 9 /* 队列为空错 */
#define ERR_FULL_QUEUE 10 /* 队列为满错 */
#define ERR_NOT_FOUND 11 /* 表项不存在 */
typedef int Status; /* Status 是函数的类型,其值是函数结果状态代码,如 RET_OK 等 */
typedef int Bollean; /* Boolean 是布尔类型,其值是 TRUE 或 FALSE */
#endif // !STATUS_H
2) sqString.h
/* 串采用定长顺序存储结构实现头文件 */
#ifndef SQSTRING_H
#define SQSTRING_H
#include "status.h"
#define MAX_STRLEN 10
typedef char SqString[MAX_STRLEN + 1];
/* 生成一个其值等于 chars 的串 T,该串最大长度为 MAX_STRLEN - 1, T[0] 存储字符串长度,留一个给空字符 */
Status StrAssign(SqString T, char *chars);
/* 由串 S 复制得串 T */
Status StrCopy(SqString T, SqString S);
/* 若 S 为空串,则返回 TRUE,否则返回 FALSE */
Status StrEmpty(SqString S);
/* 初始条件: 串 S 和 T 存在
操作结果: 若 S > T,则返回值 > 0;若S = T,则返回值 = 0;若 S < T,则返回值 < 0 */
int StrCompare(SqString S, SqString T);
/* 返回串的元素个数 */
int StrLength(SqString S);
/* 初始条件:串 S 存在
操作结果:将 S 清为空串 */
Status ClearString(SqString S);
/* 算法 4.2, 用 T 返回 S1 和 S2 联接而成的新串。若未截断,则返回 TRUE,否 FALSE */
Status Concat(SqString T, SqString S1, SqString S2);
/* 算法 4.3, 用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串 */
Status SubString(SqString Sub, SqString S, int pos, int len);
/* 算法 4.5, 返回子串 T 在主串 S 中第 pos 个字符之后的位置。若不存在,则函数值为 0
其中,T 非空,1 ≤ pos ≤ StrLength(S) */
int Index(SqString S, SqString T, int pos);
/* 初始条件: 串 S 和 T 存在,1 ≤ pos ≤ StrLength(S) + 1
操作结果: 在串 S 的第 pos 个字符之前插入串 T。完全插入返回 TRUE,部分插入返回 FALSE */
Status StrInsert(SqString S, int pos, SqString T);
/* 初始条件: 串 S 存在, 1 ≤ pos ≤ StrLength(S) - len + 1
操作结果: 从串 S 中删除第 pos 个字符起长度为 len 的子串 */
Status StrDelete(SqString S, int pos, int len);
/* 初始条件: 串 S, T 和 V 存在, T 是非空串(此函数与串的存储结构无关)
操作结果: 用 V 替换主串 S 中出现的所有与 T 相等的不重叠的子串 */
Status Replace(SqString S, SqString T, SqString V);
/* 由于 SqString 是定长类型,无法销毁 */
void DestoryString(void);
/* 输出字符串 T */
void StrPrint(SqString T);
#endif // !SQSTRING_H
3) sqString.c
/* 串采用定长顺序存储结构实现源文件 */
#include "sqString.h"
#include
#include
/* 生成一个其值等于 chars 的串 T,该串最大长度为 MAX_STRLEN - 1, T[0] 存储字符串长度,留一个给空字符 */
Status StrAssign(SqString T, char *chars)
{
CHECK_VALUE(!chars, ERR_NULL_PTR)
int length = strlen(chars);
CHECK_VALUE(length > MAX_STRLEN, ERR_PARA)
T[0] = length;
for (int i = 1; i <= T[0]; ++i) {
T[i] = *(chars + i - 1);
}
return RET_OK;
}
/* 由串 S 复制得串 T */
Status StrCopy(SqString T, SqString S)
{
for (int i = 0; i <= S[0]; ++i) {
T[i] = S[i];
}
return RET_OK;
}
/* 若 S 为空串,则返回 TRUE,否则返回 FALSE */
Status StrEmpty(SqString S)
{
return (S[0] == 0) ? TRUE : FALSE;
}
/* 初始条件: 串 S 和 T 存在
操作结果: 若 S > T,则返回值 > 0;若S = T,则返回值 = 0;若 S < T,则返回值 < 0 */
int StrCompare(SqString S, SqString T)
{
for (int i = 1; i <= S[0] && i <= T[0]; ++i) {
if (S[i] != T[i]) {
return S[i] - T[i];
}
}
return S[0] - T[0];
}
/* 返回串的元素个数 */
int StrLength(SqString S)
{
return S[0];
}
/* 初始条件:串 S 存在
操作结果:将 S 清为空串 */
Status ClearString(SqString S)
{
S[0] = 0;
return RET_OK;
}
/* 算法 4.2, 用 T 返回 S1 和 S2 联接而成的新串。若未截断,则返回 TRUE,否 FALSE */
Status Concat(SqString T, SqString S1, SqString S2)
{
for (int i = 0; i <= S1[0]; ++i) {
T[i] = S1[i];
}
/* 未截断 */
if (S1[0] + S2[0] <= MAX_STRLEN) {
for (int i = 1; i <= S2[0]; ++i) {
T[S1[0] + i] = S2[i];
}
T[0] = S1[0] + S2[0];
return TRUE;
}
/* 截断 */
for (int i = 1; i <= MAX_STRLEN - S1[0]; ++i) {
T[S1[0] + i] = S2[i];
}
T[0] = MAX_STRLEN;
return FALSE;
}
/* 算法 4.3, 用 Sub 返回串 S 的第 pos 个字符起长度为 len 的子串 */
Status SubString(SqString Sub, SqString S, int pos, int len)
{
CHECK_VALUE((pos < 1) || (pos) > S[0] || (len < 0) || (len > S[0] - pos + 1), ERR_PARA)
Sub[0] = len;
for (int i = 1; i <= len; ++i) {
Sub[i] = S[pos + i - 1];
}
return RET_OK;
}
/* 算法 4.5, 返回子串 T 在主串 S 中第 pos 个字符之后的位置。若不存在,则函数值为 0
其中,T 非空,1 ≤ pos ≤ StrLength(S) */
int Index(SqString S, SqString T, int pos)
{
CHECK_VALUE(!(1 <= pos) && (pos <= S[0]), 0)
int i = pos, j = 1;
while ((i <= S[0]) && (j <= T[0])) {
if (S[i] == T[j]) {
++i;
++j;
} else {
i = i - j + 2;
j = 1;
}
}
return (j > T[0]) ? (i - T[0]) : 0;
}
/* 初始条件: 串 S 和 T 存在,1 ≤ pos ≤ StrLength(S) + 1
操作结果: 在串 S 的第 pos 个字符之前插入串 T。完全插入返回 TRUE,部分插入返回 FALSE */
Status StrInsert(SqString S, int pos, SqString T)
{
CHECK_VALUE((pos < 1) || (pos > S[0] + 1), ERR_PARA)
Status ret = TRUE;
int offset = T[0];
int length = S[0];
if (S[0] + T[0] <= MAX_STRLEN) {
length += T[0];
} else {
length = MAX_STRLEN;
offset = MAX_STRLEN - S[0];
ret = FALSE;
}
for (int i = S[0]; i >= pos; --i) {
S[i + offset] = S[i];
}
for (int i = pos; i < pos + offset; ++i) {
S[i] = T[i - pos + 1];
}
S[0] = length;
return ret;
}
/* 初始条件: 串 S 存在, 1 ≤ pos ≤ StrLength(S) - len + 1
操作结果: 从串 S 中删除第 pos 个字符起长度为 len 的子串 */
Status StrDelete(SqString S, int pos, int len)
{
CHECK_VALUE((pos < 1) || (pos > S[0] - len + 1) || (len < 0), ERR_PARA)
for (int i = pos + len; i <= S[0]; ++i) {
S[i - len] = S[i];
}
S[0] -= len;
return RET_OK;
}
/* 初始条件: 串 S, T 和 V 存在, T 是非空串(此函数与串的存储结构无关)
操作结果: 用 V 替换主串 S 中出现的所有与 T 相等的不重叠的子串 */
Status Replace(SqString S, SqString T, SqString V)
{
CHECK_VALUE(StrEmpty(T), ERR_PARA)
int i = 1;
do {
i = Index(S, T, i);
if (i) {
StrDelete(S, i, StrLength(T));
StrInsert(S, i, V);
i += StrLength(V);
}
} while (i);
return RET_OK;
}
/* 由于 SqString 是定长类型,无法销毁 */
void DestoryString(void)
{
printf("Do not need to destory!\n");
}
/* 输出字符串 T */
void StrPrint(SqString T)
{
for (int i = 1; i <= T[0]; ++i) {
printf("%c", T[i]);
}
}
4) main.c
#include "sqString.h"
#include
#include
int main(void)
{
printf("Please input string s1: ");
char str[MAX_STRLEN + 1] = { 0 };
gets_s(str, sizeof(str));
SqString s1;
Status ret = StrAssign(s1, str);
CHECK_VALUE(ret != RET_OK, ret)
printf("The string s1 is %s, the length of s1 is %d\n", (StrEmpty(s1) == TRUE) ? "empty" : "not empty",
StrLength(s1));
SqString s2;
StrCopy(s2, s1);
printf("The string of s2 copied by s1 is: ");
StrPrint(s2);
printf("\n");
printf("Please input string s2: ");
gets_s(str, sizeof(str));
ret = StrAssign(s2, str);
CHECK_VALUE(ret != RET_OK, ret)
ret = StrCompare(s1, s2);
char ch = (ret == 0) ? '=' : ((ret < 0) ? '<' : '>');
printf("string s1 %c string s2\n", ch);
SqString t;
ret = Concat(t, s1, s2);
printf("The concat of s1 and s2 t is: ");
StrPrint(t);
printf("\n");
if (ret == FALSE) {
printf("There is truncation in connection\n");
}
ClearString(s1);
printf("After clear string s1, s1 is: ");
StrPrint(s1);
printf("\n");
printf("The string s1 is %s, the length of s1 is %d\n", (StrEmpty(s1) == TRUE) ? "empty" : "not empty",
StrLength(s1));
printf("Please input the start position and length of substring of sting t: ");
int pos, length;
scanf_s("%d%d", &pos, &length);
ret = SubString(s2, t, pos, length);
if (ret == RET_OK) {
printf("The substring of string t s2 is: ");
StrPrint(s2);
printf("\n");
}
printf("Please input the start position and length of substring of sting t to be deleted: ");
scanf_s("%d%d", &pos, &length);
StrDelete(t, pos, length);
printf("After delete substring, the string t is: ");
StrPrint(t);
printf("\n");
pos = StrLength(s2) / 2;
StrInsert(s2, pos, t);
printf("After insert string t before the %dth character of string s2, s2 is: ", pos);
StrPrint(s2);
printf("\n");
ret = Index(s2, t, 1);
printf("The %dth character of string s2 is matched with string t\n", ret);
SubString(t, s2, 1, 1);
printf("Substring t is: ");
StrPrint(t);
printf("\n");
Concat(s1, t, t);
printf("The string s1 is: ");
StrPrint(s1);
printf("\n");
Replace(s2, t, s1);
printf("After replace the same string of string t in string s2 that not overload with string s1, string s2 is: ");
StrPrint(s2);
printf("\n");
DestoryString();
return 0;
}
3. 输出示例