链表实验-文件读取-增删改查
程序员文章站
2022-05-13 15:09:33
...
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
//========================================================结构体===========================================================
//字符类型节点
typedef struct Node
{
char *data; //字符型指针
struct Node *next; //指向同类型节点的指针
} NODE, *PNODE;
//字符串链表
typedef struct LinkedList
{
PNODE head; //头节点
int length; //链表长度
} LINKEDLIST, *PLINKLIST;
//========================================================函数列表===========================================================
void appendNode(PLINKLIST list, char *value); //尾部追加节点
void headAddNode(PLINKLIST list, char *value); //头部插入节点
void insertNode(PLINKLIST list, char *value, int index); //任意位置插入节点
void delAll(PLINKLIST list); //清空链表
void delNodeByIndex(PLINKLIST list, int index); //删除指定下标的节点
PNODE findNodeByIndex(PLINKLIST list, int index); //根据下标查找并返回节点
void readFile(PLINKLIST list, char *filePath); //载入文件
void opration(PLINKLIST list); //循环操作
void outPutAllList(PLINKLIST list); //输出链表所有
void findData(PLINKLIST list); //查找
void insertData(PLINKLIST list); //插入
void delData(PLINKLIST list); //删除
void findEnglish(PLINKLIST list); //英文精确查找
void findChinese(PLINKLIST list); //中文模糊查找
void getWord(char *data, char *result, int options); //获取,英文,词型,中文三种字符串的函数
int cmp(char *str, char *find); //判断str字符串中是否包含find字符串
int cmpAll(char *str, char *find); //全词匹配
//========================================================主函数============================================================
void main()
{
PLINKLIST list = (PLINKLIST)malloc(sizeof(LINKEDLIST)); //创建链表
list->length = 0;
list->head = NULL;
readFile(list, "cet4word2.txt"); //加载数据
opration(list); //循环测试
alert(6); //佛祖保佑,永无bug
}
//========================================================WORD-CRUD=========================================================
/*
功能:载入文件
参数: filePath 文件路径
返回值:无
*/
void readFile(PLINKLIST list, char *filePath)
{
char buf[1024];
//打开文件输入流
FILE *fp = fopen(filePath, "r");
//校验文件是否打开成功
if (fp == NULL)
{
printf("文件打开失败");
return;
}
//将流写入数组中
while (!feof(fp)) //如果文件没有结束,那么就持续循环
{
//读取一行到buf中
//申请空间
if (NULL != fgets(buf, 1024, fp))
{
//将数据追加到链表中
appendNode(list, buf);
}
}
//关闭文件输入流
fclose(fp);
alert(1);
}
/*
功能:循环测试个模块功能
参数: list 链表
返回值:无
*/
void opration(PLINKLIST list)
{
_flushall(); //以防万一,清除一下流
char op; //输入的操作
//输出一些操作前的提示
alert(5);
alert(6);
alert(3);
//循环操作,输入操作类型
while (1)
{
printf("请输入您的操作:");
_flushall();
op = getchar();
if (op == '0' || op == '1' || op == '2' || op == '3' || op == '4' || op == '5')
{
if (op == '0')
{
printf("退出成功\n");
return;
}
break;
}
else
{
printf("您的输入有误\n");
}
}
//循环操作,执行操作的函数
while (op != '0')
{
switch (op)
{
case '1':
outPutAllList(list);
break;
case '2':
findData(list); //暂时不可用
break;
case '3':
insertData(list);
break;
case '4':
delData(list);
break;
default:
printf("请输入合法字符\n");
break;
}
printf("请继续您的操作:");
_flushall();
op = getchar();
if (op == '0')
{
printf("退出成功\n");
}
}
}
/*
功能:输入链表所有信息
参数:
list 链表
返回值:
无
*/
void outPutAllList(PLINKLIST list)
{
int i = 1;
PNODE temp = list->head;
while (temp != NULL)
{
printf("第 %d 个的内容是 %s \n", i, temp->data);
temp = temp->next;
i++;
}
}
/*
功能:英文精确查找,中文模糊查找
参数:无
返回值:无
思路:
分两种情况:1、英文查找 2、中文查找
*/
void findData(PLINKLIST list)
{
_flushall(); //以防万一,清除一下流
alert(4);
char op; //输入的操作
//循环操作,输入操作类型
while (1)
{
printf("请输入您的操作:");
_flushall();
op = getchar();
if (op == '0' || op == '1' || op == '2')
{
if (op == '0')
{
alert(3);
return;
}
break;
}
else
{
printf("您的输入有误\n");
}
}
//循环操作,执行操作的函数
while (op != '0')
{
switch (op)
{
case '1':
findEnglish(list); //英文查找
break;
case '2':
findChinese(list); //中文查找
break;
default:
printf("请输入合法字符\n");
break;
}
printf("请输入您的操作:");
_flushall();
op = getchar();
if (op == '0')
{
alert(3);
}
}
}
/*
功能:英文精确查找
参数:
list
返回值:
无
思路:
输入一个要查找的英文字符串,value
循环执行
对list中的某个data进行剪切,遇见第一个逗号就停止,然后将第一个逗号之前的字符串保存到一个字符数组中叫 A
用strstr函数对比 a和value 如果一样 就打印当前 data 并结束这个函数
*/
void findEnglish(PLINKLIST list)
{
char value[100];
char *english = (char *)malloc(sizeof(char) * 1000);
printf("请输入要查询的内容:");
scanf("%s", value);
PNODE tempNode = list->head;
while (tempNode != NULL)
{
getWord(tempNode->data, english, 1);
if (cmpAll(english, value)) //精确查找
{
printf("查找成功,内容为:%s\n", tempNode->data);
return;
}
tempNode = tempNode->next;
}
printf("未搜寻到结果\n");
}
/*
功能:中文模糊查找
参数:
list
返回值:
无
*/
void findChinese(PLINKLIST list)
{
char value[100];
char *chinese = (char *)malloc(sizeof(char) * 1000);
printf("请输入要查询的内容:");
scanf("%s", value);
PNODE tempNode = list->head;
while (tempNode != NULL)
{
getWord(tempNode->data, chinese, 3);
if (cmp(chinese, value)) //模糊查找
{
printf("查找成功,内容为:%s\n", tempNode->data);
}
tempNode = tempNode->next;
}
}
/*
功能:获取英文单词
参数:
char *data 输入值
result 返回值
int 返回值类型 1、英文 2、词性 3、翻译
*/
void getWord(char *data, char *result, int options)
{
int pos = 0;
int j = 0;
for (int i = 0; i < 1000; i++)
{
if (options == 1) //英文
{
if (data[i] == ',') //输入数据碰见第一个“,”结束循环,此时result中是英文
{
result[i] = '\0';
return;
}
result[i] = data[i]; //一个字符一个字符的将数据切割
}
else if (options == 2) //词性
{
if (data[i] == ',')
{
pos++;
i++; //跳过“,”
}
if (pos == 1) //从第一个“,”开始之后赋值
{
result[j] = data[i]; //加1就是跳过,号
j++;
}
if (pos == 2) //遇见第二个“,”此时的result是词型
{
result[j] = '\0';
return;
}
}
else
{
if (data[i] == ',')
{
pos++;
i++; //跳过“,”
}
if (pos == 2) //从第二个“,”开始之后赋值
{
char temp;
int k = i; //也不知道为啥i的步长变成了2,所以这里新开辟一个空间k
while (1)
{
result[j] = data[k]; //赋值
temp = data[k];
k++;
j++;
if (temp == '\0') //字符串结束
{
return;
}
}
}
}
}
}
/*
功能:插入元素
参数:无
返回值:无
*/
void insertData(PLINKLIST list)
{
int pos; //插入的位置
char value[1024]; //插入的数据
printf("请输入您将要插入的数据:");
scanf("%s", &value);
printf("请输入您要插入的位置:");
scanf("%d", &pos);
//插入之前判断一下是否可以插入
while (1)
{
if (pos < 1 || pos > (list->length + 1))
{
printf("插入的位置不合理,请重新输入位置:");
scanf("%d", &pos);
}
else
{
break;
}
}
//开始插入
insertNode(list, value, pos - 1);
printf("插入成功\n");
}
/*
功能:删除某个节点
参数:无
返回值:无
*/
void delData(PLINKLIST list)
{
int pos; //删除的位置
printf("请输入您要删除的位置:");
scanf("%d", &pos);
while (1)
{
if (pos < 1 || pos > list->length)
{
printf("删除的位置不合理,请重新输入位置:");
scanf("%d", &pos);
}
else
{
break;
}
}
delNodeByIndex(list, pos - 1);
printf("删除成功\n");
}
//========================================================链表添加===========================================================
/*
功能:尾部追加
参数:
list 链表
value 要追加的元素
返回值:
无
原理:
两种情况:1、空链表2、非空链表
1、空链表:将值赋给头节点 length++
2、非空链表:
例如 a b c 三个节点,现在将temp节点插入到尾部
c->next = temp length++
关键是获取到最后一个节点
*/
void appendNode(PLINKLIST list, char *value)
{
PNODE tempNode = (PNODE)malloc(sizeof(NODE)); //为新加的节点申请空间
char *newData = (char *)malloc(1024); //新开辟一块空间去放数据
tempNode->data = strcpy(newData, value);
tempNode->next = NULL;
//判断是否是空链表
//空链表
if (list->length == 0)
{
list->head = tempNode; //赋值给头部节点
list->length++;
}
//非空链表
else
{
findNodeByIndex(list, list->length - 1)->next = tempNode; //尾部节点指向新加的节点
list->length++;
}
}
/*
功能:头部追加
参数:
list 链表
value 追加的值
返回值:
无
原理:
两种情况:1、空链表2、非空链表
1、空链表:将值赋给头节点 length++
2、非空链表:
例如 a b c 三个节点,现在将temp节点插入到头部
temp->next = list->head
list->head = temp
*/
void headAddNode(PLINKLIST list, char *value)
{
PNODE tempNode = (PNODE)malloc(sizeof(NODE)); //为新加的节点申请空间
char *newData = (char *)malloc(1024); //新开辟一块空间去放数据
tempNode->data = strcpy(newData, value);
tempNode->next = NULL;
//判断是否是空链表
//空链表
if (list->length == 0)
{
list->head = tempNode; //赋值给头部节点
list->length++;
}
//非空链表
else
{
tempNode->next = list->head; //新节点指向头节点
list->head = tempNode; //头节点重新命名为head
list->length++;
}
}
/*
功能:插入数据
参数:
list 链表
value 插入的值
index 插入的下标
返回值:
无
原理:
三种情况:1、位置在头部2、位置在中间3、末尾
1、直接调用headAdd()
2、假设有 a b c 三个节点 现在有一个temp节点要插入到位置2,即插入后的顺序是 a temp b c
temp->next = a->next
a->next = temp
关键是要找到节点a,即要插入位置的前一个节点
*/
void insertNode(PLINKLIST list, char *value, int index)
{
if (index < 0 || index > list->length)
{
printf("插入位置不合理");
return;
}
PNODE tempNode = (PNODE)malloc(sizeof(NODE));
char *newData = (char *)malloc(1024); //新开辟一块空间去放数据
tempNode->data = strcpy(newData, value);
tempNode->next = NULL;
if (index == 0)
{
headAddNode(list, value); //头加
list->length++;
}
else if (index == list->length)
{
appendNode(list, value);
}
else
{
tempNode->next = findNodeByIndex(list, index - 1)->next;
findNodeByIndex(list, index - 1)->next = tempNode;
list->length++;
}
}
//========================================================链表删除===========================================================
/*
功能:清空链表
参数:
list 要清空的链表
返回值:
无
原理:
循环free
*/
void delAll(PLINKLIST list)
{
list->length = 0;
while (list->head != NULL)
{
PNODE tempNode = list->head;
list->head = list->head->next;
free(tempNode);
}
}
/*
功能:删除指定下标的节点
参数:
list 链表
index 要删除节点的下标
返回值:
无
原理:
两种情况:1、头部节点 2、尾部节点
1、头部节点 例如有 a b c 现在要删除a
temp = list-head 将头部节点存储
list->head = list->head->next 将头部变成第二个元素
temp->next = NULL a断开和b的连接
free(temp)
2、中间节点 例如有 a b c 现在要删除b
temp = a->next
a->next = a->next->next a的下一个节点指向c 但是b现在也指向了c,所以还得操作一波
temp->next = NULL b指向空
*/
void delNodeByIndex(PLINKLIST list, int index)
{
//空链表判断
if (list->length == 0)
{
printf("链表已空");
return;
}
//位置判断
if (index < 0 || index > list->length - 1)
{
printf("删除位置不合理");
return;
}
//头节点删除
if (index == 0)
{
PNODE tempNode = list->head;
list->head = list->head->next;
tempNode->next = NULL;
list->length--;
return;
}
//其他位置删除
else
{
PNODE tempNode = findNodeByIndex(list, index - 1)->next;
findNodeByIndex(list, index - 1)->next = findNodeByIndex(list, index - 1)->next->next;
tempNode->next = NULL;
list->length--;
}
}
/*
功能:删除并打印返回被删除的节点
参数:
index
list
返回值:
无
*/
PNODE delNodeByIndexReturnNode(PLINKLIST list, int index)
{
//空链表判断
if (list->length == 0)
{
printf("链表已空");
return;
}
//位置判断
if (index < 0 || index > list->length - 1)
{
printf("删除位置不合理");
return;
}
//头节点删除
if (index == 0)
{
PNODE tempNode = list->head;
list->head = list->head->next; //将第二个节点变成头节点
tempNode->next = NULL;
list->length--;
return tempNode;
}
//其他位置删除
else
{
PNODE tempNode = findNodeByIndex(list, index - 1)->next;
findNodeByIndex(list, index - 1)->next = findNodeByIndex(list, index - 1)->next->next;
tempNode->next = NULL;
list->length--;
return tempNode;
}
}
//========================================================链表查找===========================================================
/*
功能:根据下标获取节点
参数:
list 链表
index 下标
返回值:
tempNode 对应下表的节点
*/
PNODE findNodeByIndex(PLINKLIST list, int index)
{
PNODE tempNode = list->head; //将临时变量指向头节点
if (list->length == 0)
{
printf("空链表\n");
return;
}
if (index < 0 || index > (list->length - 1))
{
printf("下标不合理\n");
return;
}
int j = 0; //下标
while (tempNode != NULL)
{
if (index != j)
{
tempNode = tempNode->next;
j++;
}
else
{
return tempNode;
}
}
}
//========================================================字符比较函数===========================================================
/*
功能:中文模糊查找
参数:
str 被查找的字符串
find 要查找的字符串
返回值:
0 str不包含find
1 str包含find
思路:
这里一个中文字符有三个字节
先获取str的length 和find的length
校验
if
str.length<find.length 返回0
else
这里的find要和str中的起始位置0,1,2分别比较才能确保包含在str中
for(j=0;j<str.length-find.length;j++){外层循环循环str的位置
int k = 0;
for(i=0;i<find.length;i++){内层循环循环find的值,分别于str的值进行比较
if(find[i] == str[j]){
k++;
if(i==find.length){
return 1; 找到了
}
while (k != strlen(find))
{
if (find[i + k] == str[j + k])//当第一个字符匹配后,就开始比较后面字符是否一样
{
k++;
if (k == strlen(find))//全一样就说明包含
{
return 1;
}
}
else
{
k = 0; //k重新赋值为0
break;
}
}
}
}
12345
345
}
*/
int cmp(char *str, char *find)
{
if (strlen(find) > strlen(str))
{
return 0;
}
else
{
for (int j = 0; j < strlen(str); j++)
{
// printf("===========第 %d 次 循环==========\n", j);
int k = 0;
for (int i = 0; i < strlen(find); i++)
{
// printf("find[%d] == %d str[%d] == %d\n", i, find[i], j, str[j]);
if (find[i] == str[j])
{
k++;
// printf("k----->%d\n", k);
if (k == strlen(find))
{
return 1;
}
while (k != strlen(find))
{
if (find[i + k] == str[j + k])
{
k++;
if (k == strlen(find))
{
return 1;
}
}
else
{
k = 0; //k重新赋值为0
break;
}
}
}
}
}
return 0;
}
}
/*
功能:英文精确查找
参数:
str 被查找的字符串
find 要查找的字符串
返回值:
0 str != find
1 str == find
思路:
*/
int cmpAll(char *str, char *find)
{
if (strlen(str) != strlen(find))
{
return 0;
}
else
{
int k = 0;
for (int i = 0; i < strlen(str); i++)
{
if (find[i] == str[i])
{
k++;
if (k == strlen(str))
{
return 1;
}
}
else
{
return 0;
}
}
}
}
//========================================================提示信息===========================================================
/*
功能:各种提示信息
参数:options
返回值:无
*/
void alert(int options)
{
switch (options)
{
case 1:
printf("-------------------------------------------------------------\n");
printf("| |\n");
printf("| 词库数据装载成功 |\n");
printf("| |\n");
printf("-------------------------------------------------------------\n");
break;
case 2:
printf("-------------------------------------------------------------\n");
printf("| |\n");
printf("| 暂无词库数据记录 |\n");
printf("| |\n");
printf("-------------------------------------------------------------\n");
break;
case 3:
printf("-------------------------------------------------------------\n");
printf("| |\n");
printf("| 1.显示词库所有信息 |\n");
printf("| 2.查找单词 |\n");
printf("| 3.插入单词 |\n");
printf("| 4.删除单词 |\n");
printf("| 0.退出系统 |\n");
printf("| |\n");
printf("| |\n");
printf("-------------------------------------------------------------\n");
break;
case 4:
printf("-------------------------------------------------------------\n");
printf("| |\n");
printf("| 1.英文全词匹配查找 |\n");
printf("| 2.中文模糊查找 |\n");
printf("| 0.退出 |\n");
printf("| |\n");
printf("-------------------------------------------------------------\n");
break;
case 5:
printf("-------------------------------------------------------------\n");
printf("| 欢迎使用英汉辞典 |\n");
printf("-------------------------------------------------------------\n");
break;
case 6:
printf(" _ooOoo_ \n");
printf(" o8888888o \n");
printf(" 88 '.' 88 \n");
printf(" (| -_- |) \n");
printf(" O\\ = /O \n");
printf(" ____/`---'\\____ \n");
printf(" .' \\| |// `. \n");
printf(" / \\||| : |||// \\ \n");
printf(" / _||||| -:- |||||- \\ \n");
printf(" | | \\\\ - /// | | \n");
printf(" | \\_| ''\\---/'' | | \n");
printf(" \\ .-\\__ `-` ___/-. / \n");
printf(" ___`. .' /--.--\\ `. . __ \n");
printf(" .'' '< `.___\\_<|>_/___.' >'''. \n");
printf(" | | : `- \\`.;`\\ _ /`;.`/ - ` : | | \n");
printf(" \\ \\ `-. \\_ __\\ /__ _/ .-` / / \n");
printf(" ======`-.____`-.___\\_____/___.-`____.-'====== \n");
printf(" `=---=' \n");
printf(" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ \n");
printf(" 佛祖保佑 永无BUG \n");
break;
default:
break;
}
}
上一篇: 生成验证码