五月模拟 : 记事本

本文档描述了一个Windows平台下经典文本编辑器——记事本的操作流程,包括光标移动、输入、删除等操作。此外,还详细解释了粘滞功能的工作原理,以及查找、字数统计、复制和打印等高级功能。通过一系列示例,阐述了如何在不同状态下执行这些操作。
摘要由CSDN通过智能技术生成

题目描述

记事本是 Windows 平台下一款经典的文本编辑器,其存储文件的扩展名为 .txt,文件属性没有任何格式标签或者风格,所以相当适合在 DOS 环境中编辑。

在本题中,可能会用到的按键如下图所示:
在这里插入图片描述

光标移动

光标表示当前要进行输入等操作的位置,在本题中,我们假设所有字符都是等宽的。

光标的位置可以用行列坐标来描述,光标所在的行和列均从1开始,例如:
在这里插入图片描述

以下操作可以进行光标的移动,使用 MOVE 输入相关的操作,其中 表示指令,可以使用以下字符串代替:

Home:把光标移动到当前行的开头。
End:把光标移动到当前行的末尾。
Up:光标移动到上一行的相同列。
若当前为第一行,则不进行任何操作。
若上一行的列数小于当前光标的列数,则将光标移动到上一行的末尾。
Down:光标移动到下一行的相同列。
若当前为最后一行,则不进行任何操作。
若下一行的列数小于当前光标的列数,则将光标移动到下一行的末尾。
Left:光标左移一位。
若当前光标位于记事本开始,则不进行任何操作。
若当前光标处于某一行的开头,则将光标移动到上一行的末尾。
Right:光标右移一位。
若当前光标位于记事本末尾,则不进行任何操作。
若当前光标处于某一行的末尾,则将光标移动到下一行的开头。
输入

以下操作可以在光标后进行输入,使用 INSERT 输入相关的操作,其中 表示指令,可以使用以下字符串代替:

Char :输入一个字符,其中 是输入的字符。

