Open nine-point-eight-p opened 2 years ago
基本可行。撤销和重做需要再仔细定义一下,比如复制不算操作、剪切和粘贴算操作? 内容已经足够了,不需要添加别的内容 麻烦提供一下main.cpp的代码,样例输入输出,部分分规则
main.cpp:
#include "editor.h"
#include <string>
#include <iostream>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
TextEditor t;
string opr;
while (!cin.eof())
{
cin >> opr;
if (opr == "MOVE")
{
int row, col;
cin >> row >> col;
t.moveCursor({row, col});
}
else if (opr == "SELECT")
{
int row1, col1, row2, col2;
cin >> row1 >> col1 >> row2 >> col2;
t.select({row1, col1}, {row2, col2});
}
else if (opr == "WRITE")
{
cin.get(); // Eliminate the space
cin >> t;
}
else if (opr == "ENTER")
{
t.write("\n");
}
else if (opr == "PRINT")
{
cout << t;
}
else if (opr == "DELETE")
{
t.del();
}
else if (opr == "COPY")
{
t.copy();
}
else if (opr == "CUT")
{
t.cut();
}
else if (opr == "PASTE")
{
t.paste();
}
else if (opr == "UNDO")
{
t.undo();
}
else if (opr == "REDO")
{
t.redo();
}
else if (opr == "CLEARH")
{
t.clearHistory();
}
else if (opr == "SCREEN")
{
t.screenShot();
}
else if (opr == "QUIT")
{
break;
}
else
cout << "Invalid operation" << endl;
// t.screenShot();
}
return 0;
}
缺点就是if-else太多了……
输入输出的话可以从main.cpp看出来。输入大概就像
WRITE abcde
SELECT 0 0 0 2
DELETE
UNDO
PRINT
SCREEN
输出就是对应行(不带光标)的内容或整个文本(带光标)的内容。说实话,我感觉输入(>>
)设计得有点奇怪。
关于撤销和重做:撤销和重做实际上只涉及出现写入/删除的过程。所以剪切和粘贴会被考虑到撤回的操作中,而复制不会。不过剪贴板里的东西不会因为撤销/重做而发生改变。
关于部分分,目前考虑:基础的功能是输入输出、光标操作、单行内的写入删除;然后增加多行范围的写入删除,以及复制、剪切、粘贴;最后是撤销、重做等。
我觉得可以适当减少操作。比如剪切包含复制,我觉得只留一个就行。输出所在行和screen差不多,可以考虑不要。clearHistory可能也没太大必要。 输入确实有点奇怪,而且提醒一下cin.get()在win下不一定能把换行吃掉,win换行符有两个
好的,那几个都删掉了。我觉得重载输入输出其实也没什么意思,反而更混乱了,干脆也不要了。输入只靠write,输出只靠screen。所以write我给改成了:
else if (opr == "WRITE")
{
std::string data;
cin.get(); // Clear the space
getline(cin, data);
t.write(data);
}
那个get我是想吃掉一个空格(?)因为输入的时候是这样的:
WRITE hello world
然后就把剩下的内容都算作要写入的东西。不过好像很难换行,所以我才设置了一个ENTER选项。
好的,麻烦再给下修改后的完整题面和main吧 另外能给TextEditor的实现给些限制(或者提示)吗,比如说剪贴板和命令之类的对象?
有了STL的帮助,我们可以做出很多东西。这次让我们来做一个简单的文本编辑器TextEditor
。
重要说明:它的行为和一般的文本编辑器基本一致,如windows自带的记事本、vscode等。如果有理解上的困难,可以在这些编辑器上操作一下,来观察其功能,例如光标的移动规律,撤销、重做的模式等等。
TextEditor
的基本构成有:
文本:被编辑的对象。文本可以被加载到TextEditor
内部进行操作,也可以由TextEditor
输出。
光标:指示正在进行编辑的位置,由行号和列号确定,即(row, col)
。为方便起见,一切编号从0开始,同时约定:
举例如下:
abc
hello
$(0,0)$即为a之前的位置,$(0,3)$即为c之后的位置。
具体来说,TextEditor
具有以下功能:
光标:
移动光标(moveCursor
):移动光标至指定位置。
选择(select
):接受两个位置beg
、end
,选中[beg,end)
区域,以便进一步编辑。
输入与输出:
输入部分由main.cpp代为处理,通过write写入。详见下文。
截屏(screenShot
):将目前文本编辑器处理得到的文本输出至标准输出。用*
标出光标的位置或选中区域的位置。如:
光标在$(0,2)$处:
ab*c
hello
选中区域为$[(0,0),(1,0))$:
*abc
*
hello
编辑:
write
):写入一定内容。光标随之移动。del
):若无选中区域,则删除光标位置的一个字符,光标位置不变;若有选中区域,则删除已选中的内容,同时退出选中状态,光标置于选中区域靠近开头的位置。copy
):复制选中区域的内容至剪贴板。若无选中区域,则无任何影响。paste
):若无选中区域,将剪贴板现有内容粘贴到光标处;若有选中区域,则替换之,即先删除再粘贴。若剪贴板为空,则无任何影响。关于历史的操作:
undo
):撤销一次操作。连续的写入/删除应当被一次撤销,例如:连续输入abcde,撤销时将完全删除abcde。redo
):重做一次操作。连续的写入/删除应当被一次重做,同上。注意:光标和文本受影响,而剪贴板不受影响;在撤销/重做时,粘贴不计入连续的写入,如写入abc->粘贴->写入de,则需要撤销三次才能完全回到初始状态。
main.cpp
已给定,如下:
#include "editor.h"
#include <string>
#include <iostream>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
TextEditor t;
string opr;
while (!cin.eof())
{
cin >> opr;
if (opr == "MOVE")
{
int row, col;
cin >> row >> col;
t.moveCursor({row, col});
}
else if (opr == "SELECT")
{
int row1, col1, row2, col2;
cin >> row1 >> col1 >> row2 >> col2;
t.select({row1, col1}, {row2, col2});
}
else if (opr == "WRITE")
{
std::string data;
cin.get(); // Clear the space between "WRITE" and data
getline(cin, data);
t.write(data);
}
else if (opr == "ENTER")
{
t.write("\n");
}
else if (opr == "DELETE")
{
t.del();
}
else if (opr == "COPY")
{
t.copy();
}
else if (opr == "PASTE")
{
t.paste();
}
else if (opr == "UNDO")
{
t.undo();
}
else if (opr == "REDO")
{
t.redo();
}
else if (opr == "SCREEN")
{
t.screenShot();
}
else if (opr == "QUIT")
{
break;
}
else
cout << "Invalid operation" << endl;
}
return 0;
}
请编写editor.h
,可以增加文件。将你所写的文件和makefile打包提交。
下发文件给大家参考吧,不用限制死
比如这样?
// editor.h
#pragma once
#include "command.h"
#include <vector>
#include <list>
class TextEditor {
private:
using Position = std::pair<int, int>;
std::vector<std::string> data;
std::list<Command*> cmd;
// To be filled or changed...
public:
// To be filled or changed...
};
// command.h
#pragma once
class Command {
private:
using Position = std::pair<int, int>;
Position beg, end;
// To be filled or changed...
public:
// To be filled or changed...
};
TextEditor里应该还有块剪贴板? Command里可以怎么记operation?是打算写operation和参数?这里是否有可能用继承实现不同Command,undo(TextEditor&)做成虚函数? 另外cmd的list里好像没有必要用指针,直接对象可能更方便一些吧
TextEditor里应该还有块剪贴板?
是的,的确有剪贴板。
Command里可以怎么记operation?是打算写operation和参数?这里是否有可能用继承实现不同Command,undo(TextEditor&)做成虚函数?
目前我的方法确实是通过继承实现不同的command,有execute、unexecute两个虚函数来记录行为。接口就是(TextEditor&)。如果不用指针的话,好像就没办法用虚函数了(?)
啊对,需要指针,那么Command虚函数接口也给一下吧。这部分的代码解释需要再详细一点
目前我是这么写的:
class Command {
public:
using Position = std::pair<int, int>;
using Data = std::string;
using DataSet = std::vector<Data>;
protected:
Position beg, end;
Command(Position beg, Position end);
public:
virtual ~Command() = default;
virtual void execute(TextEditor& editor) = 0;
virtual void unexecute(TextEditor& editor) = 0;
};
不过还有一些小问题,比如我还没太想好怎么处理“连续退回”这种事情;再比如昨晚发现,如果选中一块有文字的区域并写入,效果上等价于先删除再写入,但是撤销时将撤回至未删除时的情形,且处于选中状态。感觉这一块可能比较复杂,我在考虑取消“连续退回”这种东西,避免过于复杂。
这个你得对每个操作有个详细的说明,可以适当简化,不能让大家自己去看文本编辑器 总之你再考虑一下,题面细化以后我们再讨论
有了STL的帮助,我们可以做出很多东西。这次让我们来做一个简单的文本编辑器TextEditor
。
说明:它的行为和一般的文本编辑器基本一致,如windows自带的记事本、vscode等。如有困惑,可在这些编辑器上尝试以作参考,但一切以题目描述为准(因为有简化和修改)。
TextEditor
的基本构成有:
文本:被编辑的对象。文本可以被加载到TextEditor
内部进行操作,也可以由TextEditor
输出。
光标:指示正在进行编辑的位置,由行号和列号确定,即(row, col)
。为方便起见,一切编号从0开始,同时约定:
举例如下:
abc
hello
$(0,0)$即为a之前的位置,$(0,3)$即为c之后的位置。
具体来说,TextEditor
具有以下功能:
光标:
移动光标(moveCursor
):移动光标至指定位置。
选择(select
):接受两个位置beg
、end
,选中[beg,end)
区域,以便进一步编辑。
输入与输出:
输入部分由main.cpp代为处理,通过write写入。详见下文。
截屏(screenShot
):将目前文本编辑器处理得到的文本输出至标准输出。用*
标出光标的位置或选中区域的位置。如:
光标在$(0,2)$处:
ab*c
hello
选中区域为$[(0,0),(1,0))$:
*abc
*
hello
编辑:
write
):若无选中区域,则直接写入一个字符串,光标自然随之移动至写入内容的末尾;若有选中区域,则替换之,即先删除(del
)再写入。例如:// 初始
*abc
// 写入hello
hello*abc
// 初始
*ab*c
// 写入hello
hello*c
del
):若无选中区域,则删除光标位置的一个字符,光标位置不变;若有选中区域,则删除已选中的内容,同时退出选中状态,光标置于选中区域靠近开头的位置。例如:// 初始
*abc
// 删除后
*bc
// 初始
*ab*c
// 删除后
*c
copy
):复制选中区域的内容至剪贴板。若无选中区域,则无任何影响。例如:ab*c
*hello
// 执行复制,复制后的剪贴板内容如下(注意,复制了两个换行符):
c
paste
):若无选中区域,将剪贴板现有内容粘贴到光标处;若有选中区域,则替换之,即先删除再粘贴。若剪贴板为空,则无任何影响,例如:// 初始(剪贴板内容如上)
ab*c
hello
// 粘贴后
abc
*c
hello
// 初始(剪贴板内容如上)
ab*c*
hello
// 粘贴后
abc
*
hello
历史记录:
“操作”:限定为上一节中的写入、删除、粘贴,即所有可能产生写入/删除过程的操作;而复制不产生写入/删除过程,所以不包含在内。
“单元操作”:指最基本的、不包含其它操作的操作。删除始终是“单元操作”,而写入、粘贴则不一定,因为若有选中的区域则会进行替换,即先执行删除,再进行写入/粘贴;若无选中的区域,则它们都是单元操作。换言之,删除、未进行删除操作的写入、未进行删除操作的粘贴都是一次单元操作。
受撤销/重做影响的对象:光标和文本受影响,而剪贴板不受影响。例如,在实际的使用过程中,我们可以先复制一段内容,然后撤回至某一状态,再把复制的内容粘贴到此时的某个地方。在撤销的过程中,剪贴板的状态不会发生改变。
undo
):撤销一次单元操作。换言之,恢复到没有进行这次操作时的状态。redo
):重做一次单元操作。换言之,恢复到进行了这次操作时的状态。重做还有一个特点:如果在当前状态下进行了操作,则当前时间线下本状态之后的状态全部无效,也就是说不可能通过重做来达到了,因为已经进入了新的时间线。实例:
// 初始(剪贴板内容如上)
ab*c*
hello
// 粘贴后(因为有选中区域,所以这次粘贴不是单元操作)
abc
*
hello
// 撤销(因为不是单元操作,撤销时相当于连续撤销两步,
// 即先撤销纯粘贴过程,再撤销删除过程,同时恢复成选中状态)
ab*c*
hello
// 重做(同理,因为不是单元操作,所以连续进行两步,
// 即先进行删除过程,再进行粘贴过程,光标移至指定位置)
abc
*
hello
main.cpp
已给定,如下:
#include "editor.h"
#include <string>
#include <iostream>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
TextEditor t;
string opr;
while (!cin.eof())
{
cin >> opr;
if (opr == "MOVE")
{
int row, col;
cin >> row >> col;
t.moveCursor({row, col});
}
else if (opr == "SELECT")
{
int row1, col1, row2, col2;
cin >> row1 >> col1 >> row2 >> col2;
t.select({row1, col1}, {row2, col2});
}
else if (opr == "WRITE")
{
std::string data;
cin.get(); // Clear the space between "WRITE" and data
getline(cin, data);
t.write(data);
}
else if (opr == "ENTER")
{
t.enter();
}
else if (opr == "DELETE")
{
t.del();
}
else if (opr == "COPY")
{
t.copy();
}
else if (opr == "PASTE")
{
t.paste();
}
else if (opr == "UNDO")
{
t.undo();
}
else if (opr == "REDO")
{
t.redo();
}
else if (opr == "SCREEN")
{
t.screenShot();
}
else if (opr == "QUIT")
{
break;
}
else
cout << "Invalid operation" << endl;
}
return 0;
}
这里还提供一些已有代码供你参考,但你可以部分使用或不使用。
// editor.h
#pragma once
#include "command.h"
#include <vector>
#include <list>
// Do what you want to all the files...
class TextEditor {
private:
using Position = std::pair<int, int>;
std::vector<std::string> data; // 数据区
std::vector<std::string> clipboard; // 剪贴板
std::list<Command*> cmd; // 操作序列
// To be filled or changed...
public:
// To be filled or changed...
};
// command.h
#pragma once
// Do what you want to all the files...
// 操作基类
class Command {
public:
using Position = std::pair<int, int>;
Command();
virtual ~Command() = default;
virtual void execute(TextEditor& editor) = 0;
virtual void unexecute(TextEditor& editor) = 0;
};
// 写入操作
class WriteCommand : public Command {
private:
// Add some data?
public:
// Write a constructor?
void execute(TextEditor& editor) override;
void unexecute(TextEditor& editor) override;
};
请进一步编写editor.h
,也可以增加文件。将除main.cpp
以外的文件和makefile打包提交。
我觉得为啥不把现有的所有操作都当成单元操作,只要恢复到操作前状态即可?至于写入时有删除我觉得也没啥,可以认为所有写入都带删除,没有选中的话删除为空就是了
那也行……我现在觉得,记录操作的方法好像相当麻烦,也许不如直接保存状态(当然不需要保存全部的文本,保存一部分就行了),这样没准更容易恢复状态。
至于怎么保存可以让同学自己决定,接口目前这样应该没问题吧?我感觉execute和unexecute的提示还是不太清楚,这个能加点说明或者示例吗。
另外就是把修改后的题面再发一下吧。功能里面输入输出和编辑应该可以合并,输入说了两遍没有必要。
有了STL的帮助,我们可以做出很多东西。这次让我们来做一个简单的文本编辑器TextEditor
。
说明:它的行为和一般的文本编辑器基本一致,如windows自带的记事本、vscode等。如有困惑,可在这些编辑器上尝试以作参考,但一切请以题目描述为准(因为有简化和修改)。
TextEditor
的基本构成有:
文本:被编辑的对象。文本可以被加载到TextEditor
内部进行操作,也可以由TextEditor
输出。
光标:指示正在进行编辑的位置,由行号和列号确定,即(row, col)
。为方便起见,一切编号从0开始,同时约定:
举例如下:
abc
hello
$(0,0)$即为a之前的位置,$(0,3)$即为c之后的位置。
具体来说,TextEditor
具有以下功能:
创建:
TextEditor()
):创建编辑器。初始状态下,文本为空(即没有任何文本,只有1个空行),光标位置为$(0,0)$(即光标在这个空行的开头),处于非选中状态。光标:
移动光标(moveCursor
):移动光标至指定位置。
选择(select
):接受两个位置beg
、end
,选中[beg,end)
区域,以便进一步编辑。
编辑:
write
):若无选中区域,则直接写入一个字符串,光标自然随之移动至写入内容的末尾;若有选中区域,则替换之,即先删除再写入。例如:// 初始
*abc
// 写入hello
hello*abc
// 初始
*ab*c
// 写入hello
hello*c
del
):若无选中区域,则删除光标位置的一个字符,光标位置不变;若有选中区域,则删除已选中的内容,同时退出选中状态,光标置于选中区域靠近开头的位置。例如:// 初始
*abc
// 删除后
*bc
// 初始
*ab*c
// 删除后
*c
copy
):复制选中区域的内容至剪贴板。若无选中区域,则无任何影响。例如:ab*c
*hello
// 执行复制,复制后的剪贴板内容如下(注意,复制了两个换行符):
c
paste
):若无选中区域,将剪贴板现有内容粘贴到光标处;若有选中区域,则替换之,即先删除再粘贴。例如:// 初始(剪贴板内容如上)
ab*c
hello
// 粘贴后
abc
*c
hello
// 初始(剪贴板内容如上)
ab*c*
hello
// 粘贴后
abc
*
hello
screenShot
):将目前文本编辑器处理得到的文本输出至标准输出。用*
标出光标的位置或选中区域的位置。如:光标在$(0,2)$处:
ab*c
hello
选中区域为$[(0,0),(1,0))$:
*abc
*
hello
历史记录:
先做一点定义:
“状态”:包括文本的内容、光标的位置或选中的区域。剪贴板不受影响。例如,在实际的使用过程中,我们可以先复制一段内容,然后撤回至某一状态,再把复制的内容粘贴到此时的某个地方。在撤销的过程中,剪贴板的状态不会发生改变。
“操作”:限定为上一节中的写入、删除、粘贴,即所有可能产生写入/删除过程的操作;而复制不产生写入/删除过程,所以不包含在内。注意,上文所述的写入/粘贴操作有可能包含“删除”的过程,我们认为它们合起来算作一次操作。
下面是关于历史记录的功能:
undo
):撤销一次操作。换言之,恢复到没有进行这次操作时的状态,这是撤销的原则。更具体地,若进行了无选中区域的写入操作,撤销时,文本、光标还原至没有写入时的状态;若进行了有选中区域的操作,撤销时,文本还原至未被替换/删除的状态,同时恢复选中区域。
redo
):重做一次操作。换言之,恢复到进行了这次操作时的状态,这是重做的原则。重做还有一个特点:如果在当前状态下进行了任何操作,则当前时间线下本状态之后的状态全部无效,也就是说不可能通过重做来达到了,因为已经进入了新的时间线。例如,状态依次为a->b->c,随后撤销至b,这时c仍存在,可以通过重做一次得到;但假若这时进行了任一操作d,则c失效且被移除,现在的时间线是a->b->d,不可能再达到c了。
实例:
// 初始(剪贴板内容如上)
ab*c*
hello
// 粘贴后(有选中区域的操作)
abc
*
hello
// 撤销(因为有选中区域,所以恢复成选中状态)
ab*c*
hello
// 重做(回到完成粘贴的状态)
abc
*
hello
main.cpp
已给定,如下:
#include "editor.h"
#include <string>
#include <iostream>
using std::string;
using std::cin;
using std::cout;
using std::endl;
int main()
{
TextEditor t;
string opr;
while (!cin.eof())
{
cin >> opr;
if (opr == "MOVE")
{
int row, col;
cin >> row >> col;
t.moveCursor({row, col});
}
else if (opr == "SELECT")
{
int row1, col1, row2, col2;
cin >> row1 >> col1 >> row2 >> col2;
t.select({row1, col1}, {row2, col2});
}
else if (opr == "WRITE")
{
std::string data;
cin.get(); // Clear the space between "WRITE" and data
getline(cin, data);
t.write(data);
}
else if (opr == "ENTER")
{
t.enter();
}
else if (opr == "DELETE")
{
t.del();
}
else if (opr == "COPY")
{
t.copy();
}
else if (opr == "PASTE")
{
t.paste();
}
else if (opr == "UNDO")
{
t.undo();
}
else if (opr == "REDO")
{
t.redo();
}
else if (opr == "SCREEN")
{
t.screenShot();
}
else if (opr == "QUIT")
{
break;
}
else
cout << "Invalid operation" << endl;
}
return 0;
}
这里还提供一些已有代码供你参考,但你可以部分使用或不使用。这些文件里还有一些帮助性的说明。
// editor.h
#pragma once
#include "command.h"
#include <vector>
#include <list>
// Do what you want to all the files...
class TextEditor {
private:
using Position = std::pair<int, int>;
std::vector<std::string> data; // 数据区
std::vector<std::string> clipboard; // 剪贴板
std::list<Command*> cmd; // 操作序列,可参考command.h的说明
// To be filled or changed...
public:
// To be filled or changed...
};
// command.h
#pragma once
// Do what you want to all the files...
// 关于保存历史记录的提示:
// 可以通过保存操作的步骤来记录。首先从Command基类为需要的操作派生出具体的子类。
// 传入TextEditor的引用,调用unexecute函数可以对TextEditor“反向”操作,从而达到撤销后的状态;
// 调用execute函数则可以对TextEditor进行“正向”操作,从而达到重做后的状态。
// 即通过这两个函数修改TextEditor,进实现状态的转移。
// 由此,可以使用list<Command*>来储存并管理各个步骤,进而实现撤销/重做等等。
//
// 当然,也可以通过保存每次操作后文本的状态来记录。
// 此外,如有需要,可以参考memento设计模式或command设计模式。
// 操作基类
class Command {
public:
using Position = std::pair<int, int>;
Command();
virtual ~Command() = default;
virtual void execute(TextEditor& editor) = 0;
virtual void unexecute(TextEditor& editor) = 0;
};
// 写入操作
class WriteCommand : public Command {
private:
// Add some data?
public:
// Write a constructor according to the data
void execute(TextEditor& editor) override;
void unexecute(TextEditor& editor) override;
};
请进一步编写editor.h
,也可以增加文件。将除main.cpp
以外的文件和makefile打包提交。
题目是不是还没样例输入输出,需要补充一个。注意保证一个测试点是样例,并且说明部分分的设置
请将完整题面、数据(包括数据生成文件)、judger和答案程序,自行测试通过。完成之后发到邮箱 huangfei382@163.com。对于编写judger有问题可在小教员群(或找助教)讨论。
题目描述
有了STL的帮助,我们可以做出很多东西。这次让我们来做一个简单的文本编辑器
TextEditor
。重要说明:它的行为和一般的文本编辑器基本一致,如windows自带的记事本、vscode等。如果有理解上的困难,可以在这些编辑器上操作一下,来观察其功能,例如光标的移动规律,撤销、重做的模式等等。
TextEditor
的基本构成有:文本:被编辑的对象。文本可以被加载到
TextEditor
内部进行操作,也可以由TextEditor
输出。光标:指示正在进行编辑的位置,由行号和列号确定,即
(row, col)
。为方便起见,一切编号从0开始,同时约定:举例如下:
$(0,0)$即为a之前的位置,$(0,3)$即为c之后的位置。
具体来说,
TextEditor
具有以下功能:光标:
移动光标(
moveCursor
):移动光标至指定位置。选择(
select
):接受两个位置beg
、end
,选中[beg,end)
区域,以便进一步编辑。输入与输出:
输入(
operator>>
):读入一行字符串,插入到光标所在位置。输出(
operator<<
):输出光标所在行。截屏(
screenShot
):将目前文本编辑器处理得到的文本输出至标准输出。用*
标出光标的位置或选中区域的位置。如:光标在$(0,2)$处:
选中区域为$[(0,0),(1,0))$:
编辑:
write
):写入一定内容。光标随之移动。del
):若无选中区域,则删除光标位置的一个字符,光标位置不变;若有选中区域,则删除已选中的内容,同时退出选中状态,光标置于选中区域靠近开头的位置。copy
):复制选中区域的内容至剪贴板。若无选中区域,则无任何影响。cut
):剪切选中区域的内容至剪贴板,等价于先复制再删除。若无选中区域,则无任何影响。paste
):若无选中区域,将剪贴板现有内容粘贴到光标处;若有选中区域,则替换之,即先删除再粘贴。若剪贴板为空,则无任何影响。关于历史的操作:注意,光标和文本受影响,而剪贴板不受影响。
undo
):撤销一次操作。连续的写入/删除可以被一次撤销,例如:连续输入abcde,撤销时将完全删除abcde。redo
):重做一次操作。连续的写入/删除可以被一次重做,同上。clearHistory
):清空现有的历史记录。main.cpp
将会给定。请编写TextEditor.h
,可以增加文件。将你所写的文件和makefile打包提交。备注