/**
* \file goodpractice.cpp
* \author Paul Dejean
* \date 12-18-09
*
* \brief This is a short program for printing a representation of a rectangle to the console.
* It's supposed to be a demonstration of good practice.
*
* The reason for creating this is that one of my friends wanted to learn C++. He started learning from C++.com
* of course, because they were the first result on google, and the site showed him how to get started quickly.
* Following one of the examples on the site, he created this program: http://codepad.org/xBI2fk1J
* Now when I saw that program, I felt a duty to show this aspiring video game programmer the proper way to do
* things. This program is a correction of his program. It's supposed to demonstrate good practice. Obviously
* there is no reason to go to this extent if you're working on a simple program you're using for learning,
* however the reason good practice is considered good practice, is because it leads to less wasted time in
* the long run for large software projects.
*/
#include <iostream>
#include <string>
using std::cout;
using std::endl;
/**
* Thrown when the user gives bad input.
*/
/**
* An exception that will be thrown if the user gives bad input.
* Most of the times, people will code things such that the program will do nothing, if bad intput is given
* but it's good to give the programmer a choice.
*/
class BadInput : public std::exception {
friend std::ostream& operator<<(ostream& ls, const BadInput rs);
private:
std::string error_msg;
public:
BadInput(std::string msg);
~BadInput() throw() {}
};
/**
* Constructs a new BadInput exception, with a given error message.
*/
BadInput::BadInput(std::string msg) : error_msg(msg) {
}
/**
* Streams out a string representation of BadInput.
*/
std::ostream& operator<<(ostream& ls, const BadInput rs) {
ls << rs.error_msg;
return ls;
}
/**
* Represents a rectangle.
*/
/* Represents a rectangle. A good thing to represent with an object if you're just learning about classes.
* A class representing complex numbers as a favorite of Bjarne Stroustrup. A rectangle is very similar.
*/
class Rectangle {
private:
static const unsigned int MAX_HEIGHT = 30;
static const unsigned int MAX_WIDTH = 30;
static const char FILLING = ' ';
unsigned int width;
unsigned int height;
void drawHorizontalSides();
void drawVerticalSide();
public:
Rectangle(unsigned int w, unsigned int h);
void draw() throw(BadInput);
};
/** Rectangle simple constructor.
* \param w The width of the rectangle.
* \param h The height of the rectangle.
*/
Rectangle::Rectangle (unsigned int w, unsigned int h) : width(w), height(h) {
}
/**
* Draws a ASCII representation of the rectangle to standard output.
*/
void Rectangle::draw() throw(BadInput) {
if(this->width > MAX_WIDTH) {
throw new BadInput("Too large of a height, enter in something smaller!");
}
else if(this->width > MAX_HEIGHT) {
throw new BadInput("Too large of a height, enter in something smaller!");
}
else {
if(this->width > 0) {
// Draw top.
cout << " ";
this->drawVerticalSide();
cout << " " << endl;
if(this->height > 0) {
// Draw sides.
this->drawHorizontalSides();
// Draw bottom.
cout << "|";
this->drawVerticalSide();
cout << "|";
}
}
else {
// If the width is 0, then we only want to draw one horizontal side.
for(unsigned int n = this->height; n > 0; --n) {
cout << "|" << endl;
}
}
}
}
void Rectangle::drawHorizontalSides() {
std::string spacing(this->width, this->FILLING);
for(unsigned int n = this->height - 1; n > 0; --n) {
// First write the left wall.
cout << "|";
// Then write the spacing inbetween.
cout << spacing << spacing;
// Then write the right wall.
cout << "|" << endl;
}
}
void Rectangle::drawVerticalSide() {
for(unsigned int n = this->width; n > 0; --n) {
cout << "__";
}
}
/**
* Program entry point. A demonsration of the rectangle class.
*/
int main(int argc, char* argv[]) {
Rectangle sample_rectangle(23, 5);
try {
sample_rectangle.draw();
}
catch(BadInput e) {
cout << e << endl;
}
}