定义
顺序字符串是由一系列字符按照特定的顺序排列而形成的字符串。在顺序字符串中,每个字符都有一个唯一的位置,称为索引,用来表示字符在字符串中的位置。索引从0开始,依次递增,直到字符串的长度减1。
顺序字符串的定义包括以下几个要点:
- 字符集:顺序字符串由一个字符集合组成,这个字符集合可以包含字母、数字、符号等字符。字符集合的选择取决于具体的应用场景和需求。
- 字符顺序:在顺序字符串中,字符按照一定的顺序排列。这个顺序可以是字符在字符集合中的顺序,也可以是根据特定的排序规则进行排列。
- 索引:顺序字符串中的每个字符都有一个唯一的索引值,用来表示字符在字符串中的位置。索引从0开始,依次递增,直到字符串的长度减1。
- 字符串长度:顺序字符串的长度是指字符串中字符的个数。可以通过计算字符串的长度来获取。
特点
顺序字符串具有以下几个特点:
-
有序性:顺序字符串中的字符按照一定的顺序排列。这个顺序可以是字符在字符集合中的顺序,也可以是根据特定的排序规则进行排列。这种有序性使得我们可以通过索引值来访问和操作字符串中的字符。
-
索引访问:顺序字符串中的每个字符都有一个唯一的索引值,用来表示字符在字符串中的位置。索引从0开始,依次递增,直到字符串的长度减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;
}
从字符常量拷贝
/* 从字符常量拷贝 */
int sstrcpy(sstring* S, char* from) {
int i;
int len = strlen(from);
if (len > S->max) {
printf("超出了字符串S的长度!1001\n");
return 1001;
}
for (i = 0; i < len; i++) {
S->data[i] = from[i];
}
S->data[i] = '\0';
S->len = len;
return 0;
}
模式匹配
/* 模式匹配 */
int sstrmatch(sstring* S, sstring* sub) {
int i, j, k;
int m = S->len;
int n = sub->len;
for (i = 0; i <= m - n; i++) {
j = 0;
k = i;
while (j < n && S->data[k] == sub->data[j]) {
j++;
k++;
}
if (j == n) {
return i;
}
}
return -1;
}
比较两个顺序字符串
/* 比较两个顺序字符串 */
int sstrcmp(const sstring* s1, const sstring* s2) {
if (s1->len != s2->len) {
return 1;
}
return strcmp(s1->data, s2->data);
}
获取两个顺序字符串长度
/* 获取顺序字符串的长度 */
int sstrlen(const sstring* s) {
return s->len;
}
拼接串
/* 将一个 C 字符串拼接到顺序字符串的末尾 */
void sstrcat(sstring* dest, const char* src) {
int new_length = dest->len + strlen(src);
char* new_data = (char*)malloc(new_length * sizeof(char));
strcpy(new_data, dest->data);
strcat(new_data, src);
dest->len = new_length;
free(dest->data);
dest->data = new_data;
}
运行结果
完整Demo
main.c
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <string.h>
#include "sstring.h"
#include <stdlib.h>
int main(int argc, char* argv[]) {
sstring S;
sstring sub;
int index;
char str1[100];
char str2[100];
char* str = "Hello C World!";
char* substr = "World";
init(&S, 1000);
init(&sub, 100);
sstrcpy(&S, str);
sstrcpy(&sub, substr);
int choice;
printf("-----------串演示-----------\n");
while (1) {
printf(" 1. 初始化串\n");
printf(" 2. 输入串\n");
printf(" 3. 从字符常量拷贝\n");
printf(" 4. 模式匹配\n");
printf(" 5. 比较串长度\n");
printf(" 6. 输出串长度\n");
printf(" 7. 输出串内容\n");
printf(" 8. 串的拼接\n");
printf(" 0. 退出\n");
printf("请选择操作(0-8):");
scanf("%d", &choice);
if (choice == 0) {
printf("程序退出\n");
break;
}
switch (choice) {
case 1: // 初始化
init(&S, 1000);
init(&sub, 100);
printf("初始化成功!\n\n");
break;
case 2: // 输入串
printf("请输入主串:");
scanf("%s", str1);
printf("请输入子串:");
scanf("%s", str2);
printf("\n");
break;
case 3: // 从字符串常量拷贝
sstrcpy(&S, str1);
sstrcpy(&sub, str2);
printf("从字符常量拷贝已完成!\n\n");
break;
case 4: // 模式匹配
index = sstrmatch(&S, &sub);
if (index >= 0)
{
printf("匹配成功,子串在主串的%d位置\n\n", index);
}
else
{
printf("主串中不存在子串!\n\n");
}
break;
case 5: // 串比较
if (sstrcmp(&S, &sub) == 1) {
printf("主串的长度大于子串的长度\n\n");
}
else if (sstrcmp(&S, &sub) == -1) {
printf("主串的长度小于子串的长度\n\n");
}
else printf("主串和子串的长度相等但字符不一样\n");
break;
case 6: // 串的长度
int len = sstrlen(&S);
printf("主串:%s的长度为%d\n", str1, sstrlen(&S));
printf("子串:%s的长度为%d\n\n", str2, sstrlen(&sub));
break;
case 7: // 输出顺序字符串
printf("主串打印:%s\n", S.data);
printf("子串打印:%s\n\n", sub.data);
break;
case 8: // 串的拼接
char concat[1000];
printf("请输入要拼接的字符串:");
scanf("%s", concat);
sstrcat(&S, concat);
printf("拼接成功,新串为 \"%s\"\n\n", S.data);
break;
}
}
return 0;
}
sstring,c
/*
sstring.c
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include "sstring.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.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* from) {
int i;
int len = strlen(from);
if (len > S->max) {
printf("超出了字符串S的长度!1001\n");
return 1001;
}
for (i = 0; i < len; i++) {
S->data[i] = from[i];
}
S->data[i] = '\0';
S->len = len;
return 0;
}
/* 模式匹配 */
int sstrmatch(sstring* S, sstring* sub) {
int i, j, k;
int m = S->len;
int n = sub->len;
for (i = 0; i <= m - n; i++) {
j = 0;
k = i;
while (j < n && S->data[k] == sub->data[j]) {
j++;
k++;
}
if (j == n) {
return i;
}
}
return -1;
}
/* 比较两个顺序字符串 */
int sstrcmp(const sstring* s1, const sstring* s2) {
if (s1->len != s2->len) {
return 1;
}
return strcmp(s1->data, s2->data);
}
/* 获取顺序字符串的长度 */
int sstrlen(const sstring* s) {
return s->len;
}
/* 将一个 C 字符串拼接到顺序字符串的末尾 */
void sstrcat(sstring* dest, const char* src) {
int new_length = dest->len + strlen(src);
char* new_data = (char*)malloc(new_length * sizeof(char));
strcpy(new_data, dest->data);
strcat(new_data, src);
dest->len = new_length;
free(dest->data);
dest->data = new_data;
}
sstring.h
#pragma once
/*
sstring.h
顺序字符串
*/
typedef struct {
char* data;
int max;
int len;
} sstring;
/* 初始化串 */
int init(sstring* S, int max);
/* 从字符常量拷贝 */
int sstrcpy(sstring* S, char* from);
/* 模式匹配 */
int sstrmatch(sstring* S, sstring* sub);
/* 比较两个顺序字符串 */
int sstrcmp(const sstring* s1, const sstring* s2);
/* 获取顺序字符串的长度 */
int sstrlen(const sstring* s);
/* 将一个 C 字符串拼接到顺序字符串的末尾 */
void sstrcat(sstring* dest, const char* src);
小结
总之,顺序字符串具有有序性、索引访问、字符串长度、不可变性和各种字符串操作等特点,这些特点使得顺序字符串成为一种非常常见和重要的数据结构。
顺序字符串是一种常见且重要的数据结构,广泛应用于编程和计算机科学领域。了解和理解顺序字符串的特点和操作,对于处理和操作字符串数据非常有帮助。
参考
百度