题目描述
记事本是 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语句进行跳转,输入的字符跳转到对应的操作。
有点像学生成绩查询输入系统的做法,但是具体的函数需要自己再写写。