• 简单行编辑程序


    实验题目:简单行编辑程序
    一,题目:
    30、简单行编辑程序
    [问题描述]
    文本编辑程序是利用计算机进行文字加工的基本软件工具,实现对文本文件的插入、删除等修改操作。限制这些操作以行为单位进行的编辑程序称为行编辑程序。
    被编辑的文本文件可能很大,全部读入编辑程序的数据空间(内存)的做法既不经济,
    也不总能实现。一种解决方法是逐段地编辑。任何时刻只把待编辑文件的一段放在内存,称为活区。试按照这种方法实现一个简单的行编辑程序。设文件每行不超过 320 个字符,很少超过 80 字符。
    [基本要求]
    实现以下 4 条基本编辑命令:
    (1) 行插入。格式:i<行号><回车><文本><回车>
    将<文本>插入活区中第<行号>行之后
    (2)行删除。格式:d<行号 1>[□<行号 2>]<回车>
    删除活区中第<行号 1>行(到第<行号 2>行)。两种格式的例子是:“d10↙”和“d10□14↙”
    (3)活区切换。格式:n<回车>
    将活区写入输出文件,并从输入文件中读入下一段,作为新的活区。
    (4)活区显示。格式:p<回车>
    逐页地(每页 20 行)显示活区内容,每显示一页之后请用户决定是否继续显示以后各
    页(如果存在)。印出的每一行要前置以行号和一个空格符,行号固定占 4 位,增量为 1。
    各条命令中的行号均须在活区中各行行号范围之内,只有插入命令的行号可以等于活区
    第一行行号减 1,表示插入当前屏幕中第一行之前,否则命令参数非法。
    13 [选作内容] (1) 对于命令格式非法等一切错误作严格检查和适当处理。 (2) 加入更复杂的编辑操作,如对某行进行串替换;在活区内进行模式匹配
    二、要解决的问题
    (1) 行插入。
    (2)行删除。
    (3)活区切换。
    (4)活区显示。
    附加:
    (5)在活区内进行多或单模式匹配
    三、算法基本思想描述:
    对于题目的要求,在进行活区切换及显示,行插入,行删除,模式匹配都要求涉及链表,所以对链表进行的基本操作在课设中有所体现,而在附加功能中,使用了AC自动机,进行匹配,来提高时间效率。
    AC自动机,其实类似于字典树+KMP算法,通过构建匹配失败后的fail指针,来构建AC自动机的模式匹配树,而fail的构建涉及bfs算法,而fail的构建算法,首先先将连接于root的点的所有子节点连向root的点,再将所有非NULL的点压入队列,弹出进行操作,考虑节点失配的情况,让失配的节点p->next[i]->fail=p->fail->next[i];这个过程后就可以建立一颗带fail节点的字典树。
    而在自动机的匹配过程中就是按照生成的fail树对应匹配。即匹配失败就移动到p->next[i]->fail.
    顺带补充下字典树的建立,
    本课设的字典树是采用指针版,即一个节点下有对应的30的子指针,代表a-z,然后如果为空即代表没有这个字母。如果不为空,这代表有这个字母,假设abc,fde建立的字典树如图:


    四、设计
    1. 数据结构的设计
    (1)储存结构:
    1.
    const int MAXN = 81;
    const int MAXNS = 1024;
    char file_name[MAXNS]; ///储存用户输入的地址
    char file_ends_name[MAXNS]; ///储存文本输出的地址
    char AC_TIRE_ARR[325 * 25];///代表AC自动机要匹配的数组
    2.读出和读入文件的数据结构:
    typedef struct NODE
    {
    char words[MAXN];///代表每个节点中储存的数据
    struct NODE *next;///指向下一个节点
    int num; ///代表行数(供输出的时候使用)
    bool flag; ///flag代表行结束,行没结束时,flag==false,结束时///将其标记为true
    } node;
    3.AC自动机中的字典树的数据结构
    typedef struct TIRE
    {
    struct TIRE *next[30];///代表指向字典树子节点
    bool flag;///代表匹配串是否结束了
    struct TIRE *fail;///指向失配后的位置
    } tire;


    2.算法的设计
    2.1函数的思路详解
    (1)向系统申请node类型的空间,并返回给node型指针
    node *creat()
    (2)判断读取的数据是否为文件尾的数据
    bool PD1(char word[]) ///判断行是否结束
    其主要思路通过对数组word的strlen(word)-1来进行判断,因为txt文档中的数据读取一行的话,行末会带’ ’,所以’ ’可以代表一行的结束
    (3)从文件中读取到链表中来构建数据。
    int get_hang(char fileopenname[MAXNS], node *head, int move, int &fflag)
    使用fgets函数从文件中读取一行中的81个字符到储存数据的链表中,然后在读取到一行结束的时候把node结构体中的flag=true,来标记结束。
    (4)输出从文件中读取到链表的内容
    void PRINTNODE(node *head) ///输出链表
    通过head来读取数据,如果遇到flag==true的就证明,该行到达了结束,输出换行,接着输出该节点的序号,然后循环。
    (5),清空函数
    void clearl(node *p)///释放链表,防止内存泄露
    void clear()///清屏函数
    (6)///菜单生成表
    void view()
    (7)针对于添加后超出活区限制,提交到文件中
    void only_insert(char strs[305], node *&head)///把第一行输出到文本中
    因为题意中表明了,会出现添加超过了活区的情况,那么我就将活区链表的第一个节点提交到文件中,并且将第一个节点经行移动。然后重新建立序号。
    (8)把修改后的活区读入文件中
    void INPUT_file(char file_sname[MAXNS], node *head)
    通过申请一个中转数组来储存第一行的数据,通过对链表的读取来储存数据,然后通过fput读入文件。
    (9),代表删除一个行区间
    其原理为

    void del_file_one(int ans1, int ans2, node *&head) ///代表删除一个区间
    采用两个指针来实现,一个指向要删除的行的前一个的节点,一个指向后一个节点,采用将前一个指针指向后一个指针来实现区间删除。
    关于删除第一个节点,直接将头指针移动到下一个行节点。就可以了。
    多出来的节点可以通过删除函数进行删除。

    (10),删除单行
    void del_file_two(int ans1, node *&head)
    原理也是采用两个两个节点来跑,一个指向要删除的行的前一个的节点,一个指向后一个节点,采用将前一个指针指向后一个指针来实现单行删除。
    原理图跟上述一样
    (11),创建AC自动机的字典树部分的节点
    tire *creat_tire()
    申请一个节点,并且将其相连的子节点==NULL
    然后把标记变成0;标记的意思是是否走到这个子匹配串的末尾。
    (12),在字典树中插入匹配子串
    一个节点下有对应的30的子指针,代表a-z,然后如果为空即代表没有这个字母。如果不为空,这代表有这个字母,假设abc,fde建立的字典树如图:


    void insert_tire(char words[], tire *root)
    思路就是对子串数组进行遍历,如果第一个节点下的对应节点为NULL的话就建立这个节点,而建立的方式有个核心,就是next【ans】,ans=words【i】-’a’;
    来获取,应用了ascii码的运算
    (13)生成fail指向
    /**
    通过构建匹配失败后的fail指针,来构建AC自动机的模式匹配树,而fail的构建涉及bfs算法,而fail的构建算法,首先先将连接于root的点的所有子节点连向root的点,再将所有非NULL的点压入队列,弹出进行操作,考虑节点失配的情况,让失配的节点p->next[i]->fail=p->fail->next[i];这个过程后就可以建立一颗带fail节点的字典树。涉及bfs,即广度优先搜索!
    而在自动机的匹配过程中就是按照生成的fail树对应匹配。即匹配失败就移动到p->next[i]->fail.

    **/
    void build_ACtire(tire *root)
    (14)查找匹配的位置
    如图:

    bool ACTIRE_search(char str[], tire *root)

    将查找串与匹配串所建立的fail树进行匹配,如果匹配失败就访问匹配失败的fail指针再次经行匹配。匹配成功就返回匹配的的字段的位置。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <queue>
    #include <vector>
    using namespace std;
    const int MAXN = 81;
    const int MAXNS = 1024;
    char file_name[MAXNS];      ///用户输入的地址
    char file_ends_name[MAXNS]; ///文本输出的地址
    char AC_TIRE_ARR[325 * 25];
    typedef struct NODE
    {
        char words[MAXN];
        struct NODE *next;
        int num;   ///代表行数
        bool flag; ///flag代表行结束
    } node;
    typedef struct TIRE
    {
        struct TIRE *next[30];
        bool flag;
        struct TIRE *fail;
    } tire;
    node *head;
    node *creat()
    {
        node *p;
        p = new node;
        memset(p->words, 0, sizeof(p->words));
        p->num = 1;
        p->flag = false;
        p->next = NULL;
        return p;
    }
    bool PD1(char word[]) ///判断行是否结束
    {
        int len = strlen(word);
        if (word[len - 1] == '
    ')
        {
            return true;
        }
        else
            return false;
    }
    int get_hang(char fileopenname[MAXNS], node *head, int move, int &fflag) ///fflag代表是否读到文件尾
    {
        FILE *fp;
        int re; ///代表字节数
        int biaoji = 0;
        re = 0;
        fp = fopen(fileopenname, "r");
        fseek(fp, move, 0);
        int number = 1; ///number代表行数
        while (fgets(head->words, 81, fp) != NULL)
        {
            re += (strlen(head->words) + 1);
            //printf("%d
    ",re);
            if (PD1(head->words))
            {
                number++;
                if (number == 21)
                {
                    fflag = 1;
                    break;
                }
                head->flag = true;
                node *p;
                p = creat();
                p->num = number;
                head->next = p;
                head = head->next;
            }
            else
            {
                node *p;
                p = creat();
                p->num = number;
                head->next = p;
                head = head->next;
            }
        }
        fclose(fp);
        return re;
    }
    void PRINTNODE(node *head) ///输出链表
    {
        if (head == NULL)
        {
            printf("error,no thing
    ");
            return;
        }
        printf("%4d ", head->num);
        while (head)
        {
            printf("%s", head->words);
            if (head->flag == true)
            {
                //printf("...
    ");
                int lens = strlen(head->words);
                if (head->words[lens - 1] != '
    ')
                    printf("
    "); ///这个是针对于添加之后的。
                if (head->next != NULL)
                    printf("%4d ", head->next->num);
            }
            head = head->next;
        }
        //puts("");
    }
    void clearl(node *p)
    {
        if (p != NULL)
        {
            clearl(p->next);
            free(p);
        }
    }
    void clear()
    {
        system("cls");
    }
    void view()
    {
        printf("
    ");
        printf("活区切换。格式:n<回车>
    ");
        printf("活区显示。格式:p<回车> 
    ");
        printf("行插入。格式:i<行号><回车><文本><回车> 
    ");
        printf("行删除。格式:d<行号 1>[ <行号 2>]<回车> 
    ");
        printf("活区多或单模式匹配。 格式:m<模式串 1>[ <模式串 2> ......]<回车>
    ");
    }
    void only_insert(char strs[305], node *&head)
    {
        node *hhead;
        hhead = head;
        int j = 0;
        char wordss[325];
        int ans;
        while (hhead->flag == false)
        {
            ans = strlen(hhead->words);
            for (int i = 0; i < ans; i++)
            {
                wordss[j] = hhead->words[i];
                j++;
                //printf("...........
    ");
            }
        }
        ans = strlen(hhead->words);
        for (int i = 0; i < ans; i++)
        {
            //printf("%c",hhead->words[i]);
            wordss[j] = hhead->words[i];
            j++;
        }
        if (wordss[j - 1] != '
    ')
            wordss[j] = '
    ';
        FILE *fp = fopen(strs, "a+");
        fputs(wordss, fp);
        fclose(fp);
        hhead = hhead->next;
        head = hhead;
    }
    void add_hang(int n, node *&head)
    {
        int j = 0;
        node *p;
        node *begins;
        node *headss = creat();
        node *heads = creat();
        begins = creat();
        p = creat();
        heads = head;
        headss = head;
        begins = p;
        p->num = n + 1;
        char str[355];
        printf("please the words 
    ");
        cin >> str;
        getchar();
        int len = strlen(str);
        for (int i = 0; i < len; i++)
        {
            p->words[j++] = str[i];
            if (j == 81)
            {
                j = 0;
                node *q;
                q = creat();
                q->num = n + 1;
                p->next = q;
                p = p->next;
            }
        }
        //p->words[j]='
    ';
        p->flag = true;
        if (n == 0)
        {
            p->next = head;
            head = p;
            headss = head;
            //printf("%s
    ",head->words);
            int numbers = 1;
            while (headss)
            {
                headss->num = numbers;
                if (headss->flag == true && headss->next != NULL)
                {
                    numbers++;
                }
                headss = headss->next;
            }
            //PRINTNODE(head);
            if (numbers > 20)
            {
                only_insert(file_ends_name, head);
            }
            node *hhead;
            hhead = creat();
            hhead = head;
            numbers = 1;
            while (hhead)
            {
                hhead->num = numbers;
                if (hhead->flag == true)
                {
                    numbers++;
                }
                hhead = hhead->next;
            }
        }
        else
        {
            while (headss->next->num != begins->num)
            {
                //printf("%d
    ",headss->next->num);
                headss = headss->next;
                if (headss->next == NULL)
                {
                    break;
                }
            }
            headss->flag = true;
            p->next = headss->next;
            headss->next = begins;
            int numbers = 1;
            while (heads)
            {
                heads->num = numbers;
                if (heads->flag == true && heads->next != NULL)
                {
                    numbers++;
                }
                heads = heads->next;
            }
            //PRINTNODE(head);
            if (numbers > 20)
            {
                only_insert(file_ends_name, head);
            }
            node *headsss;
            headsss = creat();
            headsss = head;
            numbers = 1;
            while (headsss)
            {
                headsss->num = numbers;
                if (headsss->flag == true)
                {
                    numbers++;
                }
                headsss = headsss->next;
            }
        }
    }
    void INPUT_file(char file_sname[MAXNS], node *head)
    {
        char buf[MAXN * 10];
        memset(buf, 0, sizeof(buf));
        FILE *fps = fopen(file_sname, "a+");
        int j = 0;
        while (head)
        {
            int len = strlen(head->words);
            for (int i = 0; i < len; i++)
            {
                buf[j] = head->words[i];
                j++;
            }
            if (head->flag == true && head->next == NULL)
            {
                //printf("%s
    ",buf);
                fputs(buf, fps);
                j = 0;
                memset(buf, 0, sizeof(buf));
            }
            if (head->flag == false && head->next == NULL)
            {
                fputs(buf, fps);
                j = 0;
                memset(buf, 0, sizeof(buf));
            }
            if (head->flag == true && head->next != NULL)
            {
                int lens = strlen(head->words);
                if (head->words[lens - 1] != '
    ')
                    buf[j] = '
    ';
                fputs(buf, fps);
                j = 0;
                memset(buf, 0, sizeof(buf));
            }
            head = head->next;
        }
        fclose(fps);
    }
    void Node_clear(node *s, node *h)
    {
        while (s != h)
        {
            //printf("...........
    ");
            Node_clear(s->next, h);
            delete s;
        }
    }
    void del_file_one(int ans1, int ans2, node *&head) ///代表删除一个区间
    {
        node *head1; ///代表指向前一个的指针
        head1 = creat();
        node *head2; ///代表指向后一个的指针
        head2 = creat();
        node *head3; ///释放内存空间
        head3 = creat();
        node *head4;
        head4 = creat();
        head1 = head;
        head2 = head;
        ///ans1 ans2 0 10 代表0到10都被删除
        if (ans1 != 1)
        {
            while (head1->next->num != ans1)
            {
                head1 = head1->next;
            }
            while (head2->next->num != ans2 + 1)
            {
                head2 = head2->next;
                if (head2->next == NULL)
                {
                    break;
                }
            }
            head3 = head1->next;
            head4 = head2;
            head1->next = head2->next;
            //Node_clear(head3,head2);
            /**
            以下是一个重新构造输出数据的函数
            **/
            node *heads;
            heads = creat();
            heads = head;
            int numbers = 1;
            while (heads)
            {
                heads->num = numbers;
                if (heads->flag == true)
                {
                    numbers++;
                }
                heads = heads->next;
            }
        }
        else if (ans1 == 1)
        {
            while (head2->next->num != ans2 + 1)
            {
                head2 = head2->next;
                if (head2->next == NULL)
                {
                    break;
                }
            }
            //printf("%s
    ",head2->words);
            head3 = head;
            head4 = head2;
            head2 = head2->next;
            head = head2;
            //Node_clear(head3,head4);
            node *headss;
            headss = creat();
            headss = head;
            int numbers = 1;
            while (headss)
            {
                headss->num = numbers;
                if (headss->flag == true)
                {
                    numbers++;
                }
                headss = headss->next;
            }
        }
    }
    void del_file_two(int ans1, node *&head)
    {
        if (ans1 == 1)
        {
            node *heads;
            heads = creat();
            heads = head;
            while (heads->next->num == 1)
            {
                heads = heads->next;
                if (heads->next == NULL)
                {
                    break;
                }
            }
            heads = heads->next;
            head = heads;
            node *head1;
            head1 = creat();
            head1 = head;
            int numbers = 1;
            while (head1)
            {
                head1->num = numbers;
                if (head1->flag == true)
                {
                    numbers++;
                }
                head1 = head1->next;
            }
        }
        else
        {
            int ans2 = ans1 + 1;
            node *head1;
            head1 = creat();
            head1 = head;
            node *head2;
            head2 = creat();
            head2 = head;
            while (head1->next->num != ans1)
            {
                head1 = head1->next;
                if (head1->next == NULL)
                    break;
            }
            while (head2->next->num != ans2)
            {
                head2 = head2->next;
                if (head2->next == NULL)
                {
                    break;
                }
            }
            head2 = head2->next;
            head1->next = head2;
            int nums = 1;
            node *head3;
            head3 = creat();
            head3 = head;
            while (head3)
            {
                head3->num = nums;
                if (head3->flag == true)
                    nums++;
                head3 = head3->next;
            }
        }
    }
    tire *creat_tire()
    {
        tire *p;
        p = new tire;
        p->flag = false;
        for (int i = 0; i < 30; i++)
        {
            p->next[i] = NULL;
        }
        p->fail = NULL;
        return p;
    }
    //tire *root = creat_tire();
    void insert_tire(char words[], tire *root)
    {
        int len;
        len = strlen(words);
        tire *p;
        p = root;
        for (int i = 0; i < len; i++)
        {
            int ans;
            ans = words[i] - 'a';
            //printf("%d
    ",ans);
            if (p->next[ans] == NULL)
            {
                tire *q;
                q = creat_tire();
                p->next[ans] = q;
            }
            p = p->next[ans];
        }
        p->flag = true; ///代表结束
    }
    void build_ACtire(tire *root)
    {
        tire *p = root;
        tire *q;
        queue<tire *> que;
        for (int i = 0; i < 30; i++)
        {
            if (p->next[i] != NULL)
            {
                p->next[i]->fail = root;
                que.push(p->next[i]);
            }
            else
                p->next[i] = root;
        }
        while (!que.empty())
        {
            tire *to;
            to = que.front();
            que.pop();
            for (int i = 0; i < 30; i++)
            {
                ///因为第一个模式串如果匹配失败,有可能是另一个匹配串
                ///所以应该找到另一个
                ///失配的话,就是回到root点再寻找
                if (to->next[i] != NULL)
                {
                    to->next[i]->fail = to->fail->next[i];
                    que.push(to->next[i]);
                }
                else
                    to->next[i] = to->fail->next[i];
            }
        }
    }
    bool ACTIRE_search(char str[], tire *root)
    {
        vector<int> vec;
        int len = strlen(str);
        //printf("%d
    ",len);
        tire *ans;
        ans = creat_tire();
        ans = root;
        for (int i = 0; i < len; i++)
        {
            int num = str[i] - 'a';
            if (num < 0)
                continue;
            //printf("%d...
    ",num);
            if (ans->next[num] != NULL)
            {
                ans = ans->next[num];
                //printf("%d....
    ",ans->flag);
                if (ans->flag == true)
                {
                    //if(ans==NULL)
                    //printf("............................................
    ");
                    vec.push_back(i);
                }
            }
            else
            {
                if (ans == root)
                    i++;
                else
                {
                    ans = ans->fail;
                    if (ans->flag == true)
                    {
                        vec.push_back(i);
                    }
                }
            }
        }
        if (vec.size() != 0)
        {
            for (int i = 0; i < vec.size(); i++)
            {
                printf("%d ", vec[i]);
            }
            puts("");
            return true;
        }
        return false;
    }
    int main()
    {
        int file_move = 0;
        node *p;
        int end_flag = 0;
        printf("please cin the in file_name
    ");
        cin >> file_name;
        getchar();
        printf("please cin the out file_name
    ");
        cin >> file_ends_name;
        getchar();
        while (1)
        {
            view();
            node *head;
            char s[100];
            char strs[105];
            int nums;
            gets(s);
            if (s[0] == 'n')
            {
                if (file_move == 0)
                {
                    head = creat();
                    nums = get_hang(file_name, head, file_move, end_flag);
                    if (nums == 0)
                    {
                        printf("error
    ");
                        continue;
                    }
                    file_move += nums;
                    PRINTNODE(head);
                }
                else
                {
                    INPUT_file(file_ends_name, head);
                    head = creat();
                    nums = get_hang(file_name, head, file_move, end_flag);
                    if (nums == 0)
                    {
                        printf("the file open is error
    ");
                        printf("because the file is end
    ");
                        continue;
                    }
                    file_move += nums;
                    PRINTNODE(head);
                }
            }
            if (s[0] == 'p')
            {
                PRINTNODE(head);
            }
            if (s[0] == 'i')
            {
                int ans = 0;
                int len;
                len = strlen(s);
                for (int i = 1; i < len; i++)
                {
                    if (s[i] >= '0' && s[i] <= '9')
                    {
                        ans = ans * 10 + (s[i] - '0');
                    }
                    else
                        break;
                }
                add_hang(ans, head);
            }
            if (s[0] == 'd')
            {
                int ans1, ans2;
                ans1 = 0;
                ans2 = 0;
                int i;
                int len = strlen(s);
                for (i = 1; i < len; i++)
                {
                    if (s[i] >= '0' && s[i] <= '9')
                    {
                        ans1 = ans1 * 10 + (s[i] - '0');
                    }
                    else
                        break;
                }
                if (i == len)
                {
                    del_file_two(ans1, head);
                }
                else
                {
                    for (i = i + 1; i < len; i++)
                    {
                        if (s[i] >= '0' && s[i] <= '9')
                        {
                            ans2 = ans2 * 10 + (s[i] - '0');
                        }
                        else
                            break;
                    }
                    del_file_one(ans1, ans2, head);
                }
            }
            if (s[0] == 'm')
            {
                tire *root = creat_tire();
                root = new tire;
                root->flag = false;
                for (int i = 0; i < 30; i++)
                    root->next[i] = NULL;
                root->fail = NULL;
                char hzb[MAXN * 2];
                memset(hzb, 0, sizeof(hzb));
                int hzblen = strlen(s);
                int hzbj = 0;
                for (int i = 1; i < hzblen; i++)
                {
                    if (s[i] == ' ')
                    {
                        hzb[hzbj] = '';
                        //printf("%s
    ", hzb);
                        insert_tire(hzb, root);
                        hzbj = 0;
                        continue;
                    }
                    hzb[hzbj++] = s[i];
                }
                hzb[hzbj] = '';
                //printf("%s
    ", hzb);
                insert_tire(hzb, root);
                build_ACtire(root);
                node *hzb_head;
                hzb_head = creat();
                hzb_head = head;
                memset(AC_TIRE_ARR, 0, sizeof(AC_TIRE_ARR));
                int hzbz = 0;
                while (hzb_head)
                {
                    int hhzb = strlen(hzb_head->words);
                    for (int i = 0; i < hhzb; i++)
                        if (hzb_head->words[i] != '
    ')
                            AC_TIRE_ARR[hzbz++] = hzb_head->words[i];
                    hzb_head = hzb_head->next;
                }
                AC_TIRE_ARR[hzbz] = '';
                bool hflag = ACTIRE_search(AC_TIRE_ARR, root);
                if (hflag == false)
                    printf("sorry!this is nothing
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    2014/11/25 函数
    2014/11/24 条件查询
    2、计算器
    1、winform数据库调用(基本方法)
    1、网页基础
    14、函数输出参数、递归
    13、C#简易版 推箱子游戏
    12、函数
    11、结构体、枚举
    10、特殊集合
  • 原文地址:https://www.cnblogs.com/qq136155330/p/9231565.html
Copyright © 2020-2023  润新知