How to sort an object array - c++

I've created a class called Box that is pretty much what it sounds like. I want to sort these box objects, and I have created a function to do so.
void boxSort(Box array[], int size) {
Box temp;
bool swap;
do {
swap = false;
for(int count=0; count<(size-1); count++) {
int volume1 = array[count].getVolume(array[count].height, array[count].width, array[count].length);
int volume2 = array[count+1].getVolume(array[count+1].height, array[count+1].width, array[count+1].length);
if(volume1 > volume2) {
temp = array[count];
array[count] = array[count+1];
array[count+1] = temp;
swap = true;
}
}
}
while(swap);
}
This function sorts an array of objects of class Box.
Box class:
class Box {
public:
double height, width, length;
double getVolume(double, double, double);
double getSurfaceArea(double, double, double);
void setHeight(double);
void setWidth(double);
void setLength(double);
Box() {
height = width = length = 1;
}
Box(double h, double w, double l) {
setHeight(h);
setWidth(w);
setLength(l);
}
};
#endif
void Box::setHeight(double h) {
height = h;
}
void Box::setWidth(double w) {
width = w;
}
void Box::setLength(double l) {
length = l;
}
double Box::getVolume(double h, double w, double l) {
double volume = h*w*l;
return volume;
}
double Box::getSurfaceArea(double h, double w, double l) {
double surfaceArea = (h*w)*2 + (h*l)*2 + (l*w)*2;
return surfaceArea;
}
When I run this program I get an error:
linker command failed with exit code 1
This doesn't shown up on any particular line, and I have no idea what it means, so I'm a little lost on how to debug this.

The linker errors are reported if you have any problem with libraries or object files linked. Were you able to successfully build the executable?

I think this error is occurring due to more than one main() function in your code.You can have only one main() function.

Not sure about the error. But I would suggest changing boxSort function to something like this.
change getVolume to this
double Box::getVolume() {
return height*width*length;
}
and boxSort to this
void boxSort(std::array<Box, 3> boxes)
{
struct
{
bool operator()(Box x, Box y)
{
return x.getVolume() < y.getVolume();
}
}compFunc;
std::sort(boxes.begin(), boxes.end(), compFunc);
for(Box a: boxes)
{
std::cout<<a.getVolume()<<" ";
}
}
function call:
std::array<Box,3> boxes = {box1, box2, box3};
boxSort(boxes);

Related

Deep copy unsuccessful

