目录
一.串的定义与特点
串(string)是由零个或多个字符组成的有限序列,又名叫字符串。
一般记为s=“a1a2……an”(n>0),其中,s是串的名称,用双引号(有些书中也用单引号)括起来的字符序列是串的值。注意双引号不属于串的内容。ai(1≤i≤n)可以是字母、数字或其他字符,i就是该字符在串中的位置。串中的字符数目n称为串的长度,定义中谈到"有限"是指n是一个有限数值。
1.2串的特点
1.字符顺序:字符串中的字符按照一定的顺序排列,每个字符都有一个对应的位置索引。
2.不可变性:字符串的内容在创建后通常是不可更改的,也就是说,不能直接修改字符串中的某个字符,只能通过重新创建字符串来实现修改。
3.可迭代性:字符串可以被看作是一个字符序列,可以通过迭代的方式访问其中的每个字符。
1.3基本运算
a.求串长:求一个字符串的长度,也就是字符串中字符的个数。
b.串复制:将输入的字符串存储到原字符串中。
c.串联接:将俩个字符串连接起来,形成一个新的字符串。
d.串比较:将这两个字符串从左到右逐个字符比较。
二. 循环串的存储机构定义
typedef struct
{
char* data;
int max;
int len;
}sstring;
字符串的实现
1.初始化
int init(sstring *S, int max) {
S->data = (char *) malloc(sizeof(char) * max);
if (!S->data) {
printf("申请内存失败!1000\n");
return 1000;
}
S->max = max;
S->len = 0;
return 0;
}
2.串的拷贝
int sstrcpy(sstring *S, char *str) {
int i;
int fromLength = getLength(str);
if (fromLength > S->max) {
printf("超出了字符串S的长度!1001\n");
return 1001;
}
for (i = 0; i < fromLength; i++) {
S->data[i] = str[i];
}
S->data[i] = '\0';
S->len = fromLength;
return 0;
}
3.串的匹配
int sstrmatch(sstring *S, const char *str) {
int i, j, k;
int m = S->len;
int n = getLength(str);
for (i = 0; i <= m - n; i++) {
j = 0;
k = i;
while (j < n && S->data[k] == str[j]) {
j++;
k++;
}
if (j == n) {
return i+1;
}
}
return -1;
}
4.比较字符串大小
void comparison(sstring *S, sstring *str) {
int sLength = getLength(S->data);
int strLength = getLength(str->data);
if (sLength == strLength) {
int i;
for (i = 0; i < S->len;) {
int sAscll = (int) S->data[i];
int strAscll = (int) str->data[i];
if (sAscll == strAscll) {
i++;
} else if (sAscll > strAscll) {
printf("%s比%s大\n", S->data, str->data);
break;
} else {
printf("%s比%s大\n", str->data, S->data);
break;
}
}
if(i == S->len){
printf("两个字符串相等\n");
}
} else if (sLength > strLength) {
printf("%s比%s大:\n", S->data, str->data);
} else {
printf("%s比%s大:\n", str->data, S->data);
}
}
5.获取串长度
int getLength(const char *str) {
int length = 0;
while (str[length] != '\0'){
length++;
}
return length;
}
6.联接字符串
void addSstring(sstring *S, const char from[]) {
int fromLength = getLength(from);
for (int i = 0; i < fromLength; ++i) {
S->data[S->len + i] = from[i];
}
S->data[S->len + fromLength] = '\0';
S->len += fromLength;
}
7.输出字符串
void printfS(sstring *S) {
printf("%s\n", S->data);
}
三、完整Demo
main.c
#include <stdio.h>
#include <stdlib.h>
#include "sstring.c"
#include "welcome.h"
int main() {
sstring S, str;
int cmd, max, index;
str.data = malloc(100);
for (int i = 0; i < getLength(welcome); i++) {
printf("%c", welcome[i]);
for (int m = 0; m < 1000; m++)
for (int n = 0; n < 1000; n++) {
}
}
do {
printf("---------串的储存结构演示-----------\n");
printf("1.初始化串\n");
printf("2.从字符常量拷贝\n");
printf("3.模式匹配\n");
printf("4.比较字符串的大小\n");
printf("5.字符串长度\n");
printf("6.追加字符串\n");
printf("7.输出字符串\n");
scanf("%d", &cmd);
switch (cmd) {
case 1:
printf("请输入串的最大存储值:\n");
scanf("%d", &max);
fflush(stdin);
if (!init(&S, max)) {
printf("初始化串成功!\n");
} else {
printf("初始化串失败!\n");
}
break;
case 2:
printf("请输入拷贝的串:\n");
fflush(stdin); // 清除输入缓冲区中的换行符
scanf(" %[^\n]", str.data); // 加上空格,以消耗掉换行符
if (!sstrcpy(&S, str.data)) {
printf("拷贝成功!\n");
} else {
printf("拷贝失败!\n");
}
break;
case 3:
printf("请输入子串:\n");
scanf(" %[^\n]", str.data);
fflush(stdin);
index = sstrmatch(&S, str.data);
if (index != -1) {
printf("匹配成功,子串在主串的%d位置!\n", index);
} else {
printf("主串中不存在子串:%s\n", str.data);
}
break;
case 4:
printf("请输入比较大小的字符串:");
scanf(" %[^\n]", str.data);
fflush(stdin);
comparison(&S, &str);
break;
case 5:
printf("字符串长度:%d\n", getLength(S.data));
break;
case 6:
printf("请输入追加的字符串:\n");
scanf(" %[^\n]", str.data);
fflush(stdin);
addSstring(&S, str.data);
printf("追加成功!\n");
break;
case 7:
printfS(&S);
break;
case 0:
printf("感谢使用!\n");
break;
default:
printf("输入有误!请重新输入\n");
break;
}
} while (cmd != 0);
free(S.data);
free(str.data);
return 0;
}
sstring.c
/*
sstring.c
*/
#include <stdio.h>
#include "sstring.h"
#include <stdlib.h>
/*初始化串*/
int init(sstring *S, int max) {
S->data = (char *) malloc(sizeof(char) * max);
if (!S->data) {
printf("申请内存失败!1000\n");
return 1000;
}
S->max = max;
S->len = 0;
return 0;
}
/*从字符常量拷贝*/
int sstrcpy(sstring *S, char *str) {
int i;
int fromLength = getLength(str);
if (fromLength > S->max) {
printf("超出了字符串S的长度!1001\n");
return 1001;
}
for (i = 0; i < fromLength; i++) {
S->data[i] = str[i];
}
S->data[i] = '\0';
S->len = fromLength;
return 0;
}
/*模式匹配*/
int sstrmatch(sstring *S, const char *str) {
int i, j, k;
int m = S->len;
int n = getLength(str);
for (i = 0; i <= m - n; i++) {
j = 0;
k = i;
while (j < n && S->data[k] == str[j]) {
j++;
k++;
}
if (j == n) {
return i+1;
}
}
return -1;
}
/*比较字符串大小*/
void comparison(sstring *S, sstring *str) {
int sLength = getLength(S->data);
int strLength = getLength(str->data);
if (sLength == strLength) {
int i;
for (i = 0; i < S->len;) {
int sAscll = (int) S->data[i];
int strAscll = (int) str->data[i];
if (sAscll == strAscll) {
i++;
} else if (sAscll > strAscll) {
printf("%s比%s大\n", S->data, str->data);
break;
} else {
printf("%s比%s大\n", str->data, S->data);
break;
}
}
if(i == S->len){
printf("两个字符串相等\n");
}
} else if (sLength > strLength) {
printf("%s比%s大:\n", S->data, str->data);
} else {
printf("%s比%s大:\n", str->data, S->data);
}
}
/*获取串的长度*/
int getLength(const char *str) {
int length = 0;
while (str[length] != '\0'){
length++;
}
return length;
}
/*追加字符串*/
void addSstring(sstring *S, const char from[]) {
int fromLength = getLength(from);
for (int i = 0; i < fromLength; ++i) {
S->data[S->len + i] = from[i];
}
S->data[S->len + fromLength] = '\0';
S->len += fromLength;
}
/*输出串*/
void printfS(sstring *S) {
printf("%s\n", S->data);
}
sstring.h
/*
sstring.h
顺序字符串
*/
typedef struct
{
char* data;
int max;
int len;
}sstring;
/*初始化串*/
int init(sstring *S, int max);
/*从字符常量拷贝*/
int sstrcpy(sstring *S, char *str);
/*模式匹配*/
int sstrmatch(sstring *S, const char *str);
/*比较字符串大小*/
void comparison(sstring *S, sstring *str);
/*字符串长度*/
int getLength(const char *str);
/*追加*/
void addSstring(sstring *S, const char *from);
/*输出字符串*/
void printfS(sstring *S);
welcome.h
char welcome[] = "hjl";
四、总结
串(String)是由零个或多个字符组成的有限序列,又名叫字符串。本质上,它是一种线性表的扩展,但相对于线性表关注一个个元素来说,对串这种结构更多的是关注它子串的应用问题,如查找、替换等操作。现在的高级语言都有针对串的函数可以调用。我们在使用这些函数的时候,同时也应该要理解它在当中的原理,以便于在碰到复杂问题时,可以更加灵活的使用,比如KMP模式匹配算法的学习,就是更有效地去理解index函数当中的实现细节。
五、参考文献
《数据结构(c语言版)》李刚 刘万辉