(十七)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;
}
上一篇 下一篇

猜你喜欢

热点阅读