might be a stupid question and if it is, let me know, I will delete it as soon as possible. The thing is I have to make a deep copy in class "Kambarys" (ignore mixed languages, I know I shouldn't do that). Program terminates after trying to call function second time. Probably the problem is my syntax in constructor copy, but I can't find the correct one anywhere. One of the requirements is to create langas, durys and kambarys in dynamic memory using "new" and delete windows vector and door in Kambarys destructor. Appreciate the help!
Requirements:
In the main method, use the new operator to create room k1, add windows and doors to it. Write a constructor Room (const Room & k) that would create a correct copy. In the method main, write another room k2. Calculate the length of the baseboards / wall area.
Perform the following steps: k2 = * k1; delete k1;
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
class Langas{
private:
float height;
float widht;
static int countL;
public:
Langas(float h, float w){
this->height=h;
this->widht=w;
countL++;
}
~Langas(){
--countL;
}
float getHeight(){
return height;
}
float getWidht(){
return widht;
}
static int getWindowCount(){
return countL;
}
};
class Durys{
private:
float heightD;
float widhtD;
static int countD;
public:
Durys(float hD, float wD){
this->heightD=hD;
this->widhtD=wD;
countD++;
}
~Durys(){
--countD;
}
float getHeightD(){
return heightD;
}
float getWidhtD(){
return widhtD;
}
static int getDoorCount(){
return countD;
}
};
class Kambarys{
private:
float heightK;
float widhtK;
float lenghtK;
public:
vector<Langas*> windows;
Durys* door;
Kambarys(float hK, float wK, float lK){
this->heightK=hK;
this->widhtK=wK;
this->lenghtK=lK;
}
Kambarys(const Kambarys &k){
this->door=k.door;
this->windows=k.windows;
heightK=k.heightK;
widhtK=k.widhtK;
lenghtK=k.lenghtK;
}
~Kambarys(){
door=NULL;
for(int i=0; i<windows.size(); i++){
delete windows[i];
}
windows.clear();
delete door;
}
float getHeightK(){
return heightK;
}
float getWidhtK(){
return widhtK;
}
float getLenghtK(){
return lenghtK;
}
void addWindow(Langas* w){
windows.push_back(w);
}
void addDoor(Durys *d){
door=d;
}
};
float countWallPlot(Kambarys* k){
float cWPlot=(2*k->getLenghtK()*k->getHeightK())+(2*k->getWidhtK()*k->getHeightK());
for(int i=0; i<k->windows.size(); i++){
cWPlot-=((k->windows[i]->getHeight()))*(k->windows[i]->getWidht());
}
cWPlot-=((k->door->getHeightD()))*(k->door->getWidhtD());
return cWPlot;
}
float countLenght(Kambarys* k){
float floorL=(k->getLenghtK()*k->getWidhtK()*2);
floorL-=(k->door->getWidhtD());
return floorL;
}
int Langas::countL=0;
int Durys::countD=0;
int main(){
Langas *langas1=new Langas(3.4, 1.2);
Durys *durys=new Durys(3.1, 1.5);
Langas *langas2=new Langas(6.4, 1.5);
Kambarys *k=new Kambarys(30.4, 40.1, 50.1);
Kambarys *k2=k;
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
cout<<countWallPlot(k)<<" "<<countLenght(k)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
k2=k;
delete k;
cout<<countWallPlot(k2)<<" "<<countLenght(k2)<<endl;
cout<<"Window count "<<Langas::getWindowCount()<<", door count "<<Durys::getDoorCount()<<endl;
}
You have to allocate memory for k2 and copy the object, not the pointer.
You have to allocate memory in the copy constructor and copy assignment operator.
door=NULL; before delete door; would skip the delete and cause a memory leak.
windows.clear(); is not necessary in the destructor. Keep your code simple.
EDIT: After you added "Perform the following steps: k2 = * k1; delete k1;" I made k2 an object, not a pointer.
#include <iostream>
#include <vector>
class Langas {
private:
float height;
float width;
static int count;
public:
Langas(float h, float w): height(h), width(w) {
++count;
}
~Langas() { --count; }
float getHeight() const { return height; }
float getWidht() const { return width; }
static int getWindowCount() { return count; }
};
class Durys {
private:
float height;
float width;
static int count;
public:
Durys(float h, float w): height(h), width(w) {
++count;
}
~Durys() { --count; }
float getHeight() const { return height; }
float getWidth() const { return width; }
static int getDoorCount() { return count; }
};
class Kambarys {
private:
float height;
float width;
float length;
public:
std::vector<Langas *> windows;
Durys *door = nullptr;
Kambarys(float hK, float wK, float lK): height(hK), width(wK), length(lK) {}
Kambarys(const Kambarys &k): height(k.height), width(k.width), length(k.length), windows(), door(k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr) {
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
}
Kambarys &operator=(const Kambarys &k) {
door = k.door ? new Durys(k.door->getHeight(), k.door->getWidth()) : nullptr;
for (const auto window : k.windows) {
windows.emplace_back(new Langas(window->getHeight(), window->getWidht()));
}
height = k.height;
width = k.width;
length = k.length;
return *this;
}
~Kambarys() {
for (auto window : windows) {
delete window;
}
delete door;
}
float getHeight() const { return height; }
float getWidth() const { return width; }
float getLength() const { return length; }
void addWindow(Langas *w) { windows.emplace_back(w); }
void addDoor(Durys *d) { door = d; }
};
float countWallPlot(const Kambarys &k) {
float cWPlot = 2 * k.getLength() * k.getHeight() + 2 * k.getWidth() * k.getHeight();
for (const auto window : k.windows) {
cWPlot -= window->getHeight() * window->getWidht();
}
cWPlot -= k.door->getHeight() * k.door->getWidth();
return cWPlot;
}
float countLength(const Kambarys &k) {
float floor = k.getLength() * k.getWidth() * 2;
floor -= k.door->getWidth();
return floor;
}
int Langas::count = 0;
int Durys::count = 0;
int main() {
Langas *langas1 = new Langas(3.4, 1.2);
Durys *durys = new Durys(3.1, 1.5);
Langas *langas2 = new Langas(6.4, 1.5);
Kambarys *k = new Kambarys(30.4, 40.1, 50.1);
Kambarys k2(*k);
k->addWindow(langas1);
k->addWindow(langas2);
k->addDoor(durys);
std::cout << countWallPlot(*k) << " " << countLength(*k) << std::endl;
k2 = *k;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
delete k;
std::cout << countWallPlot(k2) << " " << countLength(k2) << std::endl;
std::cout << "Window count " << Langas::getWindowCount() << ", door count " << Durys::getDoorCount() << std::endl;
}

I am getting an error in typecasting, please help me out with this

Create a class Rectangle. This class has attributes length and width each of which defaults to 1. It has methods that calculate the perimeter and area of the rectangle. It has set and get methods for both length and width. The set methods should verify that length and width are floating – point nos larger than 0.0 and less than 20.0.
#include<iostream>
using namespace std;
class rect
{
float l;
float w;
public:
void setlw();
float getl(float len);
float getw(float width);
void seta();
void setp();
};
void rect:: setlw()
{
cout<<"enter the lenght and width"<<endl;
cin>>l>>w;
}
float rect:: getl(float len)
{
if (l>=0.0 && l<=20.0)
len=l;
else
len=1.0;
return(len);
}
float rect:: getw(float width)
{
if(w>=0 && w<=20.0)
width=w;
else
width=1.0;
return(width);
}
void rect::seta()
{
float a;
a=l*w;
cout<<"the area is"<<a<<endl;
}
void rect:: setp()
{
float p;
p=2*(l+w);
cout<<"the perimeter is"<<p<<endl;
}
int main()
{
rect r;
r.setlw();
cout<<"length is"<<r.getl(float)<<endl;
cout<<"width is"<<r.getw(float)<<endl;
r.seta();
r.setp();
return (0);
}
I have corrected your code. Removed the input parameters for getl() and getw(), as it's not required when you are taking input with setlw() . You've also not declared variables len and width in functions getl and getw.
New Code:
#include<iostream>
using namespace std;
class rect
{
float l;
float w;
public:
void setlw();
float getl();
float getw();
void seta();
void setp();
};
void rect::setlw()
{
cout<<"enter the lenght and width"<<endl;
cin>>l>>w;
}
float rect::getl()
{ float len;
if (l>=0.0 && l<=20.0)
len=l;
else
len=1.0;
return(len);
}
float rect::getw()
{ float width;
if(w>=0 && w<=20.0)
width=w;
else
width=1.0;
return(width);
}
void rect::seta()
{
float a;
a=l*w;
cout<<"the area is"<<a<<endl;
}
void rect::setp()
{
float p;
p=2*(l+w);
cout<<"the perimeter is"<<p<<endl;
}
int main()
{
rect r;
r.setlw();
cout<<"length is"<<r.getl()<<endl;
cout<<"width is"<<r.getw()<<endl;
r.seta();
r.setp();
return (0);
}

How to fix class function "prototype does not match" and "cadidate is" errors

I'm desperately trying to finish this last assignment, and I'm at a complete loss for what these errors are trying to tell me to do. The errors are as such:
"prototype for 'double Rectangle::calculateArea()' does not match any in class 'Rectangle'" (line 40)
"candidate is: int Rectangle::calculateArea()" (line 11)
"prototype for 'double Rectangle::calculatePerimeter()' does not match any in class 'Rectangle'" (line 45)
"candidate is: int Rectangle::calculatePerimeter()" (line 12)
This is my first post on this forum, so I apologize in advance for it being ill-formatted
I haven't tried anything because none of the solutions I've found on forums relate directly to my problem (or so I think).
Thank you
// Rectangle.cpp
using namespace std;
class Rectangle
{
public:
void setLength(double length);
void setWidth(double width);
double getLength();
double getWidth();
int calculateArea() {return width*length;}
int calculatePerimeter() {return (width*2) + (length*2);}
private:
double length;
double width;
};
void Rectangle::setLength(double len)
{
len = length;
}
void Rectangle::setWidth(double wid)
{
wid = width;
}
double Rectangle::getLength()
{
return length;
}
double Rectangle::getWidth()
{
return width;
}
double Rectangle::calculateArea()
{
return (width*length)
}
double Rectangle::calculatePerimeter()
{
return ((width*2) + (length*2))
}
You already defined the functions in the class definition with a wrong return type (int instead of double)
class Rectangle
{
//...
int calculateArea() {return width*length;}
int calculatePerimeter() {return (width*2) + (length*2);}
//..
};
And then you redefined them outside the class
double Rectangle::calculateArea()
{
return (width*length)
}
double Rectangle::calculatePerimeter()
{
return ((width*2) + (length*2))
}
Also these functions are defined incorrectly
void Rectangle::setLength(double len)
{
len = length;
^^^^^^^^^^^^
}
void Rectangle::setWidth(double wid)
{
wid = width;
^^^^^^^^^^^
}
They must be defined like
void Rectangle::setLength(double len)
{
length = len;
}
void Rectangle::setWidth(double wid)
{
width = wid;
}
And all these functions
double getLength();
double getWidth();
int calculateArea() {return width*length;}
int calculatePerimeter() {return (width*2) + (length*2);}
should be declared with the qualifier const
double getLength() const;
double getWidth() const;
double calculateArea() const {return width*length;}
^^^^^^
double calculatePerimeter() const {return (width*2) + (length*2);}
^^^^^^
The compiler literally tells you!
It says that these two things don't match:
int Rectangle::calculateArea()
double Rectangle::calculateArea()
And, well, that's true. Your return types differ.
Pick one and use it consistently.

Too few arguments in function call C++

Hello I am a student learning c++ and I am just starting to learn OOP. The problem is in my MAIN however I am showing all of my files in case it is from another file.
I have written my hpp and cpp file and now I am just working on my main for testing. The class is called Box and when I create an object box1 or box 2 and attempt to access my functions it says there are two few arguments. It says this regardless of whether I put box1.calcVolume(double h, double w, double l) or box1.calcVolume();
So the issue is on the line(s) that say:
double volume2 = box2.calcVolume();
double volume1 = box1.calcVolume();
double surfaceArea1 = box1.calcSurfaceArea();
If anyone can spot something that I missing our may not understand please let me know.
This is the header file:
#pragma once
#include <iostream>
#ifndef BOX_HPP
#define BOX_HPP
class Box
{
private:
double height;
double width;
double length;
public:
void setHeight(double h);
void setWidth(double w);
void setLength(double l);
double calcVolume(double h, double w, double l);
double calcSurfaceArea(double h, double w, double l);
Box();
Box(double height, double width, double length);
};
#endif
This is the CPP file
#include <iostream>
#include "Box.hpp"
Box::Box()
{
setHeight(1);
setWidth(1);
setLength(1);
}
Box::Box(double h, double w, double l)
{
setHeight(h);
setWidth(w);
setLength(l);
}
void Box::setHeight(double h)
{
height = h;
}
void Box::setWidth(double w)
{
width = w;
}
void Box::setLength(double l)
{
length = l;
}
double Box::calcVolume(double h, double w, double l)
{
double volume;
volume = h * w * l;
return volume;
}
double Box::calcSurfaceArea(double h, double w, double l)
{
double surfaceArea;
surfaceArea = 2 * (h*w) + 2 * (h*l) + 2 * (l*w);
return surfaceArea;
}
my BoxMain file:
#include <iostream>
#include "Box.hpp"
using std::cout;
using std::cin;
using std::endl;
int main()
{
Box box1(1.1, 2.4, 3.8);
Box box2;
box2.setHeight(12);
box2.setWidth(22.3);
box2.setLength(2.3);
double volume2 = box2.calcVolume();
double volume1 = box1.calcVolume();
double surfaceArea1 = box1.calcSurfaceArea();
cout << box1.calcVolume(); << endl; //testing different methods
return 0;
}
Your method takes three parameters:
double Box::calcVolume(double h, double w, double l)
{
double volume;
volume = h * w * l;
return volume;
}
So, you would call it like so:
Box b;
double volume = b.calcVolume(1, 2, 3);
But that's not quite right. An instance of Box knows how big it is, because you pass a size to the constructor, which stores the sizes in the fields width, height, and length. You probably want something like this:
double Box::calcVolume()
{
volume = height * width * length;
return volume;
}
You have the code wrong. The dimensions of the box are known during the creation of box object. The length, width and height are already available - updated in the member variables.
Functions calcVolume and calcSurfaceArea should not take arguments but return the computed value. Modified code below:
double Box::calcVolume()
{
return height*width*length;
}
double Box::calcSurfaceArea()
{
return 2*((height*width) + (height*length) + (length*width));
}
Also, remember to modify the .hpp file with the declarations corresponding to the code above.
Declaration in the .hpp file should be
double calcVolume();
double calcSurfaceArea();
I have solved the problem. I removed the arguments in calcVolume and calcSurfaceArea everywhere in my code and it resolved the error.

My object is being destructed right after being constructed

I'm trying to construct a two-dimensional boolean array with a class I've created called Grid. The Grid object is a private member class of another class called GameOfLife. Whenever I create a GameOfLife object with the parameters belove, the Grid object first gets created with the default constructor, then it gets created again with the constructor with parameters, and then for some reason Grid's deconstructor runs and deletes everything ? I'm really out of ideas :p I'm running MinGW GCC on Eclipse Luna.
Main.cpp
const int HEIGHT = 25;
const int WIDTH = 25;
#include <iostream>
#include "GameOfLife.h"
int main(int argc, const char * argv[]) {
GameOfLife game = GameOfLife(HEIGHT, WIDTH, false);
game.play();
return 0;
}
Grid.h
#ifndef __Game_Of_Life__Grid__
#define __Game_Of_Life__Grid__
#include <stdio.h>
class Grid {
public:
Grid(int y, int x, bool state);
Grid();
void allocate(int x, int y, bool state);
void deallocate();
void set(int x, int y, bool state);
bool get(int x, int y);
void setAll(bool state);
void switchBoards();
~Grid();
private:
bool ** oldGeneration;
bool ** newGeneration;
int height;
int width;
};
#endif /* defined(__Game_Of_Life__Grid__) */
Grid.cpp
#include "Grid.h"
Grid::Grid(int y, int x, bool state) {
allocate(x, y, state);
}
void Grid::allocate(int x, int y, bool state) {
height = y;
width = x;
oldGeneration = new bool*[height];
newGeneration = new bool*[height];
for (int i = 0; i < height; i++) {
oldGeneration[i] = new bool[width];
newGeneration[i] = new bool[width];
}
}
Grid::~Grid() {
deallocate();
}
void Grid::switchBoards() {
bool ** temp = oldGeneration;
oldGeneration = newGeneration;
newGeneration = temp;
delete temp;
}
bool Grid::get(int x, int y) {
return oldGeneration[y][x];
}
void Grid::set(int x, int y, bool state) {
newGeneration[y][x] = state;
}
void Grid::deallocate() {
if (oldGeneration != NULL || newGeneration != NULL) {
for (int i = 0; i < height; i++) {
delete [] oldGeneration[i];
delete [] newGeneration[i];
}
delete [] oldGeneration;
delete [] newGeneration;
}
return;
}
Grid::Grid() {
oldGeneration = NULL;
newGeneration = NULL;
width = 0;
height = 0;
}
void Grid::setAll(bool state) {
for (int i = 0; i < height; i++) {
for (int n = 0; n < width; n++) {
newGeneration[i][n] = state;
}
}
}
GameOfLife.h
#ifndef __Game_Of_Life__GameOfLife__
#define __Game_Of_Life__GameOfLife__
#include <stdio.h>
#include "Grid.h"
#include <iostream>
class GameOfLife {
private:
Grid board;
public:
GameOfLife(int y, int x, bool state);
GameOfLife();
~GameOfLife();
void play();
void welcome();
void makeBoard();
void updateBoard();
int findAliveNeighbours(int x, int y);
};
#endif /* defined(__Conway__GameOfLife__) */
GameOfLife.cpp
#include "GameOfLife.h"
const int WIDTH = 100;
const int HEIGHT= 75;
GameOfLife::GameOfLife(int y, int x, bool state) {
board = Grid(y, x, state);
}
GameOfLife::GameOfLife() {
board = Grid();
}
GameOfLife::~GameOfLife() {
board.deallocate();
}
void GameOfLife::play() {
welcome();
makeBoard();
for (int i = 0; i < HEIGHT; i++) {
for (int n = 0; n < WIDTH; n++) {
std::cout << board.get(n,i) << " ";
}
std::cout << std::endl;
}
updateBoard();
std::cout << std::endl;
for (int i = 0; i < HEIGHT; i++) {
for (int n = 0; n < WIDTH; n++) {
std::cout << board.get(n,i) << " ";
}
std::cout << std::endl;
}
}
void GameOfLife::makeBoard() {
int x1,x2,x3,x4, y1,y2,y3,y4;
x1 = 10; y1 = 10;
x2 = 10; y2 = 11;
x3 = 10; y3 = 12;
x4 = 11; y4 = 13;
int x5 = 0; int y5 = 0;
board.set(x1, y1, true);
board.set(x2, y2, true);
board.set(x3, y3, true);
board.set(x4, y4, true);
board.set(x5, y5, true);
}
void GameOfLife::welcome() {
std::cout << "Welcome to Conway's Game Of Life"
<< std::endl;
}
GameOfLife::GameOfLife(int y, int x, bool state) {
// board is a member variable that gets initialized
// with the default constructor.
// Then it gets replaced by assignment with a different
// Grid object. The temporary object gets deleted at
// the end of the line.
board = Grid(y, x, state);
}
Change the implementation to:
GameOfLife::GameOfLife(int y, int x, bool state) : board(y, x, state) {}
Similarly, change the default constructor to:
GameOfLife::GameOfLife() {}
The more important problem that needs to be fixed is that you are breaking The Rule of Three.
You need to add proper implementations of the copy constructor and the copy assignment opertor in Grid.
The other, and better, option is to change the internal data of Grid to
std::vector<std::vector<bool>> oldGeneration;
std::vector<std::vector<bool>> newGeneration;
Then, the compiler generated copy constructor and copy assignment operator will be good enough.