欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

链表实验-文件读取-增删改查

程序员文章站 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;
    }
}