Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cs-142:shapes [2015/06/09 19:12]
cs142ta created
cs-142:shapes [2015/06/09 19:41] (current)
cs142ta
Line 29: Line 29:
 * For a circle: * For a circle:
 ** Circle (radius 12), ID#1, Blue ** Circle (radius 12), ID#1, Blue
 +
 +* Let the user select a color to change all of the shapes to before they are printed to the console
  
 ===Part III=== ===Part III===
Line 36: Line 38:
 * For a circle: * For a circle:
 ** Circle (radius 12), ID#1, Blue – area:452.39 – edge:75.4 ** Circle (radius 12), ID#1, Blue – area:452.39 – edge:75.4
 +
 +===Unimplemented Tasks===
 +====Scaling====
 +* What if we wanted to also be able to scale an object’s size?
 +* Let the user scale all objects before printing them to the console
 +====Moving====
 +* What if we wanted to include x, y coordinates of the shape’s center in the shape summary?
 +* What if we wanted to be able to move a shape (positive y meaning up and positive x meaning right)?
 +* Allow the user to move all shapes’ positions by a certain amount before printing them to the console
  
 ==Solution== ==Solution==
 ===Source.cpp=== ===Source.cpp===
 <code cpp> <code cpp>
 +/*
 +Test case classes (you should provide specific test cases)
 +
 +Test file should include both Circle and a Rectangle
 +
 +Test file should include shapes with dimension values of 0
 +
 +Test file should include shapes of many different colors and sizes
 +
 +*/
 +
 +#include <​fstream>​
 +#include <​iostream>​
 +#include <​sstream>​
 +#include <​string>​
 +#include <​vector>​
 +#include "​Circle.h"​
 +#include "​Rectangle.h"​
 +#include "​Shape.h"​
 +
 +using namespace std;
 +
 +void create_objects_from_file(string filename, vector<​Shape *> & shapes);
 +
 +int main()
 +{
 + vector<​Shape *> shapes;
 +
 + // 1. READ IN A FILE AND CREATE AN OBJECT FOR EACH SHAPE
 + cout << "​Filename:"​ << endl;
 + string filename;
 + getline(cin,​ filename);
 +
 + // static helper function
 + create_objects_from_file(filename,​ shapes);
 +
 + // Let the user select a color to change all of the shapes to before they are printed to the console
 + string user_fav_color;​
 + cout << "Fav color: ";
 + getline(cin,​ user_fav_color);​
 +
 + // 2. PRINT A SUMMARY OF THE SHAPES (to_string() is fine)
 + for (int i = 0; i < shapes.size();​ i++)
 + {
 + // All derived classes have access to the base class set_color() function
 + shapes[i]->​set_color(user_fav_color);​
 +
 + // Each derived class implements and executes these differently. HERE IS POLYMORPHISM
 + cout << shapes[i]->​to_string() << endl;
 + cout << "​\tAREA:"​ << shapes[i]->​area() << endl;
 + cout << "​\tEDGE:"​ << shapes[i]->​edge_length() << endl;
 + }
 +
 + system("​pause"​);​
 + return 0;
 +}
 +
 +/*
 +Function to load contents of a file and create shape objects depending on file contents
 +@param filename name of file to load shapes from
 +@param shapes vector into which to load new shape objects
 +*/
 +void create_objects_from_file(string filename, vector<​Shape *> & shapes)
 +{
 + ifstream in_file;
 +
 + in_file.open(filename);​
 + // Note: we don't test if the filename is valid or not
 +
 + string line;
 + // loop continues as long as another line can be read
 + while (getline(in_file,​ line))
 + {
 + // cout << "LINE: " << line << endl;
 + // use an istringstream when trying to read different data types from a string
 + istringstream strm(line);
 + string color;
 + string shape_type;
 +
 + strm >> color;
 + strm >> shape_type;
 +
 + // This is a pointer to the shape we are going to create for the given line
 + Shape * new_shape = NULL;
 + if (shape_type == "​Rectangle"​)
 + {
 + int width, height;
 + strm >> width >> height;
 +
 + // The substitution principle allows us to put an object of a derived class
 + // where an object of the base class is expected
 + new_shape = new Rectangle(color,​ width, height);
 + }
 + else if (shape_type == "​Circle"​)
 + {
 + int radius;
 + strm >> radius;
 +
 + // The substitution principle allows us to put an object of a derived class
 + // where an object of the base class is expected
 + new_shape = new Circle(color,​ radius);
 + }
 + // cout << "shape created with color: " << new_shape->​get_color() << endl;
 +
 + // this is NULL if the shape_type was neither Rectangle nor Circle
 + if (new_shape != NULL)
 + {
 + shapes.push_back(new_shape);​
 + }
 + }
 +
 +}
 </​code>​ </​code>​
 ===Shape.h=== ===Shape.h===
 <code cpp> <code cpp>
 +#include <​string>​
 +
 +using namespace std;
 +
 +#pragma once
 +class Shape
 +{
 +public:
 + // CONSTRUCTOR
 + /*
 + Default constructor for a Shape object
 + */
 + Shape();
 +
 + // OTHER MEMBER FUNCTIONS
 + /*
 + @return color of *this* Shape object
 + */
 + string get_color() const;
 +
 + /*
 + @param new_color color to be set as *this* Shape object'​s color
 + */
 + void set_color(string new_color);
 +
 + /*
 + @return the unique id for this Shape
 + */
 + int get_id() const;
 +
 + /*
 + Function to compute shape'​s area. Note that this can't be computed for a generic shape
 + hence why it is a pure virtual function
 + @return the area of *this* Shape object
 + */
 + // a Pure Virtual Function must, by definition, be overwritten by any derived class
 + virtual double area() const = 0;
 +
 + /*
 + Function to compute shape'​s perimeter edge length. Note that this can't be computed for a generic shape
 + hence why it is a pure virtual function
 + @returns the perimeter of *this* Shape object
 + */
 + // a Pure Virtual Function must, by definition, be overwritten by any derived class
 + virtual double edge_length() const = 0;
 +
 + /*
 + @return a string representation of *this* Shape object
 + */
 + virtual string to_string() const;
 +
 +private:
 + // DATA MEMBERS
 + string color;
 + int id;
 +
 + // static variables exist once for all instances of the class
 + static int next_id;
 +};
 </​code>​ </​code>​
 ===Shape.cpp=== ===Shape.cpp===
 Note that even though Shape is an abstract class (by virtue of having a pure virtual function), there is still an implementation file. Note that even though Shape is an abstract class (by virtue of having a pure virtual function), there is still an implementation file.
 <code cpp> <code cpp>
 +#include <​sstream>​
 +#include "​Shape.h"​
 +
 +// initialize our static variable
 +int Shape::​next_id = 0;
 +
 +Shape::​Shape()
 +{
 + color = "";​
 + id = next_id; // static variable at work
 + next_id++;
 +}
 +
 +string Shape::​get_color() const
 +{
 + return color;
 +}
 +
 +void Shape::​set_color(string new_color)
 +{
 + color = new_color;
 +}
 +
 +int Shape::​get_id() const
 +{
 + return id;
 +}
 +
 +string Shape::​to_string() const
 +{
 + // use an ostringstream when creating a string from different data types
 + ostringstream strm;
 +
 + strm << "ID# " << id << ", " << color;
 +
 + return strm.str();
 +}
 </​code>​ </​code>​
 ===Circle.h=== ===Circle.h===
 <code cpp> <code cpp>
 +#pragma once
 +// to BE a Shape, we must know what a Shape is
 +#include "​Shape.h"​
 +
 +// Here is where we define that a Circle IS-A Shape and inherits all of its members and functions
 +class Circle : public Shape
 +{
 +public:
 + // CONSTRUCTOR
 + /*
 + Constructor to construct a new Circle object
 + @param _color color of new Circle object
 + @param _radius radius of the new Circle object
 + */
 + Circle(string _color, int _radius);
 +
 + // MEMBER FUNCTION
 + /*
 + @return a string representation of *this* Circle object
 + */
 + virtual string to_string() const;
 +
 + /*
 + @return area of *this* Circle object
 + */
 + virtual double area() const;
 +
 + /*
 + @return perimeter edge length of *this* Circle object
 + */
 + virtual double edge_length() const;
 +
 +private:
 + // DATA MEMBERS
 + int radius;
 +
 + // Note that this inherits all other data members and member functions that it needs from the base class
 +};
 </​code>​ </​code>​
 ===Circle.cpp=== ===Circle.cpp===
 <code cpp> <code cpp>
 +#include <​sstream>​
 +#include "​Circle.h"​
 +
 +
 +Circle::​Circle(string _color, int _radius)
 + :Shape(), radius(_radius)
 + // Everything after ':'​ is the initializer list
 + // The Shape() constructor is called by default but we include it for emphasis
 +{
 + set_color(_color);​
 +}
 +
 +string Circle::​to_string() const
 +{
 + // use an ostringstream when creating a string from different data types
 + ostringstream strm;
 +
 + strm << "​Circle (radius " << radius << "), "
 + << Shape::​to_string();​
 +
 + return strm.str();
 +}
 +
 +double Circle::​area() const
 +{
 + return 3.14159 * radius * radius;
 +}
 +
 +double Circle::​edge_length() const
 +{
 + return 2 * 3.14159 * radius;
 +}
 </​code>​ </​code>​
 ===Rectangle.h=== ===Rectangle.h===
 <code cpp> <code cpp>
 +#pragma once
 +// to BE a Shape, we must know what a Shape is
 +#include "​Shape.h"​
 +
 +// Here is where we define that a Rectangle IS-A Shape and inherits all of its members and functions
 +class Rectangle : public Shape
 +{
 +public:
 + // CONSTRUCTOR
 + /*
 + Constructor to construct a new Rectangle object
 + @param _color color of new Rectangle object
 + @param _radius radius of the new Rectangle object
 + */
 + Rectangle(string _color, int _width, int _height);
 +
 + // MEMBER FUNCTION
 + /*
 + @return a string representation of *this* Rectangle object
 + */
 + virtual string to_string() const;
 +
 + /*
 + @return area of *this* Rectangle object
 + */
 + virtual double area() const;
 +
 + /*
 + @return perimeter edge length of *this* Rectangle object
 + */
 + virtual double edge_length() const;
 +
 +private:
 + int width;
 + int height;
 +
 + // Note that this inherits all other data members and member functions that it needs from the base class
 +};
 </​code>​ </​code>​
 ===Rectangle.cpp=== ===Rectangle.cpp===
 <code cpp> <code cpp>
 +#include <​sstream>​
 +#include "​Rectangle.h"​
 +
 +
 +Rectangle::​Rectangle(string _color, int _width, int _height)
 + :Shape(), width(_width),​ height(_height)
 + // Everything after ':'​ is the initializer list
 + // The Shape() constructor is called by default but we include it for emphasis
 +{
 + set_color(_color);​
 +}
 +
 +string Rectangle::​to_string() const
 +{
 + // use an ostringstream when creating a string from different data types
 + ostringstream strm;
 +
 + strm << "​Rectangle (" << width << " x " << height << "), "
 + << Shape::​to_string();​
 +
 + return strm.str();
 +}
 +
 +double Rectangle::​area() const
 +{
 + return width * height;
 +}
 +
 +double Rectangle::​edge_length() const
 +{
 + return 2 * width + 2 * height;
 +}
 </​code>​ </​code>​
 +===shapes.txt===
 +Here is a possible input file
 +<pre>
 +Red Circle 38 12 22
 +Blue Circle 18 56 79
 +Green Rectangle 22 42 190 76
 +Yellow Circle 78 78 190
 +Black Circle 1 78 78
 +Supercalifragilisticexpialidocious this is the only error we test
 +Grey Circle 3 78 78
 +Black Circle 5 78 78
 +Green Rectangle 10 10 100 100
 +Pink Circle 10 50 50
 +</​pre>​
cs-142/shapes.txt · Last modified: 2015/06/09 19:41 by cs142ta
Back to top
CC Attribution-Share Alike 4.0 International
chimeric.de = chi`s home Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0