I wrote the code that can generate random Geometry figures and display it in cmd in text form.
Here is my 3 files:
Geometry.h
#pragma once
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include <iostream>
#include <time.h>
#include <fstream>
#include <string>
#define PI 3.1415926535
using namespace std;
enum color { White, Red, Green, Blue, Yellow, Black };
enum _shape { line, rectangle, circle, picture }; //to roll shapes
void print_color(color c);
//--------------------------Point---------------------------
class Point {
private:
int m_xc, m_yc; //(x,y) coordinats
public:
Point(int x = 0, int y = 0) : m_xc(x), m_yc(y) {}
int x(void) const { return m_xc; };
int y(void) const { return m_yc; };
Point operator+(const Point& p) const
{
return Point(m_xc+p.m_xc, m_yc+p.m_yc);
}
Point& operator+=(const Point& p) //move point
{
m_xc += p.m_xc;
m_yc += p.m_yc;
return *this;
}
friend ostream& operator<<(ostream& os, const Point& p);
Point move(int x, int y){
m_xc += x;
m_yc += y;
return *this;
}
};
//------------------------Shape-----------------------------
class Shape {
protected:
Point m_org;
color m_color;
_shape m_shape;
public:
Shape(const Point& p1 = 0, color c = White, _shape sh = line) : m_org(p1), m_color(c), m_shape(sh){};
virtual ~Shape() = 0 {};
virtual void move(const Point& p) = 0;
virtual void draw(char tabs) const = 0;
virtual void Who_am_I() const = 0;
virtual double Area() const { return 0; };
virtual void Save2File(ofstream &myfile) const = 0;
};
//------------------------Line---------------------------------
class Line : public Shape {
protected:
Point m_end; // line end
public:
Line(const Point& p1, const Point& p2, color c) : Shape(p1, c, line), m_end(p2) {}
void move(const Point& p)
{
m_org += p;
m_end += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Line";
}
double length() const;
double Area() const { return 0; };
void Save2File(ofstream &myfile) const;
};
//----------------------Rectangle-------------------------------
class Rectangle : public Shape {
protected:
int width;
int height;
public:
Rectangle(const Point& p1, color c = White, int w = 0, int h = 0) : Shape(p1, c, rectangle), width(w), height(h) {}
void move(const Point& p)
{
m_org += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Rectangle";
}
double Area() const { return width*height; };
void Save2File(ofstream &myfile) const;
};
//----------------------Circle---------------------------
class Circle : public Shape {
protected:
int radius;
public:
Circle(const Point& p1, color c = White, int r = 0) : Shape(p1, c, circle), radius(r) {};
void move(const Point& p)
{
m_org += p;
}
void draw(char tabs) const;
void Who_am_I() const {
print_color(m_color);
cout << "Circle";
}
double Area() const { return PI*(double)radius*(double)radius; };
void Save2File(ofstream &myfile) const;
};
//--------------------------Picture-------------------------
class Picture : public Shape {
private:
Picture(const Picture&); //CCtor is not accessible from main
protected:
Shape** m_shapes; //array of pointers to shapes
int m_count; //number of shapes
static unsigned idx; //number of pictures created for debug
public:
Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
~Picture();
void insert_shape(Shape* sh);
void draw(char tabs) const;
void move(const Point& p){ m_org += p; };
void Who_am_I() const {
print_color(m_color);
cout << "Picture";
}
void Save2File(ofstream &myfile) const;
int get_count(void){ return m_count; }
double Area() const;
unsigned GetAmPic(void) { return idx; }
};
Geometry.cpp
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include "geometry.h"
using namespace std;
unsigned Picture::idx = 0;
ostream& operator<<(ostream& os, const Point& p)
{
os << '(' << p.x() << ',' << p.y() << ')';
return os;
}
void print_color(color c) {
string color_print[6] = { "White ", "Red ", "Green ", "Blue ", "Yellow ", "Black " };
cout << color_print[(int)c];
}
//------------------Line methods--------------------
void Line::draw(char tabs) const
{
cout << string(tabs, '\t');
Who_am_I();
cout << " from " << m_org << " to " << m_end << endl;
}
double Line::length() const
{
return sqrt((double)((m_org.x()-m_end.x())*(m_org.x()-m_end.x()) + (m_org.y()-m_end.y())*(m_org.y()-m_end.y())));
}
void Line::Save2File(ofstream& myfile) const {// save to file
myfile << 'L' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
<< m_end.x() << " " << m_end.y() << endl;
}
//------------------Rectangle methods----------------
void Rectangle::draw(char tabs) const
{
cout << string(tabs, '\t');
Point temp1 = m_org;
Point temp2 = m_org;
Line l1(temp1, temp2.move(width, 0), m_color);
temp1 = temp2;
Line l2(temp2, temp1.move(0, height), m_color);
temp2 = temp1;
Line l3(temp1, temp2.move(-width, 0), m_color);
temp1 = temp2;
Line l4(temp2, temp1.move(0, -height), m_color);
Who_am_I(); cout << endl;
cout << string(tabs, '\t'); l1.draw(1);
cout << string(tabs, '\t'); l2.draw(1);
cout << string(tabs, '\t'); l3.draw(1);
cout << string(tabs, '\t'); l4.draw(1);
}
void Rectangle::Save2File(ofstream& myfile) const {// save to file
myfile << 'R' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " " << width
<< " " << height << endl;
}
//----------------------Circle methods---------------------------
void Circle::draw(char tabs) const
{
cout << string(tabs, '\t');
Who_am_I();
cout << " Center in " << m_org << " Radius is " << radius << endl;
}
void Circle::Save2File(ofstream& myfile) const {// save to file
myfile << 'C' << " " << m_color << " " << m_org.x() << " " << m_org.y() << " "
<< radius << endl;
}
//----------------------Picture methods--------------------------
void Picture::insert_shape(Shape* s) // insert a new shape to picture
{
if (m_count == 0) {//new picture creating
m_shapes = new Shape*[1];
if (!m_shapes)
cout << "Can't allocate memory!";
}
if (m_count > 0){
Shape** temp = new Shape*[m_count];
memcpy(temp, m_shapes, sizeof(Shape*)*m_count); //save to temp
delete m_shapes; //delete old array
m_shapes = new Shape*[m_count + 1]; //add 1 more place
if (!m_shapes)
cout << "Can't allocate memory!";
memcpy(m_shapes, temp, sizeof(Shape*)*m_count); //return to array
delete temp;
}
m_shapes[m_count] = s; // insert the new shape into the last slot in the array
m_shapes[m_count]->move(m_org); //adjusts the location of the shape
m_count++; // increment the number of shapes in picture
}
void Picture::draw(char tabs) const
{
cout << string(tabs, '\t');
cout << "------------------ ";
Who_am_I();
cout << " ----------------------" << endl;
for (unsigned i = 0; i < m_count; i++)
{
m_shapes[i]->draw(tabs + 1); // draw each shape
}
cout << string(tabs, '\t');
cout << "------------------ End ";
Who_am_I();
cout << " ------------------ " << endl;
}
double Picture::Area() const //sum of areas of all shapes in the picture
{
double area = 0;
for (int i = 0; i < m_count; i++)
{
area += m_shapes[i]->Area();
}
return area;
}
Picture::~Picture()
{
for (int i = 0; i < m_count; i++){
if (m_shapes[i])
delete m_shapes[i];
}
Who_am_I(); cout << " deleting..." << endl;
// sometimes (every 5-10 runs) error here. can't reproduce and debug
if (m_shapes)
delete m_shapes;
// seems like program try to delete already freed memory
}
void Picture::Save2File(ofstream& myfile) const // save to file
{
myfile << 'P' << " " << m_color << " " << m_org.x() << " " << m_org.y() << endl;
for (int i = 0; i < m_count; i++)
m_shapes[i]->Save2File(myfile);
myfile << 'E' << endl; // end of a picture
}
drawing_app.cpp
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
#define new DEBUG_NEW
#include "geometry.h"
#include <iostream>
#define MAX_PICS_IN_PIC 3
#define MAX_SHAPES 5
using namespace std;
void randomizer(Picture*, int); //recursive function
Picture* Load(istream&);
Point GenP(void);
color GenC(void);
int GenLen(void);
int main(void)
{
srand((unsigned int)time(NULL));
Picture *main_pic = new Picture(Point(0, 0), GenC());
ofstream myfile_write("myfile.txt", ios::out);
if (!myfile_write.is_open())
cout << "Can't open file!" << endl;
randomizer(main_pic, MAX_PICS_IN_PIC); //recursive function
main_pic->Save2File(myfile_write); //save picture to file
myfile_write.close();
cout << " Created Picture:" << endl << endl;
main_pic->draw(0); //draw the main picture
cout << "Created: " << main_pic->GetAmPic() << " pictures." << endl; // for debugging
delete[] main_pic;
ifstream myfile_read("myfile.txt", ios::in);
if (!myfile_read.is_open())
cout << "Can't open file!" << endl;
Picture* buff_pic = Load(myfile_read); //load the picture from the file
cout << endl << endl << " Loaded Picture:" << endl << endl;
buff_pic->draw(0); //display loaded picture
myfile_read.close();
delete[] buff_pic;
cout << "\nLeaks: " << _CrtDumpMemoryLeaks() << endl;
return 0;
}
void randomizer(Picture* pic, int count) {
for (int i = 0; i < MAX_SHAPES; i++){
Point p1 = GenP(); //m_org of the shape
color c = GenC(); //roll random color
_shape shape;
shape = (_shape)(rand() % 4); //roll random shape
if (shape == line){
Point p2 = GenP();
Line* _line = new Line(p1, p2, c);
pic->insert_shape(_line);
}
if (shape == rectangle){
Rectangle* _rect = new Rectangle(p1, c, GenLen(), GenLen());
pic->insert_shape(_rect);
}
if (shape == circle){
Circle* _circ = new Circle(p1, c, GenLen());
pic->insert_shape(_circ);
}
if (shape == picture){
if (count > 0){
Picture* inner_pic = new Picture(p1, c);
count--;
randomizer(inner_pic, count);
pic->insert_shape(inner_pic);
}
else return;
}
}
}
Picture* Load(istream& myfile) {
int m_color, m_org_x, m_org_y;
char m_shape;
myfile >> m_shape >> m_color >> m_org_x >> m_org_y; //read first line
Picture* pic = new Picture(Point(m_org_x, m_org_y), (color)m_color); //create the main picture
myfile >> m_shape; //read next line for shape
while (m_shape != 'E')
{
if (m_shape == 'L'){
int m_end_x, m_end_y;
myfile >> m_color >> m_org_x >> m_org_y >> m_end_x >> m_end_y;
Line* _line = new Line(Point(m_org_x, m_org_y), Point(m_end_x, m_end_y), (color)m_color);
pic->insert_shape(_line);
}
if (m_shape == 'C'){
int radius;
myfile >> m_color >> m_org_x >> m_org_y >> radius;
Circle* Circel = new Circle(Point(m_org_x, m_org_y), (color)m_color, radius);
pic->insert_shape(Circel);
}
if (m_shape == 'R') {
int m_width, m_height;
myfile >> m_color >> m_org_x >> m_org_y >> m_width >> m_height;
Rectangle* Rect = new Rectangle(Point(m_org_x, m_org_y), (color)m_color,
m_width, m_height);
pic->insert_shape(Rect);
}
if (m_shape == 'P') {
myfile.seekg(-1, ios::cur);
Picture* inner_pic = Load(myfile);
pic->insert_shape(inner_pic);
}
myfile >> m_shape;
}
return pic;
}
Point GenP(){ //roll random point x = 0 to 30, y = 0 to 30
Point p(rand() % 31, rand() % 31);
return p;
}
color GenC(){ //generate random color
return (color)(rand() % 6);
}
int GenLen(){ // generate random length from 1 to 50
return rand() % 50 + 1;
}
Every 5-10 runs I got strange error:
Unhandled exception at 0x5214A9E8 (msvcr120d.dll) in Geometry.exe: 0xC0000005: Access violation reading location 0xCDCDCDC1.
Referring me to Destructor of Picture class. I can't reproduce this error and can't find the source of this error. Do you have any ideas how I can debug it?
The obvious error is that it is entirely (and easily) possible to attempt to delete an uninitialized m_shapes pointer in the Picture destructor.
The outline of your code is this:
class Picture : public Shape {
private:
Picture(const Picture&); //CCtor is not accessible from main
protected:
Shape** m_shapes; //array of pointers to shapes
int m_count; //number of shapes
static unsigned idx; //number of pictures created for debug
public:
Picture(const Point& p1 = 0, color c = White) : Shape(p1, c, picture), m_count(0){ idx++; }
//...
~Picture();
};
In the ~Picture() function, you do the following:
Picture::~Picture()
{
for (int i = 0; i < m_count; i++){
if (m_shapes[i])
delete m_shapes[i];
}
if (m_shapes) // This may not have been initialized!!
delete m_shapes;
}
In the Picture() constructor, you failed to initialize m_shapes, thus a simple one line program would be able to invoke the undefined behavior of calling delete on an uninitialized pointer.
Example:
int main()
{
Picture p(Picture(Point(0, 0), GenC()));
} // The `p` destructor will invoke undefined behavior.
Therefore the immediate fix is to go back and make sure m_shapes is initialized to (at least) a nullptr on construction of Picture.
However the ultimate fix is to start to use std::vector and other containers, in addition to using smart pointers such as std::shared_ptr<Shape> and/or std::unique_ptr<Shape>. When you do this, functions such as Picture::insert_shape become either obsolete, or are simple one-line functions issuing a call to (for example) std::vector<Shape*>::push_back().
For example (using a vector of raw pointers)
#include <vector>
class Picture
{
//...
std::vector<Shape *> m_shapes;
void insert_shape(Shape* s);
//...
};
void Picture::insert_shape(Shape* s)
{
m_shapes.push_back(s);
}
If you want to debug the crash in C++ code, let me show you how to use and inspect dumps:
Use adplus.exe (get it from Microsoft) and run your app in process monitor mode
Download WinDBG (also from Microsoft)
Use the following command to create a dump in monitor mode of your process
ADPlus -Crash -pmn Geometry.exe -o C:\CrashDumps
Open the crash dump in WinDBG
Learn the power of WinDBG
A note: You might need symbols (.pdb) files to be created/loaded in your dump inspection
The error is in this line.
Picture *main_pic = new Picture(Point(0, 0), GenC());
You're not giving the size to your Picture pointer and you're deleting it like an array, You must assign a size to your pointer then you also can delete is like this.
delete [] main_pic;
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 9 months ago.
Improve this question
I have tried to run the program with more than one inheritance i got many errors
For this program ,but when i use it for Source File, it will looks good
I don't know why but I think because i update my version or does make any sense
please help me with my project
int main
#include"Shapes.h"
#include"Cylinder.h"
#include"Sphere.h"
#include"Triangle.h"
#include"Square.h"
#define MAX_SHAPES 100
int main() {
ofstream myfile;
myfile.open("Shapes.dat");
Shape* shapes[MAX_SHAPES];
int currentShapes = 0;
int n = 0;
cout << "Select any Number to calculate : \n";
cout << "1. Square\n";
cout << "2. Triangle\n";
cout << "3. Sphere\n";
cout << "4. Cylinder\n";
cout << "Enter your choice: ";
cin >> n;
cin.ignore();
if (n == 1) {
Square* obj2 = new Square();
obj2->readData();
shapes[currentShapes] = obj2;
}
if (n == 2) {
Triangle* obj3 = new Triangle();
obj3->readData();
shapes[currentShapes] = obj3;
}
if (n == 3) {
Sphere* obj5 = new Sphere();
obj5->readData();
shapes[currentShapes] = obj5;
}
if (n == 4) {
Cylinder* obj7 = new Cylinder();
obj7->readData();
obj7->computeSurfaceArea();
obj7->computeVolume();
obj7->print();
obj7->printToFile();
shapes[currentShapes] = obj7;
}
return 0;
}
shape.h
class Shape {
private:
string color, name;
public:
// default constructor
Shape()
{
color = 1.0;
name = "";
cout << "Base Class is Shape for this element . \n";
}
// parameterized constructor
Shape(string color, string name) {
this->color = color;
this->name = name;
}
// read data
void readData() {
cout << "Enter color: ";
getline(cin, color);
cout << "Enter name: ";
getline(cin, name);
}
virtual void print() = 0;
virtual void printToFile() = 0;
virtual void readFromFile(ifstream& input) = 0;
};
shape2d.h
class Shape2D : public Shape {
public:
double area;
double perimeter;
Shape2D() :Shape()
{
cout << "Parent Class is Shape2D for this element .\n";
}
// parameterized constructor
Shape2D(string color, string name) :Shape(color, name) {
}
// read data
void readData() {
Shape::readData();
}
virtual void computeArea() = 0;
virtual void computePerimeter() = 0;
virtual void print() = 0;
virtual void printToFile() = 0;
virtual void readFromFile(ifstream& input) = 0;
};
Shape3d
class Shape3D : public Shape {
public:
double surfaceArea;
double volume;
Shape3D() :Shape()
{
surfaceArea = 1.0;
volume = 1.0;
cout << "Parent Class is Shape3D for this element .\n";
}
// parameterized constructor
Shape3D(string color, string name) :Shape(color, name) {
}
void readData() {
Shape::readData();
}
virtual void computeSurfaceArea() = 0;
virtual void computeVolume() = 0;
virtual void print() = 0;
virtual void printToFile() = 0;
virtual void readFromFile(ifstream& input) = 0;
};
Square.h
class Square : public Shape2D {
private:
double side;
public:
Square() :Shape2D()
{
side = 1.0;
cout << "Calculating square area and perimeter \n";
}
// parameterized constructor
Square(string color, string name, double side) :Shape2D(color, name) {
this->side = side;
}
void readData() {
Shape2D::readData();
cout << "Square Side: ";
cin >> side;
cin.ignore();
computeArea();
computePerimeter();
}
void computeArea()
{
area = side * side;
}
void computePerimeter() {
perimeter = 4 * side;
}
void print(string x, double y)
{
cout << x << " of Square = " << y << "\n";
}
void print() {
print("Area: ", area);
print("Perimeter", perimeter);
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat", ios_base::app);
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Square = " << y << "\n";
ofs.close();
}
void printToFile() {
printToFile("Area: ", area);
printToFile("Perimeter", perimeter);
}
void readFromFile(ifstream& input)
{
string data = "";
while (std::getline(input, data))
{
std::cout << data << endl;
}
}
};
Triangle.h
class Triangle : public Shape2D {
private:
double base;
double height;
public:
Triangle() :Shape2D()
{
cout << "This is a Triangle\n";
}
// parameterized constructor
Triangle(string color, string name, double base, double height) :Shape2D(color, name) {
this->base = base;
this->height = height;
}
void readData() {
Shape2D::readData();
cout << "Triangle Base: ";
cin >> base;
cout << "Triangle Height: ";
cin >> height;
cin.ignore();
computeArea();
computePerimeter();
}
void computeArea() {
area = (height * base) / 2;
}
void computePerimeter() {
perimeter = 2 * height + base;
}
void print(string x, double y)
{
cout << x << " of Triangle = " << y << "\n";
}
void print() {
print("Area: ", area);
print("Perimeter: ", perimeter);
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat", ios_base::app);
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Triangle = " << y << "\n";
ofs.close();
}
void printToFile() {
printToFile("Area: ", area);
printToFile("Perimeter", perimeter);
}
void readFromFile(ifstream& input)
{
string data = "";
while (std::getline(input, data))
{
std::cout << data << endl;
}
}
};
Sphere.h
class Sphere : public Shape3D {
private:
double radius;
public:
Sphere() :Shape3D()
{
radius = 1.0;
cout << "This is a Sphere\n";
}
// parameterized constructor
Sphere(string color, string name, double side) :Shape3D(color, name) {
this->radius = radius;
}
void readData() {
Shape3D::readData();
cout << "Sphere Radius: ";
cin >> radius;
cin.ignore();
computeSurfaceArea();
computeVolume();
}
void computeSurfaceArea() {
surfaceArea = 4 * 3.14 * radius * radius;
}
void computeVolume() {
volume = (4 / 3) * (3.14 * radius * radius * radius);
}
void print(string x, double y)
{
cout << x << " of Sphere = " << y << "\n";
}
void print() {
print("Surface Area: ", surfaceArea);
print("Volume: ", volume);
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat", ios_base::app);
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Sphere = " << y << "\n";
ofs.close();
}
void printToFile() {
printToFile("Surface Area: ", surfaceArea);
printToFile("Volume", volume);
}
void readFromFile(ifstream& input)
{
string data = "";
while (std::getline(input, data))
{
std::cout << data << endl;
}
}
};
Cylinder .h
class Cylinder : public Shape3D {
private:
double radius;
double height;
public:
Cylinder() :Shape3D()
{
radius = 1.0;
height = 1.0;
cout << "This is a Cylinder\n";
}
// parameterized constructor
Cylinder(string color, string name, double radius, double height) :Shape3D(color, name) {
this->radius = radius;
this->height = height;
}
void readData() {
Shape3D::readData();
cout << "Cylinder Radius: ";
cin >> radius;
cout << "Cylinder Height: ";
cin >> height;
cin.ignore();
//computeSurfaceArea();
//computeVolume();
}
void computeSurfaceArea() {
surfaceArea = (2 * 3.14 * radius) * (radius + height);
}
void computeVolume() {
volume = 3.14 * radius * radius * height;
}
void print(string x, double y)
{
cout << x << " of Cylinder = " << y << "\n";
}
void print() {
print("Surface Area: ", surfaceArea);
print("Volume: ", volume);
}
void printToFile(string x, double y)
{
ofstream ofs;
ofs.open("shapes.dat", ios_base::app);
if (!ofs) {
cout << "Error opening file" << endl;
}
cout << "Shapes.dat file updated .";
ofs << x << " of Cylinder = " << y << "\n";
ofs.close();
}
void printToFile() {
printToFile("Surface Area: ", surfaceArea);
printToFile("Volume", volume);
}
void readFromFile(ifstream& input)
{
string data = "";
while (std::getline(input, data))
{
std::cout << data << endl;
}
}
};
In shape2d.h and shape3d.h with have to add
#include "shape.h"
In square.h and triangle.h with have to add
#include "shape2d.h"
In sphere.h and cylinder.h you have to add
#include "shape3d.h"
And to avoid multiple inclusions add at the beginning of each .h file
#pragma once
or if your compiler doesn't support it enclose the hole code inside any .h in something like
#ifndef YOUR_H_FILE_NAME_H
#define YOUR_H_FILE_NAME_H
// ... your .h code here
#endif
Further in main.cpp you include shapes.h which doesn't exist but you can remove it because you already include all the specilized .h file
I keep getting a compiler error at 6 points in my code that claim that a "reference to non-static member function must be called" in my Executive.cpp file, I can't figure out what the issue is but I believe it might be some sort of syntax error either in my Executive class or my ShapeContainer class. The ShapeContainer class just holds an array of various shapes from a Shape Interface that includes circles, triangles, and rectangles. Everything is read in from a file and the goal is to store the shapes from the file into the ShapeContainer class and then print certain areas the file says to do so.
Part of my Executive class and where the errors are:
//Executive.h
//...
class Executive
{
private:
int m_size;
int check;
ShapeContainer Shapes(int size);
ifstream inFile;
string FileName;
public:
Executive(string FileName);
void run();
};
//...
//Executive.cpp
//...
inFile.open(FileName);
int number;
inFile >> number;
while(check != 1)
{
string command = "";
int index = 0;
string shape = "";
double value1 = 0;
double value2 = 0;
inFile >> command >> index >> shape >> value1 >> value2;
if(command == "ADD")
{
if(shape == "CIRC")
{
Circle myCirc(value1);
try
{
Shapes.add(myCirc, index);//ERROR 1
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(shape == "TRI")
{
Triangle myTri(value1, value2);
try
{
Shapes.add(myTri(value1, value2), index);//ERROR 2
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(shape == "REC")
{
Rectangle myRect(value1, value2);
try
{
Shapes.add(myRect(value1, value2), index);//ERROR 3
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
}
else if(command == "DELETE")
{
try
{
Shapes.remove(index);//ERROR 4
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(command == "PRINT")
{
cout << "Shape at index " << index << ": ";
try
{
cout << Shapes.shapeName(index) << " area = ";//ERROR 5
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
try
{
cout << Shapes.area(index);//ERROR 6
}
catch(std::runtime_error& rte)
{
cout << rte.what() << "\n";
}
}
else if(command == "EXIT")
{
cout << "Exiting...\n";
check = 1;
}
}
inFile.close();
//...
Here is my ShapeContainer header file:
//ShapeContainer.h
#ifndef SHAPECONTAINER_H
#define SHAPECONTAINER_H
#include "Shape.h"
#include <stdexcept>
class ShapeContainer
{
public:
ShapeContainer(int size); //initialize pointers in m_arrayOfShapes to nullptr
~ShapeContainer();
double area(int index) const; //throws a std::runtime_error if index is invalid, meaning out of range OR index has nullptr
std::string shapeName(int index) const; //throws a std::runtime_error if index is invalid, meaning out of range OR index has nullptr
void add(Shape* shapePtr, int index); //throws a std::runtime_error if index is invalid OR if shapePtr is nullptr
void remove(int index); //throws a std::runtime_error if the index is invalid OR there is no object to delete
private:
Shape** m_arrayOfShapes;
int m_size;
};
#endif
And here is my Shape interface with an example of one of my shapes:
//Shape.h
#ifndef SHAPE_H
#define SHAPE_H
#include <string>
class Shape
{
public:
virtual double area() const = 0;
virtual std::string shapeName() const = 0;
virtual ~Shape() {}
};
#endif
//Circle.h
#ifndef CIRCLE_H
#define CIRCLE_H
#include "Shape.h"
class Circle:public Shape
{
public:
Circle(double radius);
double area()const;
std::string shapeName()const;
private:
double m_radius;
};
#endif
//Circle.cpp
#include "Circle.h"
Circle::Circle(double radius)
{
m_radius = radius;
}
double Circle::area()const
{
return((m_radius * m_radius) * 3.14);
}
std::string Circle::shapeName()const
{
return("Circle");
}
Here is the input file and my hopeful output:
//file.txt
5
ADD 0 CIR 5.5
ADD 1 TRI 2.5 6.6
PRINT 0
ADD 2 REC 10.5 20.25
PRINT 99
PRINT 2
EXIT
//output
Shape at index 0: Circle area = 95.0331
Shape at index 99: Does not exist
Shape at index 2: Rectangle area = 212.625
Exiting...
Can someone help me find the issue in my code here?
I keep getting an error that just says program terminated. It runs on certain ide's but not others, and it hurts because I felt like I was starting to grasp the concepts of OOP, but guess not. The main idea of the program is to read the shape data into a pointer array and then display all of the information about the shapes.
#include <iostream>
#include <fstream>
#include <iomanip>
using namespace std;
// Global constant for array size.
const int SIZE = 99;
// Base Class
class Shape
{
protected:
char type;
int serNo;
int dim1;
int dim2;
public:
// Default constructor
Shape()
{
type = ' ';
serNo = 0;
dim1 = 0;
dim2 = 0;
}
// Constructor #1
Shape(char t, int s, int d1, int d2)
{
type = t;
serNo = s;
dim1 = d1;
dim2 = d2;
}
// Get type
char getType()
{
return type;
}
// Get serial number
int getSerNo()
{
return serNo;
}
// Get dimension1
int getDim1()
{
return dim1;
}
// Get dimension2
int getDim2()
{
return dim2;
}
// Destructor
~Shape()
{}
};
// Circle Class (Derived from Shape)
class Circle : public Shape
{
public:
Circle(char t, int s, int d1, int d2) : Shape(t, s, d1, d2)
{}
};
// Spray Class (Derived from Circle)
class Spray : public Circle
{
public:
// Constructor
Spray(char t, int s, int d1, int d2) : Circle(t, s, d1, d2)
{}
};
// Rectangle Class (Derived from Shape)
class Rectangle : public Shape
{
public:
// Constructor
Rectangle(char t, int s, int d1, int d2) : Shape(t, s, d1, d2)
{}
};
// Square Class (Derived from Rectangle)
class Square : public Rectangle
{
public:
// Constructor
Square(char t, int s, int d1, int d2) : Rectangle(t, s, d1, d2)
{}
};
class mgrShape : public Shape
{
protected:
int recordCount;
Shape * shapeArr[SIZE] = {nullptr}; // Manager owns the main data
//structure
public:
// Constructor.
mgrShape()
{
populateShapeData();
}
// Populate the shapeArr from file.
void populateShapeData()
{
fstream inputFile;
string fileName = "shaperecords.txt";
inputFile.open(fileName);
while(inputFile >> type >> serNo >> dim1 >> dim2)
{
if (type == 'C')
shapeArr[recordCount] = new Circle(type, serNo, dim1, dim2);
else if (type == 'R')
shapeArr[recordCount] = new Rectangle(type, serNo, dim1, dim2);
else if (type == 'S')
shapeArr[recordCount] = new Spray(type, serNo, dim1, dim2);
else if (type == 'Q')
shapeArr[recordCount] = new Square(type, serNo, dim1, dim2);
recordCount++;
}
inputFile.close();
}
//Display all of the shapes.
void displayAll()
{
for (int i = 0; i < recordCount; i++)
{
if (shapeArr[i]->getType() == 'C')
{
cout << "Circle Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
else if (shapeArr[i]->getType() == 'R')
{
cout << "Rectangle Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
else if (shapeArr[i]->getType() == 'S')
{
cout << "\nSpray Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
else if (shapeArr[i]->getType() == 'Q')
{
cout << "Square Found!" << endl;
cout << shapeArr[i]->getType() << endl;
cout << shapeArr[i]->getSerNo() << endl;
cout << shapeArr[i]->getDim1() << endl;
cout << shapeArr[i]->getDim2() << endl;
}
}
}
// Clear the dynamically allocated memory from shapeArr.
~mgrShape()
{
for (int i = 0; i < recordCount; i++)
delete shapeArr[i];
}
};
int main()
{
mgrShape ms;
ms.displayAll();
return 0;
}
//And here's the input file's contents
//C 1001 30 -1
//R 1002 14 10
//S 1003 30 20
//Q 1004 28 -1
//S 1005 30 75
I get an exception on this line in Visual Studio 2015. It builds with no errors.
_free_dbg(block, _UNKNOWN_BLOCK);
This is how I declare the new array of pointers:
CAirship * pAirShip[10];
This is how I delete the array of pAirShip pointers:
for (int i = 0; i < 10; i++) {
if (pAirShip[i]) {
cout << "pAirShip[" << i << "] is " << pAirShip[i] << endl;
delete pAirShip[i];// Delete appropriate object
}
} // end for loop
I get an error on attempting to delete pAirShip[0],
Here is a debug window that does print the pointer addresses:
Here is the full code:
struct AirShipFile {
int Type; // Airplane or Balloon
string name; // Name of the airship
int passCount; // passenger count
int weightCargo; // cargo weight
int EngOrGas; // engine or gas type
int distance; // range or altitude
};
enum EngineType { Jet, Propeller }; // for airplanes only
std::ostream& operator<<(std::ostream& out, const EngineType value) {
static std::map<EngineType, std::string> strings;
if (strings.size() == 0) {
#define INSERT_ELEMENT(p) strings[p] = #p
INSERT_ELEMENT(Jet);
INSERT_ELEMENT(Propeller);
#undef INSERT_ELEMENT
}
return out << strings[value];
}
enum GasType {Helium, Hydrogen }; // for proprellers only
std::ostream& operator<<(std::ostream& out, const GasType value) {
static std::map<GasType, std::string> strings;
if (strings.size() == 0) {
#define INSERT_ELEMENT(p) strings[p] = #p
INSERT_ELEMENT(Helium);
INSERT_ELEMENT(Hydrogen);
#undef INSERT_ELEMENT
}
return out << strings[value];
}
enum AirShipType { AIRPLANE, BALLOON };
class CAirship {
public:
CAirship() { }
virtual void SetData(AirShipFile &data) = 0;
virtual void GetData() = 0;
AirShipType GetAirShipType() { return m_AirShipType; }
protected:
AirShipType m_AirShipType;
};
class CAIRPLANE : public virtual CAirship {
public:
CAIRPLANE() : CAirship() {}
void SetData(AirShipFile &data);
void GetData();
private:
EngineType m_EngineType;
int m_MaxPassengerCount;
string m_Name;
int m_MaxCargoWeight;
int m_MaxAltitude;
};
// Function: SetData
void CAIRPLANE::SetData(AirShipFile &data)
{
// cast integer to enum
m_EngineType = EngineType(data.EngOrGas);
// airplane name
m_Name = data.name;
// passenger count
m_MaxPassengerCount = data.passCount;
//max cargo weight
m_MaxCargoWeight = data.weightCargo;
// cast integer to enum
m_AirShipType = AirShipType(data.Type);
// maximum altitude
m_MaxAltitude = data.distance;
}
void CAIRPLANE::GetData()
{
cout << setw(20) << m_Name << "\t" << setw(20) << m_EngineType << setw(20);
cout << left << setw(20) << m_MaxAltitude << "\n";
}
class CBALLOON : public virtual CAirship {
public:
CBALLOON() : CAirship() {}
void SetData(AirShipFile &data);
void GetData();
private:
GasType m_GasType;
EngineType m_EngineType;
int m_MaxPassengerCount;
string m_Name ;
int m_MaxCargoWeight;
int m_MaxAltitude;
};
void CBALLOON::SetData(AirShipFile &data)
{
// cast integer to enum
m_GasType = GasType(data.EngOrGas);
// airplane name
m_Name = data.name;
// passenger count
m_MaxPassengerCount = data.passCount;
//max cargo weight
m_MaxCargoWeight = data.weightCargo;
// cast integer to enum
m_AirShipType = AirShipType(data.Type);
// maximum altitude
m_MaxAltitude = data.distance;
}
void CBALLOON::GetData()
{
cout << setw(20) << m_Name << "\t" << setw(20)<< m_GasType << setw(20);
cout << left << setw(20) << m_MaxAltitude << "\n";
}
// AIRPLANE = 0
// BALLOON = 1
int main(int argc, char *argv[])
{
if (argc != 2) {
cout << "Usage: PR <filename>\n";
return 1;
}
ifstream Infile(argv[1]);
if (!Infile) {
cout << "Cannot open file\n";
return 1;
}
char LineBuf[100];
char d[] = ",";
CAirship * pAirShip[10];
int i = 0;
while (Infile.getline(LineBuf, 100)) {
struct AirShipFile data;
// read the first field Airship type
// airplane or balloon
data.Type = atoi(strtok(LineBuf, d));
switch (data.Type) {
case AIRPLANE:
// Create AIRPLANE Object
pAirShip[i] = new CAIRPLANE();
data.name = strtok(NULL, d);
data.passCount = atoi(strtok(NULL, d));
data.weightCargo = atoi(strtok(NULL, d));
data.EngOrGas = atoi(strtok(NULL, d));
data.distance = atoi(strtok(NULL, d));
break;
case BALLOON:
// Create BALLOON Object
pAirShip[i] = new CBALLOON();
data.name = strtok(NULL, d);
data.passCount = atoi(strtok(NULL, d));
data.weightCargo = atoi(strtok(NULL, d));
data.EngOrGas = atoi(strtok(NULL, d));
data.distance = atoi(strtok(NULL, d));
break;
default:
break;
} // end switch
// call appropriate function
pAirShip[i++]->SetData(data);
memset(LineBuf, '\0', 100);
}
Infile.close();
cout << "Listing of all Airplanes \n";
cout << left << setw(20) << "\nName" << left<< setw(20)<<"\tEngine Type";
cout << left<<setw(20)<<"\Maximum Range" << "\n\n";
for (int i = 0; i < 10; i++) {
if (pAirShip[i]->GetAirShipType() == AIRPLANE)
pAirShip[i]->GetData();
}
cout << "\n\nListing of all Balloons \n";
cout <<left << setw(20) << "\nName" << left << setw(20) << "\tGas Type" ;
cout << left << setw(20) << "\Maximum Altitude" << "\n\n";
for (int i = 0; i < 10; i++) {
if (pAirShip[i]->GetAirShipType() == BALLOON)
pAirShip[i]->GetData();
}
for (int i = 0; i < 10; i++) {
if (pAirShip[i]) {
delete pAirShip[i];// Delete appropriate object
}
} // end for loop
return 0;
}
The problem is that when allocating an array of any kind, C++ does not initialize the elements, but leaves them with "random" values. So, when you create an array of pointers, the pointers are not created with NULL, nullptr or 0 value, so this is not a good indicator if they are really unused on its own. Trying to free the space that isn't allocated is what generates the error. You should first initialize them (by yourself in a for loop) with nullptr right after you create the array, then you can use your code for deleting the array of pointers.
This is the photo of the model I have to resolve:
I have this class:
#include<iostream>
#include<fstream>
using namespace std;
class Word
{
protected:
char *value;
char type[20];
int noChars;
static int noWords;
public:
Word(char *value, char *type)
{
this->noChars = 0;
this->value = new char[strlen(value) + 1];
strcpy(this->value, value);
strcpy(this->type, type);
Word::noWords++;
}
Word()
{
this->noChars = NULL;
this->value = NULL;
strcpy(this->type,"Nedeterminat");
}
void operator=(Word &x)
{
this->noChars = x.noChars;
strcpy(this->type, x.type);
this->value = new char[strlen(x.value) + 1];
strcpy(this->value, x.value);
}
Word(const Word& x){
this->noChars = x.noChars;
strcpy(this->type, x.type);
this->value = new char[strlen(x.value) + 1];
strcpy(this->value, x.value);
}
char* getValue()
{
return this->value;
}
void setType(char* x)
{
if (x == NULL)
{
throw new exception("Tip gresit!");
}
else
{
strcpy(this->type, x);
}
}
char &operator[](int i)
{
if (i >= 0 && i <= (strlen(this->value) - 1))
{
return this->value[i];
}
else
cout << endl << "Eroare indice: " << i;
}
static int getNoWords()
{
return Word::noWords;
}
operator int()
{
return this->noChars;
}
friend ostream& operator<<(ostream&, Word&);
friend istream& operator>>(istream&, Word&);
};
ostream& operator<<(ostream& consola, Word& x)
{
consola << "Value: " << x.getValue() << endl;
consola << "Type: " << x.type << endl;
consola << "NoChars: " << x.noChars << endl;
return consola;
}
istream& operator>>(istream& consola, Word& x){
cout << "Value: "; consola >> x.value;
cout << "Type: "; consola >> x.type;
cout << "NoChars: "; consola >> x.noChars;
return consola;
}
int Word::noWords = 0;
class Dictionary{
private:
char *language;
int noWords;
bool isOnline;
Word v[100];
public:
Dictionary(char *language, Word w, int noWords, bool isOnline)
{
this->language = new char[strlen(language) + 1];
strcpy(this->language, language);
for (int i = 0; i < 100; i++)
{
this->v[i] = w;
}
this->noWords = noWords;
this->isOnline = isOnline;
}
};
int main()
{
//1
Word w1("exam", "noun");
/*Word w2;*/
Word w3 = w1;
cout << w3;
//2
cout << endl << "Word value: " << w3.getValue();
Word w2("to take", "noun");
w2.setType("verb");
//3
w3 = w2;
cout << endl << w3;
Word *pw = new Word("pointer", "noun");
delete pw;
//4
cin >> w3; cout << w3;
char character = w3[2];
cout << endl << character;
//5
double noChars = (int)w1;
cout << endl << noChars;
cout << endl << Word::getNoWords() << endl;
//6
Dictionary dictionary1("English", NULL, 0, false);
}
I have this main:
Dictionary dictionary1("English", NULL, 0, false);
How should I change the constructor to work? I receive a error :
Arrgument types are:(const char[8],int,int,bool);
And how should I write the default constructor?
NULL cannot be assigned to Word. Try Word() instead which will call the default constructor to Word. Consider changing that function parameter to const Word& - anonymous temporaries are allowed to bind to const references.
I'd prefer to see a std::string as the type for the member variable language; using a const std::string& as the function parameter. Then you will not have to worry about a subsequent delete call, and defining your own assignment operators and copy constructors. Currently, your class leaks memory.
You can not Assign null to the type Word. If you want to default it you should pass something like word()
Dictionary dictionary1("English", word(), 0, false);
EDIT:
The better approach,IMO, that will work for the same main() you have is like this:
class Dictionary{
private:
std::string language;
int noWords;
bool isOnline;
std::array<Word,100> v;
public:
Dictionary(std::string const& language, Word* w, int noWords, bool isOnline): language (language),isOnline(isOnline ),noWords(noWords)
{
for (int i = 0; i < 100; i++){
this->v[i] = (w==NULL)?word():*w;
}
}
};