要求
针对链接存储方式实现的字符串完成三个操作函数,分别实现在字符串取子串、查找子串、删除等子串功能。
相关知识
为了完成本关任务,你需要掌握:
如何实现一个链接存储的字符串;
链式存储字符串的基本操作。
如何实现一个链接存储的字符串
字符串的存储也可以采用链接存储方式来实现。一般采用带头结点的单链表方式存储串,但由于串结构的特殊性,每个数据元素是一个字符,则存在一个“结点大小”的问题。
具体实现时,串可以采用不同的存储策略。下面描述了非压缩形式的字符串链表的实现方案(每个节点存放一个字符):
为了讨论简单,本关任务我们采用非压缩形式的字符串链表的实现方案(即:每个节点存放一个字符):
typedef char datatype;// 串数据元素的数据类型
typedef struct node
{ datatype data;
struct node *next;
}linknode;
typedef linknode *linkstring;
链式存储字符串的基本操作
针对字符串链表数据,我们定义如下操作:
创建字符串链表:根据用户的输入创建一个长度为 len 的字符串链表,可以采用前插法和尾插法。具体操作函数定义如下:
linkstring creat(int len);
输出字符串:输出字符串 ,以 \0 结尾。该操作函数具体定义如下:
void print(linkstring head);
释放字符串链表: 将字符串链表释放销毁。具体操作函数定义如下:
delList(linkstring head);
取长度为 len 的子串:在字符串 str 中从第 i 个位置起取长度为 len 的子串(i 从 1 开始),函数返回子串链表,若子串超出边界,则返回从起始位置到串尾的子串,例如 str=computer i=6 len=8 则子串为ter。该操作函数具体定义如下:
linkstring SubString(linkstring s, int i, int len);
查找子串:查找子串 t 在主串 s 中第一次出现的位置,若匹配不成功,则返回 NULL。具体操作函数定义如下:
linkstring Index(linkstring s, linkstring t);
删除子串:在字符串 s 中删除从第 i 个位置开始(i 从 1 开始),长度为 len 的子串。具体操作函数定义如下:
void DelString(linkstring s, int i, int len);
#include <stdlib.h>
#include <stdio.h>
typedef char datatype;
typedef struct node
{ datatype data;
struct node *next;
}linknode;
typedef linknode *linkstring;
linkstring creat(int len);//尾插法建立字符单链表
void print(linkstring head);//输出字符串 ,以'\0'结尾
void delList(linkstring head);//释放单链表的内容
linkstring SubString(linkstring s, int i, int len);//在字符串s中从第i个位置起取长度为len的子串(i从1开始),函数返回子串链表。
linkstring Index(linkstring s, linkstring t);//查找子串t在主串s中第一次出现的位置,若匹配不成功,则返回NULL。
void DelString(linkstring s, int i, int len);//在字符串s中删除从第i个位置开始(i从1开始),长度为len的子串。
linkstring creat(int len)//尾插法建立字符单链表
{ linkstring head,r,s;
datatype x;
head=r=(linkstring)malloc(sizeof(linknode));
head->next=NULL;
while (len--)
{
scanf("%c",&x);
s=(linkstring)malloc(sizeof(linknode));
s->data=x;
r->next=s;
r=s;
}
r->next=NULL;
return head;
}
void print(linkstring head)//输出字符串 ,以'\0'结尾
{ linkstring p;
p=head->next;
printf("List is:");
while(p)
{ printf("%c",p->data);
p=p->next;
}
printf("\n");
}
void delList(linkstring head)//释放单链表的内容
{
linkstring p=head;
while (p)
{
head=p->next;
free(p);
p=head;
}
}
/*在字符串s中从第i个位置起取长度为len的子串(i从1开始),函数返回子串链表。*/
linkstring SubString(linkstring s, int i, int len) {
// 请在这里补充代码,完成本关任务
/********** Begin *********/
linkstring subHead = (linkstring)malloc(sizeof(linknode));
if (!subHead) return NULL; // Allocation failed
subHead->next = NULL;
linkstring r = subHead;
linkstring p = s->next;
int pos = 1;
while (p && pos < i) {
p = p->next;
pos++;
}
while (p && len > 0) {
linkstring newNode = (linkstring)malloc(sizeof(linknode));
if (!newNode) { // Allocation failed
delList(subHead); // Free the partial list
return NULL;
}
newNode->data = p->data;
newNode->next = NULL;
r->next = newNode;
r = newNode;
p = p->next;
len--;
}
return subHead;
/********** End **********/
}
/*查找子串t在主串s中第一次出现的位置,若匹配不成功,则返回NULL。*/
linkstring Index(linkstring s, linkstring t){
// 请在这里补充代码,完成本关任务
/********** Begin *********/
linkstring p = s->next;
linkstring q = t->next;
int pos = 1;
while (p) {
linkstring pTemp = p;
linkstring qTemp = q;
int tempPos = pos;
while (qTemp && pTemp->data == qTemp->data) {
pTemp = pTemp->next;
qTemp = qTemp->next;
}
if (!qTemp) return p; // Found the substring
p = p->next;
pos++;
}
return NULL; // Substring not found
/********** End **********/
}
/*在字符串s中删除从第i个位置开始(i从1开始),长度为len的子串。*/
void DelString(linkstring s, int i, int len) {
// 请在这里补充代码,完成本关任务
/********** Begin *********/
linkstring p = s;
int pos = 0;
while (p->next && pos < i - 1) { // Find the node before the start of the substring
p = p->next;
pos++;
}
linkstring toDelete = p->next;
while (toDelete && len > 0) { // Delete 'len' nodes
linkstring temp = toDelete;
toDelete = toDelete->next;
free(temp);
len--;
}
p->next = toDelete; // Reconnect the list
/********** End **********/
}