(十七)C++篇-自定义类(二)
2022-06-28 本文已影响0人
GoodTekken
扩展 Screen 类以包含 move、set 和 display 操作:
myScreen.move(4,0).set('#').display(cout);
测试代码:
#include <iostream>
#include <string>
using namespace std;
class Screen
{
public:
typedef string::size_type index;
char get() const{return contents[cursor];}
inline char get(index ht,index wd) const;
index get_cursor() const;
Screen(index hght,index wdth,const string &cntnts);
Screen& move(index r,index c);
Screen& set(char);
Screen& display(ostream &os);
private:
std::string contents;
index cursor;
index height,width;
};
Screen::Screen(index hght,index wdth,const string &cntnts):contents(cntnts),cursor(0),height(hght),width(wdth)
{
}
char Screen::get(index r,index c) const
{
index row=r*width;
return contents[row + c];
}
inline Screen::index Screen::get_cursor() const
{
return cursor;
}
Screen& Screen::set(char c)
{
contents[cursor] = c;
return *this;
}
Screen& Screen::move(index r,index c)
{
index row=r*width;
cursor=row+c;
return *this;
}
Screen& Screen::display(ostream &os)
{
os<<contents;
return *this;
}
int main()
{
Screen myScreen(5,6,"aaaaa\naaaaa\naaaaa\naaaaa\naaaaa\n");
myScreen.move(4,0).set('#').display(cout);
return 0;
}
输出结果:
tekken@tekken:~/C++WS$ ./a.out
aaaaa
aaaaa
aaaaa
aaaaa
#aaaa
这个解决方法已满足题目提出的要求,但存在一些缺陷:
(1)创建Screen对象时必须给出表示整个屏幕内容的字符串,即使有些位置上没有内容。
解决:
//修改构造函数
Screen::Screen(index hght,index wdth,const string &cntnts = ""):contents(cntnts),cursor(0),height(hght),width(wdth)
{
//将整个屏幕内容置为空格
contents.assign(hght*wdth,' ');
//用形参string对象的内容设置屏幕的相应字符
if(cntnts.size()!=0)
contents.replace(0,cntnts.size(),cntnts);
}
(2)显示的屏幕内容没有恰当地分行,而是连续显示,因此(4,0)位置上的‘#’,在实际显示时不一定正好在屏幕的(4,0)位置,显示结果较差。
解决:
Screen& Screen::display(ostream &os)
{
string::size_type index =0;
while(index !=contents.size())
{
os<<contents[index];
if((index+1)%width==0)
{
os<<'\n';
}
++index;
}
return *this;
}
(3)如果创建的Screen对象是一个const对象,则不能使用display函数进行显示。(因为const对象只能显示const成员)。
解决:
在Screen类定义体中增加如下函数声明
const Screen& display(ostream &os) const;
并在Screen类定义体外增加函数的定义
const Screen& Screen::display(ostream &os) const
{
string::size_type index =0;
while(index !=contents.size())
{
os<<contents[index];
if((index+1)%width==0)
{
os<<'\n';
}
++index;
}
return *this;
}
(4)如果move操作的目的位置超出了屏幕的边界,会出现运行时错误。
解决:
对move操作的行和列标号进行检查避免操作越界。
Screen& Screen::move(index r,index c)
{
//行,列号均从0开始
if(r>=height||r>=width)
{
cerr<<"invalid row or column"<<endl;
throw EXIT_FAILURE;
}
index row=r*width;
cursor=row+c;
return *this;
}
因此,优化后的完成代码如下:
#include <iostream>
#include <string>
using namespace std;
class Screen
{
public:
typedef string::size_type index;
char get() const{return contents[cursor];}
inline char get(index ht,index wd) const;
index get_cursor() const;
Screen(index hght,index wdth,const string &cntnts);
Screen& move(index r,index c);
Screen& set(char);
Screen& display(ostream &os);
const Screen& display(ostream &os) const;
private:
std::string contents;
index cursor;
index height,width;
};
Screen::Screen(index hght,index wdth,const string &cntnts = ""):contents(cntnts),cursor(0),height(hght),width(wdth)
{
//将整个屏幕内容置为空格
contents.assign(hght*wdth,' ');
//用形参string对象的内容设置屏幕的相应字符
if(cntnts.size()!=0)
contents.replace(0,cntnts.size(),cntnts);
}
char Screen::get(index r,index c) const
{
index row=r*width;
return contents[row + c];
}
inline Screen::index Screen::get_cursor() const
{
return cursor;
}
Screen& Screen::set(char c)
{
contents[cursor] = c;
return *this;
}
Screen& Screen::move(index r,index c)
{
//行,列号均从0开始
if(r>=height||c>=width)
{
cerr<<"invalid row or column"<<endl;
cerr<<EXIT_FAILURE<<endl;
throw EXIT_FAILURE;
}
index row=r*width;
cursor=row+c;
return *this;
}
Screen& Screen::display(ostream &os)
{
string::size_type index =0;
while(index !=contents.size())
{
os<<contents[index];
if((index+1)%width==0)
{
os<<'\n';
}
++index;
}
return *this;
}
const Screen& Screen::display(ostream &os) const
{
string::size_type index =0;
while(index !=contents.size())
{
os<<contents[index];
if((index+1)%width==0)
{
os<<'\n';
}
++index;
}
return *this;
}
int main()
{
Screen myScreen(5,6,"aaaaa\naaaaa\naaaaa\naaaaa\naaaaa\n");
myScreen.move(3,7).set('e').display(cout);
return 0;
}