1 定义
串(string)是由零个或多个字符组成的有限序列,又名叫字符串。
一般记作:S='a1 a2 a3 a4 a5'(n>=0)
其中,S 是串名,单引号括起来的字符序列是串的值; a1 a2 a3可以是字母、数字或其他字符;串中字符的个数n称为串的长度。
另外还有一些其它概念:
1.空串:n = 0 n=0n=0时的串称为空串。
2.空格串:是只包含空格的串。注意它与空串的区别,空格串是有内容有长度的,而且可以不止一个空格。
3.子串与主串:串中任意个数的连续字符组成的子序列称为该串的子串,相应地,包含子串的串称为主串。
4.子串在主串中的位置就是子串的第一个字符在主串中的序号。
2 表现形式
2.1 定长顺序存储表示(顺序存储)
类似线性表的顺序存储结构,用一组地址连续的存储单元存储串值的字符序列。 在串的定长顺序存储结构中,按照预定义的大小,为每个定义的串变量分配一个固定长度 的存储区。空间在使用之后自动释放。代码如下:
#define MAXLEN 255 //预定义最大串长为255
typedef struct{
char ch[MAXLEN]; //每个分量存储一个字符
int length; //串的实际长度
}SString;
2.2 堆分配存储表示(顺序存储)
这种存储表示的特点是,仍以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配而得。代码如下:
typedef struct{
char *ch; //按串长分配存储区,ch指向串的基地址
int length; //串的长度
}HString;
!空间需要手动释放 S.ch = (char *) malloc(MAXLEN *sizeof(char));
2.3 块链存储表示(链式存储)
和线性表的链式存储结构相类似,也可采用链表方式存储串值。由于串结构的特殊性——结构中的每个数据元素是一个字符,则用链表存储串值时,存在一个“结点大小"的 问题,即每个结点可以存放一个字符,也可以存放多个字符。理解如图:
代码部分如下:
typedef struct StringNode{//每个结点存1个字符
char ch;
struct StringNode * next;
}StringNode,*String;
3.部分基本操作代码(仅供参考)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义字符串结构体
typedef struct {
char *data;
int length;
} String;
// 初始化字符串
void initString(String *s, const char *initValue) {
int len = strlen(initValue);
s->data = (char *)malloc((len + 1) * sizeof(char));
strcpy(s->data, initValue);
s->length = len;
}
// 增加字符串
void appendString(String *s, const char *appendValue) {
int len = strlen(appendValue);
int newLength = s->length + len;
s->data = (char *)realloc(s->data, (newLength + 1) * sizeof(char));
strcat(s->data, appendValue);
s->length = newLength;
}
// 删除字符串
void deleteString(String *s, int start, int count) {
if (start < 0 || start >= s->length || count < 0 || start + count > s->length) {
printf("删除位置或长度错误\n");
return;
}
int newLength = s->length - count;
memmove(s->data + start, s->data + start + count, newLength - start + 1);
s->length = newLength;
s->data = (char *)realloc(s->data, (newLength + 1) * sizeof(char));
}
// 修改字符串
void modifyString(String *s, int start, const char *modifyValue) {
int len = strlen(modifyValue);
if (start < 0 || start >= s->length) {
printf("修改位置错误\n");
return;
}
int remainingLength = s->length - start;
if (len > remainingLength) {
s->data = (char *)realloc(s->data, (start + len + 1) * sizeof(char));
}
strcpy(s->data + start, modifyValue);
s->length = strlen(s->data);
}
// 查找字符串
int findString(String s, const char *target) {
char *result = strstr(s.data, target);
if (result) {
return (result - s.data);
}
return -1;
}
// 输出字符串
void printString(String s) {
printf("%s\n", s.data);
}
int main() {
String myString;
initString(&myString, "Hello");
printf("初始字符串: ");
printString(myString);
appendString(&myString, " World");
printf("增加后的字符串: ");
printString(myString);
deleteString(&myString, 6, 5);
printf("删除后的字符串: ");
printString(myString);
modifyString(&myString, 0, "Hi");
printf("修改后的字符串: ");
printString(myString);
int position = findString(myString, "i");
if (position!= -1) {
printf("找到 'i' 的位置: %d\n", position);
} else {
printf("未找到 'i'\n");
}
free(myString.data);
return 0;
}
各位老爷,KMP另起一章(重点!)。