编码editor应用程序
一旦你定义了公共界接口,即使你尚未实现buffer类或适当的内部表示方式,你也可以自由返回并编写编辑器应用程序。编写编辑器应用程序时,唯一重要的考虑因素是你要假设每个操作都执行。在这个层次上,实施细节是不重要的。
只要你限制在我们前面提到过的六个基本命令,编写程序就比较简单。所有程序必须构建一个新的EditorBuffer对象,然后输入一个循环,读取一系列编辑器命令。 每当用户输入命令时,程序只需查看命令名称中的第一个字符,并通过从buffer接口调用适当的方法来执行所请求的操作。编辑器的代码如下图所示:
#include <iostream>
#include <cctype>
#include <string>
#include "buffer.h"
using namespace std;
/*函数声明*/
void executeCommand(EditorBuffer & buffer, string line);
/*主函数*/
int main(){
EditorBuffer buffer;
while(true){
cout << "*";
string cmd;
getline(cin,cmd);
if (cmd != "") executeCommand(buffer, cmd);
buffer.showContents();
}
return 0;
}
/*
*这个函数执行要执行的命令
*/
void executeCommand(EditorBuffer & buffer, string line){
switch(touuper(line[0])){
case 'I': for(int i = 1; i < line.length(); i++){
buffer.insertCharacter(line[i]);
}
break;
case 'D': buffer.deleteCharacter(); break;
case 'F': buffer.moveCursorForward(); break;
case 'B': buffer.moveCursorBackward(); break;
case 'J': buffer.moveCursorToStart(); break;
case 'Z': buffer.moveCursorToEnd(); break;
case 'Q': exit(0);
default: cout << "Illegal command" << endl; break;
}
}
一个基于数组的实现
如上一篇文章所述,buffer的实现一个可能的表示形式是字符数组。虽然这种设计不是代表编辑器缓冲区的唯一选择,但它仍然是一个有用的起点。毕竟,缓冲区中的字符形成一个有序的均匀序列,这是一个传统上使用数组的数据类型。但是,该数组必须动态分配,以便随着缓冲区中的字符数量的增加而扩展。
定义私有数据结构
在许多方面,基于数组的编辑器缓冲区的底层表示方式类似于第11章中用于CharStack类的底层表示。CharStack类定义了三个实例变量:指向包含元素的动态数组的指针,该数组的容量,和字符数。对于基于数组的缓冲区,我们需要相同的实例变量,我们可以将count变量的名称更改为长度,因为常规的是说明缓冲区的长度。除了这些变量之外,EditorBuffer类的私有数据还必须包含一个表示当前游标位置的实例变量。因为游标是一个字符位置,您可以通过在EditorBuffer类的私有部分中包含另一个称为cursor的实例变量来表示它。光标的所处位置表示将插入任何新字符的字符位置,因此光标值为0表示缓冲区的开头。类似地,如果光标的值等于length的长度,则光标位于缓冲区的末尾。
下图显示了基于数组的实现的bufferpriv.h文件。给定这个设计,一个缓冲区包含
将如下所示:
所以其私有数据结构如下:
private:
/* 实例化变量 */
char *array; /* 动态字符数组 */
int capacity; /* 分配数组空间 */
int length; /* buffer中的字符数 */
int cursor; /* 字符之后的游标 */
/* 使得复制buffer合法 */
EditorBuffer(const EditorBuffer & value) { }
const EditorBuffer & operator=(const EditorBuffer & rhs) { return *this; }
/* 私有方法声明 */
void expandCapacity();