簡單行編輯程序

實驗題目:簡單行編輯程序
一,題目:
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) 加入更復雜的編輯操做,如對某行進行串替換;在活區內進行模式匹配
2、要解決的問題
(1) 行插入。
(2)行刪除。
(3)活區切換。
(4)活區顯示。
附加:
(5)在活區內進行多或單模式匹配
3、算法基本思想描述:
對於題目的要求,在進行活區切換及顯示,行插入,行刪除,模式匹配都要求涉及鏈表,因此對鏈表進行的基本操做在課設中有所體現,而在附加功能中,使用了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創建的字典樹如圖:node


4、設計
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;ios


2.算法的設計
2.1函數的思路詳解
(1)向系統申請node類型的空間,並返回給node型指針
node *creat()
(2)判斷讀取的數據是否爲文件尾的數據
bool PD1(char word[]) ///判斷行是否結束
其主要思路經過對數組word的strlen(word)-1來進行判斷,由於txt文檔中的數據讀取一行的話,行末會帶’\n’,因此’\n’能夠表明一行的結束
(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)ui

將查找串與匹配串所創建的fail樹進行匹配,若是匹配失敗就訪問匹配失敗的fail指針再次經行匹配。匹配成功就返回匹配的的字段的位置。this

#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] == '\n')
    {
        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\n",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\n");
        return;
    }
    printf("%4d ", head->num);
    while (head)
    {
        printf("%s", head->words);
        if (head->flag == true)
        {
            //printf("...\n");
            int lens = strlen(head->words);
            if (head->words[lens - 1] != '\n')
                printf("\n"); ///這個是針對於添加以後的。
            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("\n");
    printf("活區切換。格式:n<回車>\n");
    printf("活區顯示。格式:p<回車> \n");
    printf("行插入。格式:i<行號><回車><文本><回車> \n");
    printf("行刪除。格式:d<行號 1>[ <行號 2>]<回車> \n");
    printf("活區多或單模式匹配。 格式:m<模式串 1>[ <模式串 2> ......]<回車>\n");
}
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("...........\n");
        }
    }
    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] != '\n')
        wordss[j] = '\n';
    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 \n");
    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]='\n';
    p->flag = true;
    if (n == 0)
    {
        p->next = head;
        head = p;
        headss = head;
        //printf("%s\n",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\n",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\n",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] != '\n')
                buf[j] = '\n';
            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("...........\n");
        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\n",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\n",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\n",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...\n",num);
        if (ans->next[num] != NULL)
        {
            ans = ans->next[num];
            //printf("%d....\n",ans->flag);
            if (ans->flag == true)
            {
                //if(ans==NULL)
                //printf("............................................\n");
                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\n");
    cin >> file_name;
    getchar();
    printf("please cin the out file_name\n");
    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\n");
                    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\n");
                    printf("because the file is end\n");
                    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] = '\0';
                    //printf("%s\n", hzb);
                    insert_tire(hzb, root);
                    hzbj = 0;
                    continue;
                }
                hzb[hzbj++] = s[i];
            }
            hzb[hzbj] = '\0';
            //printf("%s\n", 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] != '\n')
                        AC_TIRE_ARR[hzbz++] = hzb_head->words[i];
                hzb_head = hzb_head->next;
            }
            AC_TIRE_ARR[hzbz] = '\0';
            bool hflag = ACTIRE_search(AC_TIRE_ARR, root);
            if (hflag == false)
                printf("sorry!this is nothing\n");
        }
    }
    return 0;
}
相關文章
相關標籤/搜索