Hello, i got stuck again. When i read the text it all makes sense,
but putting it all to use is a different story.:zzz: Accelerated C++ excersise 15-4:

15-4. Add an operation to reframe a Picture, which changes the frame characters. The operation should change all of the frames in the interior picture.

Where and how should i store the characters for the frame? Ive managed to change the outer frame characters, but not the inner ones as they are made from different objects that hold different characters, or something like that.:P This code however doesnt contain the solutions i have tried out.

I would be very grateful if anyone could help me out here, i hate to leave things undone, especially if its something i couldnt understand.

#ifndef GUARD_Picture_info
#define GUARD_Picture_info

#include "stdafx.h"
#include "Ptr.hpp" // handle class
#include <string>
#include <vector>
#include <iostream>

class Picture;
class Pic_base {
	friend std::ostream& operator<<(std::ostream&, const Picture&);
	friend class Frame_Pic;
	friend class HCat_Pic;
	friend class VCat_Pic;
	friend class String_Pic;
	// no public interface
	typedef std::vector<std::string>::size_type ht_sz;
	typedef std::string::size_type wd_sz;
	// this class is an abstract base class
	virtual wd_sz width() const = 0;
	virtual ht_sz height() const = 0;
	virtual void display(std::ostream&, ht_sz, bool) const = 0;
	protected:
	static void pad(std::ostream& os, wd_sz beg, wd_sz end) {
		while (beg != end) {
		os << " ";
		++beg;
		}
	}
};
class Picture {
	friend std::ostream& operator<<(std::ostream&, const Picture&);
	friend Picture frame(const Picture&);
	friend Picture hcat(const Picture&, const Picture&);
	friend Picture vcat(const Picture&, const Picture&);
	public:
	Picture(const std::vector<std::string>& =
	std::vector<std::string>());
	private:
	Picture(Pic_base* ptr): p(ptr) { }
	Ptr<Pic_base> p;
};

class String_Pic: public Pic_base {
	friend class Picture;
	std::vector<std::string> data;
	String_Pic(const std::vector<std::string>& v): data(v) { }
	ht_sz height() const { return data.size(); }
	wd_sz width() const;
	void display(std::ostream&, ht_sz, bool) const;
};
class Frame_Pic: public Pic_base {
	friend Picture frame(const Picture&);
	Ptr<Pic_base> p;
	Frame_Pic(const Ptr<Pic_base>& pic): p(pic) { }
	wd_sz width() const { return p->width() + 4; }
	ht_sz height() const { return p->height() + 4; }
	void display(std::ostream&, ht_sz, bool) const;
};
class VCat_Pic: public Pic_base {
	friend Picture vcat(const Picture&, const Picture&);
	Ptr<Pic_base> top, bottom;
	VCat_Pic(const Ptr<Pic_base>& t, const Ptr<Pic_base>& b):
	top(t), bottom(b) { }
	wd_sz width() const { return std::max(top->width(), bottom->width()); }
	ht_sz height() const { return top->height() + bottom->height(); }
	void display(std::ostream&, ht_sz, bool) const;
};
class HCat_Pic: public Pic_base {
	friend Picture hcat(const Picture&, const Picture&);
	Ptr<Pic_base> left, right;
	HCat_Pic(const Ptr<Pic_base>& l, const Ptr<Pic_base>& r):
	left(l), right(r) { }
	wd_sz width() const { return left->width() + right->width(); }
	ht_sz height() const { return std::max(left->height(), right->height()); }
	void display(std::ostream&, ht_sz, bool) const;
};

//------------------------------ "Picture.cpp"

using std::ostream; using std::endl; using std::max; using std::string;
Picture::Picture(const std::vector<std::string>& v):p(new String_Pic(v)) { }
Picture frame(const Picture& pic) { return new Frame_Pic(pic.p); }
Picture vcat(const Picture& t, const Picture& b) { return new VCat_Pic(t.p, b.p); }
Picture hcat(const Picture& l, const Picture& r) { return new HCat_Pic(l.p, r.p); }

ostream& operator<<(ostream& os, const Picture& picture)
{
	const Pic_base::ht_sz ht = picture.p->height();
	for (Pic_base::ht_sz i = 0; i != ht; ++i) {
		picture.p->display(os, i, false);
		os << endl;
	}
return os;
};

Pic_base::wd_sz String_Pic::width() const {
	Pic_base::wd_sz n = 0;
	for (Pic_base::ht_sz i = 0; i != data.size(); ++i)
	n = max(n, data[i].size());
return n;
}

void String_Pic::display(ostream& os, ht_sz row, bool do_pad) const
{
	wd_sz start = 0;
	// write the row if we're still in range
	if (row < height()) {
	os << data[row];
	start = data[row].size();
}
	// pad the output if necessary
	if (do_pad)
	pad(os, start, width());
}

void VCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const
{
	wd_sz w = 0;
	if (row < top->height()) {
		// we are in the top subpicture
		top->display(os, row, do_pad);
		w = top->width();
	} else if (row < height()) {
		// we are in the bottom subpicture
		bottom->display(os, row - top->height(), do_pad);
		w = bottom->width();
	}
	if (do_pad)
	pad(os, w, width());
}

void HCat_Pic::display(ostream& os, ht_sz row, bool do_pad) const
{
	left->display(os, row, do_pad || row < right->height());
	right->display(os, row, do_pad);
}

void Frame_Pic::display(ostream& os, ht_sz row, bool do_pad) const
{
	if (row >= height()) {
		// out of range
		if (do_pad)
		pad(os, 0, width());
	} else {
		if (row == 0 || row == height() - 1) {
			// top or bottom row
			os << string(width(), '*');
	} else if (row == 1 || row == height() - 2) {
		// second from top or bottom row
		os << "*";
		pad(os, 1, width() - 1);
		os << "*";
	} else {
		// interior row
		os << "* ";
		p->display(os, row - 2, true);
		os << " *";
	}
	}
}

#endif

Edited 6 Years Ago by Andreas5: n/a

Andreas5,

Please use an informative title for your threads. This will attract the correct set of readers.

David

This article has been dead for over six months. Start a new discussion instead.