C语言实现链串基本操作
通过调用简单函数实现顺序串的相关操作,其中大部分操作其实都可以通过string.h中的函数实现,所以这里的操作仅供理解,目的是领会链串存储结构和掌握链串中的各种基本运算算法设计。代码编译环境为VS2019 16.11.2。因为VS的某些原因,scanf写为了scanf_s,作用是一样的,在其他编译环境中可将scanf_s改回去。
#include<stdio.h> //输入输出头文件
#include<stdlib.h> //标准库头文件
#include<stdbool.h> //C语言布尔类型头文件
#define MaxSize 999
typedef char ElemType;
typedef struct String //字符串结构体
{
ElemType data;
struct String* next;
}StrNode;
void menu(void); //输出菜单
bool StrAssige(StrNode*&); //建立顺序串
bool StrShow(StrNode*); //输出顺序串
bool StrLength(StrNode*); //输出顺序串长度
bool InsStr(StrNode*&); //特定位置插入字符串
bool DelStr(StrNode*&); //删除特定位置字符串
bool RepStr(StrNode*&); //替换特定位置字符串
bool SubStr(StrNode*); //截取子串
bool Concat(StrNode*&); //在顺序串后面追加内容
bool DestroyStr(StrNode*&); //销毁链串
int main(int argc, const char* argv[])
{
StrNode* Str = NULL;
bool flag = false;
int n;
menu();
while (scanf_s("%d", &n) != EOF) {
switch (n) {
case 1:flag = StrAssige(Str); break;
case 2:flag = StrShow(Str); break;
case 3:flag = StrLength(Str); break;
case 4:flag = InsStr(Str); break;
case 5:flag = DelStr(Str); break;
case 6:flag = RepStr(Str); break;
case 7:flag = SubStr(Str); break;
case 8:flag = Concat(Str); break;
case 0:DestroyStr(Str); goto Out;
default:
printf("指令错误,请重新输入,若想终止程序请输入文件尾。\n");
}
if (flag)
printf("指令执行成功!\n");
else
printf("指令执行失败!\n");
menu();
}
Out:
return 0;
}
void menu(void)
{
printf("===========菜单==========\n");
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");
}
bool StrAssige(StrNode* &s)
{
int i = 0;
StrNode* p = NULL, * r = NULL;
s = (StrNode*)malloc(sizeof(StrNode)); //为头结点申请空间
while (s == NULL) {
s = (StrNode*)malloc(sizeof(StrNode));
}
r = s; //将尾指针指向最后一个元素
printf("请输入一个字符串:\n");
ElemType str[MaxSize];
scanf_s("%s", str, MaxSize);
for (i = 0; str[i] != '\0'; i++) { //将字符串中除结尾'\0'外的字符按顺序放入链串
p = (StrNode*)malloc(sizeof(StrNode));
while (p == NULL) {
p = (StrNode*)malloc(sizeof(StrNode));
}
p->data = str[i]; //将存有元素的节点采用尾插法插入链串中
r->next = p;
r = p;
}
r->next = NULL;
return true;
}
bool StrShow(StrNode* s)
{
if (s == NULL || s->next == NULL) {
printf("字符串不存在,请先建立字符串。\n");
return false;
}
StrNode* r = s->next;
while (r != NULL) { //挨个遍历顺序串
printf("%c", r->data);
r = r->next;
}
printf("\n");
return true;
}
bool StrLength(StrNode* s)
{
int length = 0;
StrNode* r = s->next;
while (r != NULL) { //挨个遍历顺序串
length ++;
r = r->next;
}
printf("该字符串长度为%d。\n", length); //输出长度
return true;
}
bool InsStr(StrNode*& s)
{
if (s == NULL || s->next == NULL) {
printf("字符串不存在,请先建立字符串。\n");
return false;
}
int i, n, length = 0;
StrNode* p, * r = s->next;
while (r != NULL) { //挨个遍历顺序串并统计长度
length++;
r = r->next;
}
printf("请输入插入位置:\n");
scanf_s("%d", &n);
if (n <= 0 || n > length) { //当位置比顺序串的头还要靠前,比尾还要靠后时位置无效
printf("位置不合法,无法插入。\n");
return false;
}
ElemType strs[MaxSize]; //要插入的字符串
r = s;
for (i = 1; i < n; i++) { //将尾指针移到要插入位置的前驱节点
r = r->next;
}
printf("请输入要插入的字符串:\n");
scanf_s("%s", strs, MaxSize);
//将字符串插入它要插入的位置
for (i = 0; strs[i] != '\0'; i++) {
p = (StrNode*)malloc(sizeof(StrNode));
while (p == NULL) {
p = (StrNode*)malloc(sizeof(StrNode));
}
p->data = strs[i];
p->next = r->next;
r->next = p;
r = p;
}
return true;
}
bool DelStr(StrNode*& s)
{
if (s == NULL || s->next == NULL) {
printf("字符串不存在,请先建立字符串。\n");
return false;
}
int i, j, k, length = 0;
StrNode* p, *r = s->next;
while (r != NULL) { //挨个遍历顺序串并统计长度
length++;
r = r->next;
}
printf("请输入要删除的开始位置与要删除的长度:");
scanf_s("%d%d", &i, &j);
if (i <= 0 || i > length || j<0 || i+j>length) { //当位置比顺序串的头还要靠前,比尾还要靠后时位置无效
printf("位置不合法,无法删除。\n");
return false;
}
r = s;
for (k = 1; k < i; k++) { //将尾指针移到要删除位置的前驱节点
r = r->next;
}
//将被删除的子串释放
for (k = 0; k < j; k++) {
p = r->next;
r->next = p->next;
free(p);
}
return true;
}
bool RepStr(StrNode*& s)
{
if (s == NULL || s->next == NULL) {
printf("字符串不存在,请先建立字符串。\n");
return false;
}
int i, j, k, length = 0;
StrNode* p = NULL, * r = s->next;
while (r != NULL) { //挨个遍历顺序串并统计长度
length++;
r = r->next;
}
printf("请输入要替换的开始位置与要替换的长度:");
scanf_s("%d%d", &i, &j);
if (i <= 0 || i > length || j<0 || i + j>length) { //当位置比顺序串的头还要靠前,比尾还要靠后时位置无效
printf("位置不合法,无法完成替换。\n");
return false;
}
r = s;
for (k = 1; k < i; k++) { //将尾指针移到要替换位置的前驱节点
r = r->next;
}
ElemType strs[MaxSize]; //替换后的字符串
printf("请输入替换后的字符串:\n");
scanf_s("%s", strs, MaxSize);
//将被替换的字符串删除
for (k = 0; k < j; k++) {
p = r->next;
r->next = p->next;
free(p);
}
//将替换后的字符串插入
for (i = 0; strs[i] != '\0'; i++) { //将数据结点顺序插入
p = (StrNode*)malloc(sizeof(StrNode));
while (p == NULL) {
p = (StrNode*)malloc(sizeof(StrNode));
}
p->data = strs[i];
p->next = r->next;
r->next = p;
r = p;
}
return true;
}
bool SubStr(StrNode* s)
{
if (s == NULL || s->next == NULL) {
printf("字符串不存在,请先建立字符串。\n");
return false;
}
int i, j, k, length = 0;
StrNode* r = s->next;
while (r != NULL) { //挨个遍历顺序串并统计长度
length++;
r = r->next;
}
printf("请输入要提取的开始位置与要提取的长度:");
scanf_s("%d%d", &i, &j);
if (i <= 0 || i > length || j<0 || i + j>length-1) { //当位置比顺序串的头还要靠前,比尾还要靠后时位置无效
printf("位置不合法,无法完成提取。\n");
return false;
}
r = s;
for (k = 1; k < i; k++) { //将尾指针移到要提取位置的前驱节点
r = r->next;
}
//将规定的子串输出
for (k = 0; k < j; k++) {
r = r->next;
printf("%c", r->data);
}
printf("\n");
return true;
}
bool Concat(StrNode*& s)
{
if (s == NULL || s->next == NULL) {
printf("字符串不存在,请先建立字符串。\n");
return false;
}
StrNode* p, * r = s->next;
ElemType str[MaxSize];
int i;
printf("请输入要连接的字符串:\n");
scanf_s("%s", str, MaxSize);
//将新字符串接到原字符串后面
while (r->next != NULL) { //将尾指针移到尾部
r = r->next;
}
for (i = 0; str[i] != '\0'; i++) {
p = (StrNode*)malloc(sizeof(StrNode));
while (p == NULL) {
p = (StrNode*)malloc(sizeof(StrNode));
}
p->data = str[i];
p->next = r->next;
r->next = p;
r = p;
}
return true;
}
bool DestroyStr(StrNode*& s)
{
//将链串包括头结点全部释放
StrNode* p;
while (s != NULL) {
p = s;
s = s->next;
free(p);
}
return true;
}