TxtMonster的设计过程(一)
2005-04-20 19:07
162 查看
上次的作业刚刚做完,还没来得及总结,下一个作业又来了,真是苦恼呀!先来说说问题的描述:
[描述]
设计一个类,它能接收数据流(现水平可以用接收键盘输入来代替),数据流中会有换行符,每个新行的前导和后导空格要去除,接收到的数据流要保留,可以随时输出所有已经接收到的数据(要求分行显示),也要能按提供的行号随机输出。[输入]
abc
def
gh ij
kl (最后含两个空格,注)
mno (还没有回车换行,注)
[输出]
abc
def
gh ij
kl (末尾这两个空格不输出,注)
/**************************************/
这个题目看上去不是很难嘛,呵呵。
这个题目我要解决下面几个问题:
1、接收到的数据的保存。 按道理是要存放在文件中的,可我现在还不会文件操作,我待解决的问题还有很多,文件操作先暂放一放。我打算使用一个结构变量或类来存放所有的接收到的数据。可以采用链表来存储。我打算使用下面图所示的结构:
说明:我使用surface,line,point(面,线,点)来形容这个结构,为的是好记。
我的想法是,每次有字符压进来,就放在最左边的line中,最上面的是最近(新)的。遇到换行符,生成新的line接在最左侧。
我想,这样肯定是可以完成老师的作业的,这之所以这样做还有一个原因,就是我想利用这个结构,使自己对于指针的操作进一步熟练,我也不能判断这样做带来的后果是有益的还是有害的,也许应该使用字符数组,但我想,那样的话,存放字串的数组要设计多大是一个问题,大了可能会造成大量的浪费,小了就可能放不下了(当然我们可以在结构中放一些flag说明这个串有没有结束),我所不清楚的是,这种设计无论是在读还是在写的时候会有大量的指针运动,这会降低效率吗?真希望高手指点。不过我想,就是用数组的话,说不定我们在输出数组的时候,内部也是这样的大量指针运动的(呵呵,我不清楚)。
2、我在想的一个问题是:我设计了三个结构体,他们相扣在一起形成存放字符流的结构,这个结构中会有很多的小对象,这些对象的成员是不是应该设计成私有的?下面我还是把几个struct预写一下(什么叫预写?呵呵,我发明的,就是草稿的意思嘛)。
struct point //存储一个字符的点
{
char c;
point* next;
};
struct line //存储一个串的线,带头结点
{
point* head;
line* next;
};
struct surface //存储整个树的面,带头结点
{
line* head;
};
//然后再设计一个类,当中就使用了这个结构。
class CtxtMonster //这个类还没设计完成,起个头
{
private:
surface txt_tree;
int PrintLine(point*);
public:
CTxtMonster();
~CTxtMonster();
int InputChar(char); //向Monster压入一个字符
int OutputLine(int); //参数表示要求输出的行号,以1开始
int OutputSurface(); //输出整个结构
int Reset(); //重置整个对象
};
大家可能注意到了,这个类中的我所谓的surface结构其实就是一个指针,我倒是想,这好像是一个公主的帽子,外面挂了好多的垂珠,晃晃当当的,看上去感觉一点也不聚合。总使我产生封装差的感觉。有一点我不明白,我将txt_tree这个surface结构声明成了private,那组成这个txt_tree的三个结构会不会封装得很好呢?等写完这个程序后一定要研究研究这个问题,这里暂时先放一下。(呵呵,眼睛一眨,都有两个问题放一下了,呵呵)
一、int PrintLine(point*);的实现
int CTxtMonster::PrintLine(point* pMe)
{
if(pMe->next!=NULL)
PrintLine(pMe->next);
cout<<pMe->c;
}
说明:这是向屏幕输出一个字串,向函数传递的是line的第一个point的地址。
采用的是递归方法,这样第一个输出的应该是最下面的字符,那个字符又是第一个压进去的,正好符合顺序。
二、int InputChar(char); 的实现
int CTxtMonster::InputChar(char nosh)
{
point* pNosh;
pNosh=new point;
pNosh->c=nosh;
pNosh->next=Null;
…… (这里是将上面的pNosh插入,略)
return 0;
}
说明:这是向整个结构中传入字符。这里有一个问题,就是:我们要不要判断这个传入的字符的种类,根据不同的各类做出不同的处理?比如看是不是换行符,要是的话就产生新的line,看看是不是新一行的开始的空格,是不是重复的换行等等,如果不判断也是可以的,但这个小函数就应该变成一个内部private函数,专门用来延长line结构。采用哪一种方法呢?还是用专职的吧!因为我们写的函数应该尽量功能专一,这样函数的XX性小一点(呵呵,这里有一个词忘记了,好像是什么内聚,偶联什么的,呵呵,真是不好意思)。那么我们得做一点小的修改,将名字改成:private: int ProlongLine(char);
这样的话,这个函数要做的事是:
1、 产生一个point;
2、 用参数初始化它;
3、 把它连入相应的line;
我想应该就这么多事情吧。好了,把这段再复制过来修改一下:
int CTxtMonster::ProlongLine(char nosh)
{
point* pNosh;
pNosh=new point;
pNosh->c=nosh;
pNosh->next=NULL;
return 0;
}
这样的话,又得添加一个公共函数了,这个函数就用来负责管理输入的字符,由他决定输入的字符应该怎么处理。
三、既然这样,干脆,我们再添几个私有函数,负责下面的几项任务:
1、 产生一个新的line;(正好,在产生新的line的时候我们可以让他先去判断一下前面的line的最后是不是空格,如果是的话,先删除掉)
2、 (暂时还没想到,呵呵)
int CTxtMonster::NewLine()
{
if (txt_tree.head->head==NULL) //别担心txt_tree.head是一个NULL,
return 1; //因为在构造时就添了一个line
//先将当前line的末尾的空格去掉
while(txt_tree.head->head->c==32) //注意:这个删除空格的过程并没有检查
//是否会全部删除,在调用这个函数前要自行判断
{
point* t=NULL;
t=txt_tree.head->head->next;
delete txt_tree.head->head;
txt_tree.head->head=t;
}
line* newline=NULL;
newline=new line;
newline->head=NULL;
newline->next=NULL;
newline->next=txt_tree.head;
txt_tree.head=newline;
}
四、下面来看看构造和析构函数
构造函数还是比较方便的:
CTxtMonster::CTxtMonster()
{
txt_tree.head=NULL;
line* first_line=NULL;
first_line->head=NULL;
first_line->next=NULL;
txt_tree.head=first_line;
}
析构函数就比较麻烦了,她要遍历整个结构,看样子,还要添一个删除line的内部函数
—int DelLinePoint(line*)这个函数只是删除pkill所指的line下的所有的point
CTxtMonster::~CTxtMonster()
{
/**********************
释放所有单元
**********************/
Killme(txt_tree.head);
}
int CTxtMonster::Killme(line* pkill)
{
if(pkill->next!=NULL)
Killme(pkill->next);
DelLinePoint(pkill);
delete pkill;
return 0;
}
int CTxtMonster::DelLinePoint(line* pkill)
//这个函数只是删除pkill所指的line下的所有的point
{
while(pkill->head!=NULL)
{
point* t=NULL;
t=pkill->head;
pkill=t->next;
delete t;
}
return 0;
}
////////////////以上三个函数完成了对所有空间的收回。
[描述]
设计一个类,它能接收数据流(现水平可以用接收键盘输入来代替),数据流中会有换行符,每个新行的前导和后导空格要去除,接收到的数据流要保留,可以随时输出所有已经接收到的数据(要求分行显示),也要能按提供的行号随机输出。[输入]
abc
def
gh ij
kl (最后含两个空格,注)
mno (还没有回车换行,注)
[输出]
abc
def
gh ij
kl (末尾这两个空格不输出,注)
/**************************************/
这个题目看上去不是很难嘛,呵呵。
这个题目我要解决下面几个问题:
1、接收到的数据的保存。 按道理是要存放在文件中的,可我现在还不会文件操作,我待解决的问题还有很多,文件操作先暂放一放。我打算使用一个结构变量或类来存放所有的接收到的数据。可以采用链表来存储。我打算使用下面图所示的结构:
说明:我使用surface,line,point(面,线,点)来形容这个结构,为的是好记。
我的想法是,每次有字符压进来,就放在最左边的line中,最上面的是最近(新)的。遇到换行符,生成新的line接在最左侧。
我想,这样肯定是可以完成老师的作业的,这之所以这样做还有一个原因,就是我想利用这个结构,使自己对于指针的操作进一步熟练,我也不能判断这样做带来的后果是有益的还是有害的,也许应该使用字符数组,但我想,那样的话,存放字串的数组要设计多大是一个问题,大了可能会造成大量的浪费,小了就可能放不下了(当然我们可以在结构中放一些flag说明这个串有没有结束),我所不清楚的是,这种设计无论是在读还是在写的时候会有大量的指针运动,这会降低效率吗?真希望高手指点。不过我想,就是用数组的话,说不定我们在输出数组的时候,内部也是这样的大量指针运动的(呵呵,我不清楚)。
2、我在想的一个问题是:我设计了三个结构体,他们相扣在一起形成存放字符流的结构,这个结构中会有很多的小对象,这些对象的成员是不是应该设计成私有的?下面我还是把几个struct预写一下(什么叫预写?呵呵,我发明的,就是草稿的意思嘛)。
struct point //存储一个字符的点
{
char c;
point* next;
};
struct line //存储一个串的线,带头结点
{
point* head;
line* next;
};
struct surface //存储整个树的面,带头结点
{
line* head;
};
//然后再设计一个类,当中就使用了这个结构。
class CtxtMonster //这个类还没设计完成,起个头
{
private:
surface txt_tree;
int PrintLine(point*);
public:
CTxtMonster();
~CTxtMonster();
int InputChar(char); //向Monster压入一个字符
int OutputLine(int); //参数表示要求输出的行号,以1开始
int OutputSurface(); //输出整个结构
int Reset(); //重置整个对象
};
大家可能注意到了,这个类中的我所谓的surface结构其实就是一个指针,我倒是想,这好像是一个公主的帽子,外面挂了好多的垂珠,晃晃当当的,看上去感觉一点也不聚合。总使我产生封装差的感觉。有一点我不明白,我将txt_tree这个surface结构声明成了private,那组成这个txt_tree的三个结构会不会封装得很好呢?等写完这个程序后一定要研究研究这个问题,这里暂时先放一下。(呵呵,眼睛一眨,都有两个问题放一下了,呵呵)
一、int PrintLine(point*);的实现
int CTxtMonster::PrintLine(point* pMe)
{
if(pMe->next!=NULL)
PrintLine(pMe->next);
cout<<pMe->c;
}
说明:这是向屏幕输出一个字串,向函数传递的是line的第一个point的地址。
采用的是递归方法,这样第一个输出的应该是最下面的字符,那个字符又是第一个压进去的,正好符合顺序。
二、int InputChar(char); 的实现
int CTxtMonster::InputChar(char nosh)
{
point* pNosh;
pNosh=new point;
pNosh->c=nosh;
pNosh->next=Null;
…… (这里是将上面的pNosh插入,略)
return 0;
}
说明:这是向整个结构中传入字符。这里有一个问题,就是:我们要不要判断这个传入的字符的种类,根据不同的各类做出不同的处理?比如看是不是换行符,要是的话就产生新的line,看看是不是新一行的开始的空格,是不是重复的换行等等,如果不判断也是可以的,但这个小函数就应该变成一个内部private函数,专门用来延长line结构。采用哪一种方法呢?还是用专职的吧!因为我们写的函数应该尽量功能专一,这样函数的XX性小一点(呵呵,这里有一个词忘记了,好像是什么内聚,偶联什么的,呵呵,真是不好意思)。那么我们得做一点小的修改,将名字改成:private: int ProlongLine(char);
这样的话,这个函数要做的事是:
1、 产生一个point;
2、 用参数初始化它;
3、 把它连入相应的line;
我想应该就这么多事情吧。好了,把这段再复制过来修改一下:
int CTxtMonster::ProlongLine(char nosh)
{
point* pNosh;
pNosh=new point;
pNosh->c=nosh;
pNosh->next=NULL;
return 0;
}
这样的话,又得添加一个公共函数了,这个函数就用来负责管理输入的字符,由他决定输入的字符应该怎么处理。
三、既然这样,干脆,我们再添几个私有函数,负责下面的几项任务:
1、 产生一个新的line;(正好,在产生新的line的时候我们可以让他先去判断一下前面的line的最后是不是空格,如果是的话,先删除掉)
2、 (暂时还没想到,呵呵)
int CTxtMonster::NewLine()
{
if (txt_tree.head->head==NULL) //别担心txt_tree.head是一个NULL,
return 1; //因为在构造时就添了一个line
//先将当前line的末尾的空格去掉
while(txt_tree.head->head->c==32) //注意:这个删除空格的过程并没有检查
//是否会全部删除,在调用这个函数前要自行判断
{
point* t=NULL;
t=txt_tree.head->head->next;
delete txt_tree.head->head;
txt_tree.head->head=t;
}
line* newline=NULL;
newline=new line;
newline->head=NULL;
newline->next=NULL;
newline->next=txt_tree.head;
txt_tree.head=newline;
}
四、下面来看看构造和析构函数
构造函数还是比较方便的:
CTxtMonster::CTxtMonster()
{
txt_tree.head=NULL;
line* first_line=NULL;
first_line->head=NULL;
first_line->next=NULL;
txt_tree.head=first_line;
}
析构函数就比较麻烦了,她要遍历整个结构,看样子,还要添一个删除line的内部函数
—int DelLinePoint(line*)这个函数只是删除pkill所指的line下的所有的point
CTxtMonster::~CTxtMonster()
{
/**********************
释放所有单元
**********************/
Killme(txt_tree.head);
}
int CTxtMonster::Killme(line* pkill)
{
if(pkill->next!=NULL)
Killme(pkill->next);
DelLinePoint(pkill);
delete pkill;
return 0;
}
int CTxtMonster::DelLinePoint(line* pkill)
//这个函数只是删除pkill所指的line下的所有的point
{
while(pkill->head!=NULL)
{
point* t=NULL;
t=pkill->head;
pkill=t->next;
delete t;
}
return 0;
}
////////////////以上三个函数完成了对所有空间的收回。
相关文章推荐
- TxtMonster的设计过程(二)
- 某海量用户网站,用户拥有积分,积分可能会在使用过程中随时更新。现在要为该网站设计一种算法,在每次用户登录时显示其当前积分排名。用户最大规模为2亿;积分为非负整数,且小于100万。
- C#基础-041 设计一个玩家类,一个敌人类, 玩家可以攻击敌人,敌人可以攻击玩家,攻击点合理设计,可以通过随机数产生,模拟战斗过程
- 软工总结(四)——面向过程设计
- [转]用EA 建模设计Blog全过程
- [更新设计]跨平台物联网通讯框架ServerSuperIO 2.0 ,功能、BUG、细节说明,以及升级思考过程!
- 架构设计三之app应用的启动过程分析
- 快速入门过程与方法:设计与思路;如何学习新的知识框架,建立思维模式,熟悉应用场景体系
- MySQL的存储过程设计的例子
- 设计模式-建造模式(一碗牛肉面的制造过程)
- Asp.net开发过程中的几个模式(设计,源,cs or vb)切换
- WEB2.0时代的UE设计过程
- 一个RPC服务客户端代理中间件的设计过程的回顾
- 毕业设计过程记录六,单目单点测距
- 软件工程(四)面向过程的软件设计方法
- 最近开发一个表格报表设计器,在开发过程中遇上一个问题,希望几路高手支招
- c++设计模式之Adapter适配器模式.txt
- c++设计模式之Proxy代理模式.txt
- webWMS开发过程记录(四)- 整体设计
- Java实时多任务调度过程中的安全监控设计