目录
前言
这篇博客主要讲串的用法。
1.串类型的定义
串(String)是由零个或者多个字符组成的有序序列。
串中字符的数目n称为串的长度。
零个字符的串称为空串,它的长度为零。
串中任意连续的字符组成的子序列称为该串的子串。
包含子串的串相应地称为主串。
通常称字符在序列中的序号称为该字符在串中的位置。
2.队列的表示和实现
队列可以分别使用顺存和链式两种存储方式实现。
1.定长顺序存储表示
类似线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。在串的定长顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定长度的存储区,则可用定长数组如下描述。
1.定义
// - - - - - 串的定长顺序存储表示 - - - - -
#define MAXSTRLEN 255 // 用户可在 255 以内定义最大串长
typedef unsigned char SString[MAXSTRLEN + 1];// 0号单元存放串的长度
typedef int Status;
2.串赋值
// 生成一个和chars相同的字符串
int strAssign(SString s, const char *chars) {
unsigned long len = strlen(chars);
if (len > MAXSTRLEN) {
return 0;
}
s[0] = (unsigned long)len;
for (int i = 0; i < len; i++) {
s[i + 1] = chars[i];
}
for (unsigned long i = len + 1; i <= MAXSTRLEN; i++) {
s[i] = '\0';
}
return 1;
}
3.串拷贝
//拷贝
void copyStr(SString s,const char * chars){
unsigned long len = strlen(chars);
if (len > MAXSTRLEN) {
len = MAXSTRLEN;
}
s[0] = (unsigned long)len;//存储字符串的长度
for (int i = 0; i< len; i++) {
s[i+1] = chars[i];
}
for (unsigned long i = len + 1; i<= MAXSTRLEN; i++) {
s[i] = '\0';
}
}
4.串空
// 串空
Status strEmpty(SString str){
return str[0] == 0;
}
5.串长
队首和队尾相同的时候,队列为空。
// 字符串长度
int strLength(SString s) {
return s[0];
}
6.清空串
// 清空
void clearString(SString str) {
for (int i = 1; i <= str[0]; i++) {
str[i] = '\0';
}
str[0] = 0;
}
7.串拼接
// 字符串拼接
void strConcat(SString str, SString str1, SString str2) {
int len1 = strLength(str1);
int len2 = strLength(str2);
int i, j;
if (len1 >= MAXSTRLEN) {
for (i = 1; i <= MAXSTRLEN; i++) {
str[i] = str1[i];
}
str[0] = MAXSTRLEN;
} else {
for (i = 1; i <= len1; i++) {
str[i] = str1[i];
}
if (len1 + len2 <= MAXSTRLEN) {
for (j = 1; j <= len2; j++) {
str[len1 + j] = str2[j];
}
str[0] = len1 + len2;
} else {
for (j = 1; j <= MAXSTRLEN - len1; j++) {
str[len1 + j] = str2[j];
}
str[0] = MAXSTRLEN;
}
}
}
8.截取子串
// 子串
void subString(SString sub, SString s, int pos, int len) {
if (pos < 1 || pos > strLength(s) || len < 0 || pos + len - 1 > strLength(s)) {
sub[0] = 0; // 空串
} else {
sub[0] = len;
for (int i = pos; i < pos + len; i++) {
sub[i - pos + 1] = s[i];
}
}
}
9.字符串替换
// 替换字符串中的子串
void replace(SString s, SString sub, SString replacement) {
int len = strLength(s);
int subLen = strLength(sub);
int repLen = strLength(replacement);
int pos = 1;
int index = 0;
while (pos <= len - subLen + 1) {
SString temp;
initString(temp);
subString(temp, s, pos, subLen);
if (strcmp(temp + 1, sub + 1) == 0) {
// Replace the substring
for (int i = pos; i <= pos + repLen - 1; i++) {
if (index >= MAXSTRLEN) {
return; // Avoid buffer overflow
}
s[i] = replacement[++index];
}
// Shift the remaining characters
for (int i = pos + repLen; i <= len; i++) {
s[i] = s[i + subLen - repLen];
}
len = len - subLen + repLen;
} else {
pos++;
}
}
s[0] = len;
}
10.插入串
// 在指定位置插入字符串
void strInsert(SString s, int pos, SString insertStr) {
int len = strLength(s);
int insertLen = strLength(insertStr);
if (pos < 1 || pos > len + 1 || len + insertLen > MAXSTRLEN) {
return; // 插入位置不合法或插入后长度超过最大长度,直接返回
}
// 将插入位置后的字符向后移动
for (int i = len; i >= pos; i--) {
s[i + insertLen] = s[i];
}
// 将待插入字符串插入
for (int i = 1; i <= insertLen; i++) {
s[pos + i - 1] = insertStr[i];
}
// 更新串的长度
s[0] = len + insertLen;
}
11.删除
// 从指定位置删除指定长度的子串
void strDelete(SString s, int pos, int len) {
int length = strLength(s);
if (pos < 1 || pos > length || len < 0 || pos + len > length + 1) {
return; // 删除位置不合法,直接返回
}
// 删除指定位置及后面的len个字符
for (int i = pos + len; i <= length; i++) {
s[i - len] = s[i];
}
s[0] -= len; // 更新串的长度
}
12.销毁
// 销毁字符串
void destroyString(SString str) {
// 释放动态分配的内存
free(str);
}
13.完整代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSTRLEN 10 // 用户可在 10 以内定义最大串长
typedef unsigned char SString[MAXSTRLEN + 1]; // 0号单元存放串的长度
typedef int Status;
void initString(SString str){
str[0] = 0;
}
// 字符串长度
int strLength(SString s) {
return s[0];
}
// 生成一个和chars相同的字符串
int strAssign(SString s, const char *chars) {
unsigned long len = strlen(chars);
if (len > MAXSTRLEN) {
return 0;
}
s[0] = (unsigned long)len;
for (int i = 0; i < len; i++) {
s[i + 1] = chars[i];
}
for (unsigned long i = len + 1; i <= MAXSTRLEN; i++) {
s[i] = '\0';
}
return 1;
}
// 在指定位置插入字符串
void strInsert(SString s, int pos, SString insertStr) {
int len = strLength(s);
int insertLen = strLength(insertStr);
if (pos < 1 || pos > len + 1 || len + insertLen > MAXSTRLEN) {
return; // 插入位置不合法或插入后长度超过最大长度,直接返回
}
// 将插入位置后的字符向后移动
for (int i = len; i >= pos; i--) {
s[i + insertLen] = s[i];
}
// 将待插入字符串插入
for (int i = 1; i <= insertLen; i++) {
s[pos + i - 1] = insertStr[i];
}
// 更新串的长度
s[0] = len + insertLen;
}
// 从指定位置删除指定长度的子串
void strDelete(SString s, int pos, int len) {
int length = strLength(s);
if (pos < 1 || pos > length || len < 0 || pos + len > length + 1) {
return; // 删除位置不合法,直接返回
}
// 删除指定位置及后面的len个字符
for (int i = pos + len; i <= length; i++) {
s[i - len] = s[i];
}
s[0] -= len; // 更新串的长度
}
// 字符串拼接
void strConcat(SString str, SString str1, SString str2) {
int len1 = strLength(str1);
int len2 = strLength(str2);
int i, j;
if (len1 >= MAXSTRLEN) {
for (i = 1; i <= MAXSTRLEN; i++) {
str[i] = str1[i];
}
str[0] = MAXSTRLEN;
} else {
for (i = 1; i <= len1; i++) {
str[i] = str1[i];
}
if (len1 + len2 <= MAXSTRLEN) {
for (j = 1; j <= len2; j++) {
str[len1 + j] = str2[j];
}
str[0] = len1 + len2;
} else {
for (j = 1; j <= MAXSTRLEN - len1; j++) {
str[len1 + j] = str2[j];
}
str[0] = MAXSTRLEN;
}
}
}
// 子串
void subForString(SString sub, SString s, int pos, int len) {
if (pos < 1 || pos > strLength(s) || len < 0 || pos + len - 1 > strLength(s)) {
sub[0] = 0; // 空串
} else {
sub[0] = len;
for (int i = pos; i < pos + len; i++) {
sub[i - pos + 1] = s[i];
}
}
}
//拷贝
void copyStr(SString s,const char * chars){
unsigned long len = strlen(chars);
if (len > MAXSTRLEN) {
len = MAXSTRLEN;
}
s[0] = (unsigned long)len;//存储字符串的长度
for (int i = 0; i< len; i++) {
s[i+1] = chars[i];
}
for (unsigned long i = len + 1; i<= MAXSTRLEN; i++) {
s[i] = '\0';
}
}
// 串空
Status strEmpty(SString str){
return str[0] == 0;
}
// 销毁字符串
void destroyString(SString str) {
// 释放动态分配的内存
free(str);
}
// 清空
void clearString(SString str) {
for (int i = 1; i <= str[0]; i++) {
str[i] = '\0';
}
str[0] = 0;
}
// 打印str
void printStr(SString str){
int len = str[0];
for (int i = 1; i<= len; i++) {
printf("%c",str[i]);
}
}
// 替换字符串中的子串
void replace(SString s, SString sub, SString replacement) {
int len = strLength(s);
int subLen = strLength(sub);
int repLen = strLength(replacement);
int pos = 1;
int index = 0;
while (pos <= len - subLen + 1) {
SString temp;
initString(temp);
subForString(temp, s, pos, subLen);
if (strcmp(temp + 1, sub + 1) == 0) {
// Replace the substring
for (int i = pos; i <= pos + repLen - 1; i++) {
if (index >= MAXSTRLEN) {
return; // Avoid buffer overflow
}
s[i] = replacement[++index];
}
// Shift the remaining characters
for (int i = pos + repLen; i <= len; i++) {
s[i] = s[i + subLen - repLen];
}
len = len - subLen + repLen;
} else {
pos++;
}
}
s[0] = len;
}
// 测试函数
void testString(void) {
SString str, subStr, replacement, insertStr;
printf("\n**********\t字符串是否为空操作\t**********\n");
if (strEmpty(str)) {
printf("字符串为空\n");
}
printf("字符串长度:%d\n", strLength(str));
printf("**********\t字符串赋值操作\t**********\n");
if (strAssign(str, "ABCDEFGHIJKL")) {
printf("赋值成功\n");
} else {
printf("赋值错误\n");
}
if (strAssign(str, "ABCDEFGHIJ")) {
printf("赋值成功,str:");
printStr(str);
printf("\n");
} else {
printf("赋值错误\n");
}
printf("\n**********\t字符串拷贝操作\t**********\n");
SString copStr;
copyStr(copStr, "ABCDEFGHIJK");
printf("拷贝之后的字符串:");
printStr(copStr);
printf("\n");
printf("\n**********\t字符串是否为空操作\t**********\n");
if (!strEmpty(copStr)) {
printf("字符串不为空\n");
}
printf("字符串长度:%d\n", strLength(copStr));
printf("\n**********\t字符串清空操作\t**********\n");
clearString(copStr);
printf("清空之后的字符串:");
printStr(copStr);
printf("\n");
printf("\n**********\t字符串拼接操作\t**********\n");
strAssign(str, "ABCDEFG");
strAssign(subStr, "HIJK");
strConcat(str, str, subStr);
printf("拼接之后的字符串:");
printStr(str);
printf("\n");
printf("\n**********\t字符串截取操作\t**********\n");
SString subString;
subForString(subString, str, 5, 5);
printf("截取之后的字符串:");
printStr(subString);
printf("\n");
printf("\n**********\t字符串替换操作\t**********\n");
strAssign(str, "Hello, world!");
strAssign(subStr, "world");
strAssign(replacement, "everyone");
replace(str, subStr, replacement);
printf("替换之后的字符串:");
printStr(str);
printf("\n");
printf("\n**********\t字符串插入操作\t**********\n");
strAssign(insertStr, "my ");
strInsert(str, 7, insertStr);
printf("插入之后的字符串:");
printStr(str);
printf("\n");
printf("\n**********\t字符串删除操作\t**********\n");
strDelete(str, 6, 10);
printf("删除之后的字符串:");
printStr(str);
printf("\n");
printf("\n**********\t销毁字符串操作\t**********\n");
destroyString(str);
destroyString(subStr);
destroyString(replacement);
destroyString(insertStr);
}
int main(int argc, const char *argv[]) {
testString();
return 0;
}
2.堆分配存储表示
用一组地址连续的存储单元存放串值字符序列,但是它们的存储空间是在程序执行过程中动态分配的。C语言中,存放一个称为“堆”的自由存储区,并且这些存储区域由动态分配函数malloc()和free()管理。
1.定义
// - - - - - 串的分配存储表示 - - - - -
typedef int Status;
typedef struct {
char *ch; // 若是非空串,则按串长分配存储区;否则,ch为NULL
int length; // 串长度
} HString;
2.赋值
// 生成一个和chars相同的字符串
Status strAssign(HString *s, const char *chars) {
int len = strlen(chars);
if (len == 0) {
s->ch = NULL;
s->length = 0;
} else {
s->ch = (char *)malloc((len + 1) * sizeof(char));
if (!s->ch) {
return 0; // 内存分配失败
}
strcpy(s->ch, chars);
s->length = len;
}
return 1;
}
3.字符串长度
// 字符串长度
int strLength(HString str) {
return str.length;
}
4.字符串比较
// 字符串比较
int strCompare(HString s, HString t) {
int len_s = strLength(s);
int len_t = strLength(t);
int min_len = len_s < len_t ? len_s : len_t;
for (int i = 0; i < min_len; i++) {
if (s.ch[i] != t.ch[i]) {
return s.ch[i] - t.ch[i];
}
}
return len_s - len_t;
}
5.清空串
// 清空字符串
Status clearString(HString str) {
if (str.ch) {
free(str.ch);
str.ch = NULL;
str.length = 0;
}
return 1;
}
6.拼接串
// 拼接字符串
Status concat(HString result, HString str1, HString str2) {
int len1 = strLength(str1);
int len2 = strLength(str2);
result.ch = (char *)malloc((len1 + len2 + 1) * sizeof(char));
if (!result.ch) {
return 0; // 内存分配失败
}
strcpy(result.ch, str1.ch);
strcat(result.ch, str2.ch);
result.length = len1 + len2;
return 1;
}
7.截取串
// 截取字符串
HString subString(HString s, int pos, int len) {
HString sub;
if (pos < 1 || pos > s.length || len < 0 || pos + len - 1 > s.length) {
sub.ch = NULL;
sub.length = 0;
return sub; // 返回空串
}
sub.ch = (char *)malloc((len + 1) * sizeof(char));
if (!sub.ch) {
sub.length = 0;
return sub; // 内存分配失败,返回空串
}
strncpy(sub.ch, s.ch + pos - 1, len);
sub.ch[len] = '\0'; // 添加字符串结束符
sub.length = len;
return sub;
}
9.完整代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// - - - - - 串的分配存储表示 - - - - -
typedef int Status;
typedef struct {
char *ch; // 若是非空串,则按串长分配存储区;否则,ch为NULL
int length; // 串长度
} HString;
// 生成一个和chars相同的字符串
Status strAssign(HString *s, const char *chars) {
int len = strlen(chars);
if (len == 0) {
s->ch = NULL;
s->length = 0;
} else {
s->ch = (char *)malloc((len + 1) * sizeof(char));
if (!s->ch) {
return 0; // 内存分配失败
}
strcpy(s->ch, chars);
s->length = len;
}
return 1;
}
// 字符串长度
int strLength(HString str) {
return str.length;
}
// 字符串比较
int strCompare(HString s, HString t) {
int len_s = strLength(s);
int len_t = strLength(t);
int min_len = len_s < len_t ? len_s : len_t;
for (int i = 0; i < min_len; i++) {
if (s.ch[i] != t.ch[i]) {
return s.ch[i] - t.ch[i];
}
}
return len_s - len_t;
}
// 清空字符串
Status clearString(HString str) {
if (str.ch) {
free(str.ch);
str.ch = NULL;
str.length = 0;
}
return 1;
}
// 拼接字符串
Status concat(HString result, HString str1, HString str2) {
int len1 = strLength(str1);
int len2 = strLength(str2);
result.ch = (char *)malloc((len1 + len2 + 1) * sizeof(char));
if (!result.ch) {
return 0; // 内存分配失败
}
strcpy(result.ch, str1.ch);
strcat(result.ch, str2.ch);
result.length = len1 + len2;
return 1;
}
// 截取字符串
HString subString(HString s, int pos, int len) {
HString sub;
if (pos < 1 || pos > s.length || len < 0 || pos + len - 1 > s.length) {
sub.ch = NULL;
sub.length = 0;
return sub; // 返回空串
}
sub.ch = (char *)malloc((len + 1) * sizeof(char));
if (!sub.ch) {
sub.length = 0;
return sub; // 内存分配失败,返回空串
}
strncpy(sub.ch, s.ch + pos - 1, len);
sub.ch[len] = '\0'; // 添加字符串结束符
sub.length = len;
return sub;
}
// 测试函数
void testString(void) {
HString str1, str2, result;
strAssign(&str1, "Hello");
strAssign(&str2, "World");
// 测试字符串赋值和长度
printf("str1: %s, length: %d\n", str1.ch, strLength(str1));
printf("str2: %s, length: %d\n", str2.ch, strLength(str2));
// 测试字符串比较
printf("Compare str1 and str2: %d\n", strCompare(str1, str2));
// 测试字符串拼接
concat(result, str1, str2);
printf("Concatenated string: %s, length: %d\n", result.ch, strLength(result));
// 测试字符串截取
HString sub = subString(result, 3, 5);
printf("Substring from position 3 with length 5: %s, length: %d\n", sub.ch, strLength(sub));
// 清空字符串
clearString(str1);
printf("After clearing str1, length: %d\n", strLength(str1));
}
int main(int argc, const char *argv[]) {
testString();
return 0;
}