In: Computer Science
Please, Use C++
The files in question are Square.cpp, Square.h, SquareContainer.cpp, SquareContainer.h and ClassTest.cpp. Please download, compile and run these files, and convince yourself that you understand what they do.
Question
Coding (finish in 60min) - just try to finish as many as you can
Here is the codes of Square.cpp, Square.h, SquareContainer.cpp, SquareContainer.h and ClassTest.cpp.
Square.h file
#ifndef SQUARE_H
#define SQUARE_H
class Square {
public:
void setSize(int newSize);
int getSize(void) const;
Square& operator = (const Square&);
private:
int theSize;
};
#endif
Square.cpp file
#include "Square.h"
void Square::setSize(int newSize){
theSize = newSize;
}
int Square::getSize(void) const
{
return theSize;
}
Square& Square::operator = (const Square& other)
{
theSize = other.getSize();
return *this;
}
SquareContainer.h file
#ifndef SQUARECONTAINER_H
#define SQUARECONTAINER_H
#include <stdexcept>
#include <string>
#include "Square.h"
using namespace std;
class SquareContainerException : public out_of_range {
public:
SquareContainerException(const string& message = "")
: out_of_range(message.c_str()) { }
};
class SquareContainer {
public:
// Plain constructor
SquareContainer();
// Copy constructor
SquareContainer(const SquareContainer& old);
// Destructor
~SquareContainer();
// Insert an item in next location, reallocating storage if necessary
void insertNext(Square item);
// Delete an item at last location, returning a copy
Square deleteLast(void) throw(SquareContainerException);
// Number of items in the container
unsigned size(void) const;
// Current container capacity
unsigned capacity(void) const;
private:
// Utility functions
// Utility function: copy contents of current object to new storage
// "to" must be allocated at least as much memory as theSquares
void copy(Square* to, Square* from);
// Delete dynamically allocated storage for this object
void clear(void);
// Dynamically allocated array
Square* theSquares;
// Where we are and how big we are
unsigned nextItem, currentSize;
};
#endif
SquareContainer.cpp file
#include "SquareContainer.h"
const unsigned DEFAULTSIZE = 10;
// Plain constructor
SquareContainer::SquareContainer() : currentSize(DEFAULTSIZE), nextItem(0)
{
theSquares = new Square[currentSize];
}
// Copy constructor
SquareContainer::SquareContainer(const SquareContainer& old)
: currentSize(old.currentSize), nextItem(old.nextItem)
{
theSquares = new Square[currentSize];
copy(theSquares, old.theSquares);
}
// Destructor
SquareContainer::~SquareContainer()
{
clear();
}
// Insert an item in next location, reallocating storage if necessary
void SquareContainer::insertNext(Square item)
{
// Check if we have room
if (nextItem < currentSize) {
// If we have room, insert item
theSquares[nextItem++] = item;
} else {
// If not, reallocate storage, copy old contents to new, then inert new item
unsigned newSize = currentSize*2;
Square* newStorage = new Square[newSize];
copy(newStorage, theSquares);
newStorage[nextItem++] = item;
currentSize = newSize;
delete [] theSquares;
theSquares = newStorage;
}
}
// Delete an item at last location, returning a copy, but not a reference
Square SquareContainer::deleteLast(void) throw(SquareContainerException)
{
// It's an array, and we never shrink it, so all we need to do is grab
// the item and decrement nextItem (assuming there's an item to delete).
if (nextItem == 0) {
throw SquareContainerException("SquareContainer: Attempt to delete when empty.");
}
return theSquares[--nextItem];
}
// Number of items in the container
unsigned SquareContainer::size(void) const
{
return nextItem;
}
// Current container capacity
unsigned SquareContainer::capacity(void) const
{
return currentSize;
}
// Utility function: copy contents of current object to new storage
// "to" must be allocated at least as much memory as theSquares
void SquareContainer::copy(Square* to, Square* from)
{
for (int i = 0; i<nextItem; i++) {
to[i] = from[i];
}
}
// Delete dynamically allocated storage for this object
void SquareContainer::clear(void)
{
for (int i=0; i<currentSize; i++) {
theSquares[i].setSize(0);
}
delete [] theSquares;
theSquares = NULL;
nextItem = currentSize = 0;
}
ClassTest.cpp file
#include <iostream>
#include "Square.h"
#include "SquareContainer.h"
using namespace std;
int main (int argc, char * const argv[]) {
SquareContainer c;
for (int i = 0; i < 20; i++) {
Square s;
s.setSize(i);
c.insertNext(s);
}
SquareContainer d(c); // copy
SquareContainer e = d; // assignment
try {
for (int i = 0; i < 21; i++) {
cout << "Square " << i << " size is "
<< c.deleteLast().getSize() << endl;
}
}
catch (SquareContainerException sqe) {
cerr << sqe.what();
}
return 0;
}
Hello! :)
Here are my answers for this assignment:
Presently, there is no problem with defining the two classes in SquareContainer.h because the two classes are related. It might turn into a problem only if the codebase becomes massive because it would take more time to build the project.
Here are the updated codes:
Square.h:
#ifndef SQUARE_H
#define SQUARE_H
#include <ostream>
class Square {
public:
void setSize(int newSize);
int getSize(void) const;
// The Square class does not need an
// overloaded assignment operator as
// the compiler provides it already.
// It would be necessary to overload
// the assignment operator only when
// we are dealing with pointer member
// variables where we do the memory
// management ourselves.
Square& operator = (const Square&);
bool operator < (const Square&);
friend std::ostream& operator << (std::ostream&, const Square&);
private:
int theSize;
};
#endif
Square.cpp:
#include "Square.h"
void Square::setSize(int newSize){
theSize = newSize;
}
int Square::getSize(void) const
{
return theSize;
}
Square& Square::operator = (const Square& other)
{
theSize = other.getSize();
return *this;
}
bool Square::operator < (const Square& other)
{
return this->theSize < other.getSize();
}
std::ostream& operator << (std::ostream& stream, const Square& other)
{
stream << "size of square: " << other.getSize();
return stream;
}
SquareContainer.h:
#ifndef SQUARECONTAINER_H
#define SQUARECONTAINER_H
#include <stdexcept>
#include <string>
#include <ostream>
#include "Square.h"
using namespace std;
class SquareContainerException : public out_of_range {
public:
SquareContainerException(const string& message = "")
: out_of_range(message.c_str()) { }
};
class SquareContainer {
public:
// Plain constructor
SquareContainer();
// Copy constructor
SquareContainer(const SquareContainer& old);
// Destructor
~SquareContainer();
// Insert an item in next location, reallocating storage if necessary
void insertNext(Square item);
// Delete an item at last location, returning a copy
Square deleteLast(void) throw(SquareContainerException);
// Number of items in the container
unsigned size(void) const;
// Current container capacity
unsigned capacity(void) const;
private:
// Utility functions
// Utility function: copy contents of current object to new storage
// "to" must be allocated at least as much memory as theSquares
void copy(Square* to, Square* from);
// Delete dynamically allocated storage for this object
void clear(void);
// Dynamically allocated array
Square* theSquares;
// Where we are and how big we are
unsigned nextItem, currentSize;
public:
// Overloaded assignment operator using the copy() and clear() methods.
SquareContainer& operator = (const SquareContainer&);
// Overloaded stream output operator to print out the size of each square in the container.
friend ostream& operator << (ostream&, const SquareContainer&);
};
#endif
SquareContainer.cpp:
#include "SquareContainer.h"
const unsigned DEFAULTSIZE = 10;
// Plain constructor
SquareContainer::SquareContainer() : currentSize(DEFAULTSIZE), nextItem(0)
{
theSquares = new Square[currentSize];
}
// Copy constructor
SquareContainer::SquareContainer(const SquareContainer& old)
: currentSize(old.currentSize), nextItem(old.nextItem)
{
theSquares = new Square[currentSize];
copy(theSquares, old.theSquares);
}
// Destructor
SquareContainer::~SquareContainer()
{
clear();
}
// Insert an item in next location, reallocating storage if necessary
void SquareContainer::insertNext(Square item)
{
// Check if we have room
if (nextItem < currentSize) {
// If we have room, insert item
theSquares[nextItem++] = item;
} else {
// If not, reallocate storage, copy old contents to new, then inert new item
unsigned newSize = currentSize*2;
Square* newStorage = new Square[newSize];
copy(newStorage, theSquares);
newStorage[nextItem++] = item;
currentSize = newSize;
delete [] theSquares;
theSquares = newStorage;
}
}
// Delete an item at last location, returning a copy, but not a reference
Square SquareContainer::deleteLast(void) throw(SquareContainerException)
{
// It's an array, and we never shrink it, so all we need to do is grab
// the item and decrement nextItem (assuming there's an item to delete).
if (nextItem == 0) {
throw SquareContainerException("SquareContainer: Attempt to delete when empty.");
}
return theSquares[--nextItem];
}
// Number of items in the container
unsigned SquareContainer::size(void) const
{
return nextItem;
}
// Current container capacity
unsigned SquareContainer::capacity(void) const
{
return currentSize;
}
// Utility function: copy contents of current object to new storage
// "to" must be allocated at least as much memory as theSquares
void SquareContainer::copy(Square* to, Square* from)
{
for (int i = 0; i<nextItem; i++) {
to[i] = from[i];
}
}
// Delete dynamically allocated storage for this object
void SquareContainer::clear(void)
{
for (int i=0; i<currentSize; i++) {
theSquares[i].setSize(0);
}
delete [] theSquares;
theSquares = NULL;
nextItem = currentSize = 0;
}
// Overloaded assignment operator using the copy() and clear() methods.
SquareContainer& SquareContainer::operator = (const SquareContainer& other)
{
clear();
nextItem = other.nextItem;
currentSize = other.currentSize;
Square* to = theSquares = new Square[currentSize];
Square* from = other.theSquares;
copy(to, from);
}
// Overloaded stream output operator to print out the size of each square in the container.
ostream& operator << (ostream& stream, const SquareContainer& other)
{
stream << "Size of each square in the container:" << endl;
for (unsigned i = 0; i < other.size(); i++) {
stream << other.theSquares[i] << endl;
}
return stream;
}
ClassTest.cpp:
#include <iostream>
#include <sstream>
#include <cassert>
#include "Square.h"
#include "SquareContainer.h"
using namespace std;
int main (int argc, char * const argv[]) {
SquareContainer c;
for (int i = 0; i < 20; i++) {
Square s;
s.setSize(i);
c.insertNext(s);
}
SquareContainer d(c); // copy
SquareContainer e = d; // assignment
try {
for (int i = 0; i < 21; i++) {
cout << "Square " << i << " size is "
<< c.deleteLast().getSize() << endl;
}
}
catch (SquareContainerException sqe) {
cerr << sqe.what();
}
// Testing the overloaded assignment operator of the Square class.
{
Square square1, square2;
square1.setSize(5);
square2 = square1;
assert(square1.getSize() == square2.getSize());
}
// Testing the overloaded "<" operator of the Square class.
{
Square square1, square2;
square1.setSize(5);
square2.setSize(10);
assert(square1 < square2);
}
// Testing the overloaded assignment operator of the SquareContainer class.
{
SquareContainer squareContainer2;
unsigned expectedSize;
unsigned expectedCapacity;
{
Square square1, square2, square3;
square1.setSize(1);
square2.setSize(2);
square3.setSize(3);
SquareContainer squareContainer1;
squareContainer1.insertNext(square1);
squareContainer1.insertNext(square2);
squareContainer1.insertNext(square3);
expectedSize = squareContainer1.size();
expectedCapacity = squareContainer1.capacity();
squareContainer2 = squareContainer1;
}
assert(squareContainer2.size() == expectedSize);
assert(squareContainer2.capacity() == expectedCapacity);
assert(squareContainer2.deleteLast().getSize() == 3);
assert(squareContainer2.deleteLast().getSize() == 2);
assert(squareContainer2.deleteLast().getSize() == 1);
}
// Testing the overloaded stream output operator of the Square class.
{
Square square;
square.setSize(5);
stringstream stream;
stream << square;
assert(stream.str() == "size of square: 5");
}
// Testing the overloaded stream output operator of the Square class.
{
SquareContainer squareContainer;
Square square1, square2, square3;
square1.setSize(1);
square2.setSize(2);
square3.setSize(3);
squareContainer.insertNext(square1);
squareContainer.insertNext(square2);
squareContainer.insertNext(square3);
stringstream stream;
stream << squareContainer;
assert(stream.str() == "Size of each square in the container:\nsize of square: 1\nsize of square: 2\nsize of square: 3\n");
}
return 0;
}
Here is a snapshot of a demo run:
As you can see, the code passes all the tests.
Hope this helps! :)