可能是一下字符中的任意一个:
注:下列字符中不包含空格与换行符。
`1234567890-=~!@#$%^&*()_+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;'ASDFGHJKL:"zxcvbnm,./ZXCVBNM<>?
例如:INSERT Char a 表示在当前光标后插入 a 字符。
Enter:输入换行符,并进行换行。

Space:输入空格。

Paste:在当前光标后,插入粘贴板中的内容,若粘贴板中无内容,则忽略当前操作。

删除

以下操作可以删除记事本中的内容,使用 REMOVE 输入相关的操作,其中 表示指令,可以使用以下字符串代替:

Del:删除当前光标位置之后的一个字符。
若该字符为换行符,则当前行与下一行合并为一行。
若当前光标在文件末尾,则忽略当前操作。
Backspace:删除当前光标位置之前的一个字符。
若该字符为换行符,则当前行与上一行合并为一行。
若当前光标在文件开头,则忽略当前操作。
粘滞功能(分数占比 24分)

输入SHIFT指令,可以启动或关闭粘滞功能。

开始时粘滞功能默认为关闭状态,之后每次点击:

若当前为启动状态,则关闭;
若当前为关闭状态,则启动。
粘滞功能启动时,记录当前的光标位置为 记录点。

粘滞功能关闭时,若此时的光标位置与 记录点 的位置不同,则进入选中状态。

粘滞功能启动后,直到功能关闭前,不会对记事本进行除光标移动外的任何操作。

当进入选中状态后,通过记录点与当前光标,可以唯一的确定一段内容,现令记录点与光标之间的所有字符(包括换行符)为 选中字段。

例如,记录点位于第1行第2列,光标位于第2行第4列时,选中字段如下图所示:

在这里插入图片描述

当前 处于选中状态 时,对于不同的情况,需要按照序号依次执行以下操作:

若进行光标移动:

退出选中状态;
尝试进行光标的移动(无论光标最终是否移动,都会退出选中状态)。
若进行输入:

将选中内容替换为输入内容;
退出选中状态。
若进行删除:

删除当前选中内容;
退出选中状态。
若再次启动粘滞功能:退出选中状态,但保留上一次选中字段的 记录点 作为当前记录点。

若进行查找,字数统计,复制,打印操作,则在操作后仍然保持选中状态。

查找

输入FIND 指令,进行字符串查找,其中 为输入的要查找的字符串,该字符串中不包含空格与换行符。

执行该指令时,要根据当前是否处于选中状态做不同的处理:

若当前处于选中状态:查找输入字符串在选中字段中的出现次数并输出。
否则:查找输入字符串在当前记事本中的出现次数并输出。
例如:当前没有选中的内容,且记事本中的内容为 ababa,若执行 FIND aba,则应当输出2,分别在第1列与第3列出现过。

字数统计

输入COUNT 指令,进行字数统计。

执行该指令时,要根据当前是否处于选中状态做不同的处理:

若当前处于选中状态:输出当前选中字段中的可见字符(不包括空格与换行符)的数量。
否则:输出当前文档中可见字符(不包括空格与换行符)的数量。
复制

输入COPY指令,进行复制操作。

执行该指令时,要根据当前是否处于选中状态做不同的处理:

若当前处于选中状态:复制选中字段到粘贴板;
否则,
若当前行不为空:复制当前行的内容(不包括换行符)到粘贴板;
否则:忽略当前操作。
打印

输入PRINT 指令,输出当前的记事本中的全部内容,并在之后输出一个换行符。

输入格式

输入包含
n
+
1
n+1 行。
第一行包含一个整数
n
n,表示接下来指令的数量。
接下来
n
n 行,每行一条指令,格式形如题目描述中的叙述。

输出格式

对于需要输出的指令,进行相应的输出。
若为 FIND 与 COUNT 操作,输出一行表示相应的数字。
若为 PRINT操作,则输出若干行,表示记事本的当前内容,并在之后输出一个换行。

请注意:所有的输出不要有多余的空格。

测试样例

样例输入

20
INSERT Char #
INSERT Enter
INSERT Char C
INSERT Enter
INSERT Space
INSERT Char _
INSERT Char _
PRINT
INSERT Char >
INSERT Enter
INSERT Char h
INSERT Char h
INSERT Char h
INSERT Enter
PRINT
COUNT
FIND __
REMOVE Del
REMOVE Backspace
PRINT

样例输出

C
__

C
__>
hhh

8
1

C
__>
hhh
数据规模

对于
100
%
100% 的测试数据,
1

n

5000
1≤n≤5000。

不同测试点所包含的功能不同,其具体情况如下表所示。
在这里插入图片描述

#include <iostream>
#include <list>
#include <string>
using std::list;
typedef std::string String;

list<char> mainContext;

typedef long long un;

bool sel_ing = false;
bool sel_ed = false;
list<char>::iterator sel_p;
list<char>::iterator sel_p2;
un sel_length = 0;

bool running = true;

list<char>::iterator cursor;

String clipboard;
bool emptyClipB = true;

enum IN_T {EM, ENTER, SPACE};

void init()
{
    cursor = mainContext.begin();
}

void del_sel();

void insert(IN_T it, char c)
{
    if (sel_ing) return;
    if (sel_ed)
    {
        del_sel();
    }
    if (it == ENTER) c = '\n';
    if (it == SPACE) c = ' ';
    cursor = mainContext.insert(cursor, c);
    cursor++;
}

void paste()
{
    if (sel_ing || clipboard.size() == 0) return;
    if (sel_ed)
    {
        del_sel();
    }
    for (auto c : clipboard)
    {
        insert(EM, c);
    }
}

bool left()
{
    if (sel_ed) sel_ed = false;
    if (cursor != mainContext.begin())
        cursor--;
    else return false;
    sel_length--;
    return true;
}

bool right()
{
    if (sel_ed) sel_ed = false;
    if (cursor != mainContext.end())
        cursor++;
    else return false;
    sel_length++;
    return true;
}

un home()
{
    list<char>::iterator cc = cursor;
    if (sel_ed) sel_ed = false;
    un t = 0;
    if (*(--cc) != '\n')
        t += left();
    else return t;
    while (*(--cc) != '\n' && left()) { t++; }
    return t;
}

un end()
{
    list<char>::iterator cc = cursor;
    if (sel_ed) sel_ed = false;
    un t = 0;
    if (*(cc++) != '\n')
        t += right();
    else return t;
    while (*(cc++) != '\n' && right()) { t++; }
    return t;
}

void up()
{
    un ind = home();
    left();
    home();
    while (ind > 0 && *cursor != '\n')
    {
        right();
        ind--;
    }
}

void down()
{
    un ind = home();
    end();
    if (!right())
        home();
    while (ind > 0 && *cursor != '\n')
    {
        right();
        ind--;
    }
}

void del(bool mask = true);

void del_sel()
{
    if (sel_ed)
    {
        cursor = sel_p;
        for (un i = 0; i < std::abs(sel_length); i++)
        {
            del(false);
        }
    }
    sel_ed = false;
}

void del(bool mask)
{
    if (sel_ing) return;
    if (sel_ed && mask)
        return del_sel();
    if (cursor != mainContext.end())
        cursor = mainContext.erase(cursor);
}

void backspace()
{
    if (sel_ing) return;
    if (sel_ed)
        return del_sel();
    if (left())
        del();
}

void print(bool end = false)
{
    bool preisln = false;
    if (end) std::cout << "\n<<\n";
    for (list<char>::iterator it = mainContext.begin(); it != mainContext.end(); it++)
    {
        if (cursor == it && end)
            std::cout << "|";
        if (sel_p == it && sel_ed && end)
            std::cout << "{";
        if (sel_p == it && sel_ing && end)
            std::cout << "^";
        if (sel_p2 == it && sel_ed && end)
            std::cout << "}";

        std::cout << *it;
        preisln = *it == '\n';
    }
    
    if (cursor == mainContext.end() && end) std::cout << "|";
    if (sel_p == mainContext.end() && sel_ed && end) std::cout << "{";
    if (sel_p == mainContext.end() && sel_ing && end) std::cout << "^";
    if (sel_p2 == mainContext.end() && sel_ed && end) std::cout << "}";
    if (!preisln) std::cout << std::endl;
    if (end)
        std::cout << "\n>>" << " S L " << sel_length << " |" << "\n";
}

int find(String s)
{
    un t = 0;
    list<char>::iterator fl = mainContext.begin(), fr = mainContext.end();
    if (sel_ed)
    {
        fl = sel_p;
        fr = sel_p2;
    }
    while (fl != fr)
    {
        bool same = true;
        list<char>::iterator it = fl;
        for (int i = 0; i < s.size(); i++)
        {
            if (s[i] != *it)
            {
                same = false;
                break;
            }
            it++;
        }
        t += same;
        fl++;
    }
    return t;
}

void copy()
{
    if (sel_ed)
    {
        list<char>::iterator it = sel_p;
        clipboard = "";
        while (it != sel_p2)
        {
            clipboard.push_back(*it);
            it++;
        }
    }
    else
    {
        un pos = home();
        String backup = clipboard;
        list<char>::iterator cl, cr;
        cl = cursor;
        end();
        cr = cursor;
        clipboard = "";
        while (cl != cr)
        {
            clipboard.push_back(*cl);
            cl++;
        }
        if (clipboard.size() == 0)
            clipboard = backup;
        home();
        for (un i = 0; i < pos; i++)
        {
            right();
        }
    }
}

un count()
{
    un t = 0;
    list<char>::iterator fl = mainContext.begin(), fr = mainContext.end();
    if (sel_ed)
    {
        fl = sel_p;
        fr = sel_p2;
    }
    while (fl != fr)
    {
        if (*fl != ' ' && *fl != '\n')
            t++;
        fl++;
    }
    return t;
}

void base(String s, un c)
{
    for (auto i : s)
    {
        insert(EM, i);
    }
    for (un i = 0; i < c; i++)
    {
        left();
    }
}
void run();

int main()
{
    un NN = 0;
    std::cin >> NN;
    // std::cout << " well start " << std::endl;
    init();
    // base("apple pen, be pen.\nyou are welcome.\n oh!!!", 13);
    // print(true);
    while (NN--)
        run();
    return 0;
}

void run()
{
    String cmd, subcmd;
    std::cin >> cmd;
    if (cmd[0] == 'M')
    {
        std::cin >> subcmd;
        if (subcmd[0] == 'L')
        {
            left();
        }
        if (subcmd[0] == 'R')
        {
            right();
        }
        if (subcmd[0] == 'H')
        {
            home();
        }
        if (subcmd[0] == 'E')
        {
            end();
        }
        if (subcmd[0] == 'U')
        {
            up();
        }
        if (subcmd[0] == 'D')
        {
            down();
        }
    }
    if (cmd[0] == 'I')
    {
        std::cin >> subcmd;
        if (subcmd[0] == 'C')
        {
            char c;
            std::cin >> c;
            insert(EM, c);
        }
        if (subcmd[0] == 'E')
        {
            insert(ENTER, 0);
        }
        if (subcmd[0] == 'S')
        {
            insert(SPACE, 0);
        }
        if (subcmd[0] == 'P')
        {
            paste();
        }
    }
    if (cmd[0] == 'R')
    {
        std::cin >> subcmd;
        if (subcmd[0] == 'D')
        {
            del();
        }
        if (subcmd[0] == 'B')
        {
            backspace();
        }
    }
    if (cmd[0] == 'S')
    {

        if (sel_ing)
        {
            sel_ing = false;
            sel_p2 = cursor;
            if (sel_length < 0)
            {
                std::swap(sel_p, sel_p2);
            }
            if (sel_length != 0)
                sel_ed = true;
            else
                sel_ed = false;
        }
        else if (!sel_ed)
        {
            sel_ing = true;
            sel_ed = false;
            sel_p = cursor;
            sel_length = 0;
        }
        else
        {
            sel_ing = true;
            sel_ed = false;
            if (sel_length < 0)
            {
                std::swap(sel_p, sel_p2);
            }
        }
    }
    if (cmd[0] == 'X')
    {
        std::cin >> subcmd;
        if (subcmd[0] == 'S')
        {
            if (sel_ed)
            {
                list<char>::iterator it = sel_p;
                std::cout << "{{";
                while (it != sel_p2)
                {
                    std::cout << *it;
                    it++;
                }
                std::cout << "}}\n";
            }
        }
    }
    if (cmd[0] == 'F')
    {
        std::cin >> subcmd;
        std::cout << find(subcmd) << std::endl;
    }
    if (cmd[0] == 'C' && cmd[1] == 'O' && cmd[2] == 'U')
    {
        std::cout << count() << std::endl;
    }
    if (cmd[0] == 'Q')
    {
        running = false;
    }
    if (cmd[0] == 'C' && cmd[1] == 'O' && cmd[2] == 'P')
    {
        copy();
    }
    if (cmd[0] == 'P')
    {
        print();
    }
    // print(true);
}

在这里插入图片描述

有这些操作,把他们分别写到函数里,
在这里插入图片描述
用代码描述他们的要求:
在这里插入图片描述
用if语句进行跳转,输入的字符跳转到对应的操作。
在这里插入图片描述
有点像学生成绩查询输入系统的做法,但是具体的函数需要自己再写写。

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值