Dynamic array in classes c++ [SOVED] - c++

I created a header file polygon.h and a polygon.cpp
polygon.h:
#pragma once
#include <iostream>
using namespace std;
class Polygon {
protected:
int numSides;
int* sides;
public:
Polygon(int nSides);
Polygon(const Polygon&);
~Polygon();
int getNumOfSides();
int perimeter(); // perimeter = hekef
bool operator==(Polygon);
};
polygon.cpp:
#include <iostream>
#include "Polygon.h"
using namespace std;
Polygon::Polygon(int nSides) {
this->numSides = nSides;
this->sides = new int[nSides];
if (nSides != 3 && nSides != 4)
{
cout << "Enter sides for polygon: " << endl;
for (int i = 0; i < nSides; i++)
cin >> this->sides[i];
}
};
Polygon::Polygon(const Polygon& other) {
this->numSides = other.numSides;
this->sides = new int[other.numSides];
for (int i = 0; i < this->numSides; i++)
this->sides[i] = other.sides[i];
};
Polygon::~Polygon() {
delete [] this->sides;
};
int Polygon::getNumOfSides() {
return this->numSides;
};
int Polygon::perimeter() {
int sum = 0;
for (int i = 0; i < this->numSides; i++)
sum += this->sides[i];
return sum;
};
bool Polygon::operator==(Polygon other) {
return (this->getNumOfSides() == other.getNumOfSides() && this->perimeter() == other.perimeter());
};
I'v created a Main file as well but it doesn't matter.
The problem is when I'm passing in for example into numSides the value 5 and the program should make from sides a new dynamic int array with 5 slots as for this example, but instead, while debugging it I find out that it creates only 1 slot as if it is just a regular integer and when I set in the 5 values into sides (as for this example with 5), sides ends up containing only the first value I have entered.
I will be happy if someone will help and even solve this problem :)

You didn’t say what debugger you are using, but for Visual Studio you can manually edit the debugger entry to be:
<pointer>, <size>
So in this case you’d say:
sides, 5
See this page for more info:
https://support.microsoft.com/en-us/help/198953/how-to-expand-an-array-pointer-in-the-visual-c-debugger-watch-window

As WhozCraig and 1201ProgramAlarm stated about std::vector in the comments above:
The debugger only knows that sides is a pointer, and doesn't know how many elements it points to. If you use std::vector you'd be able to see all of the points.
Stating the obvious, std::vector<int> sides; rather than manual memory management would make this trivial, and as a bonus, eliminates the need for a numSides member as well. That said, you're usage from the "calling" code is relevant. It should be included in your question. You're also missing a copy-assignment operator, therefore introducing a recipe for a rule of three violation. Things to work on.
The fact I didn't see all of the slots is because I'm used to c# and less working with pointers, and the int pointer was pointing on the start of the array.

Related

computer lab with pointers

I have this assignment with managing computer labs. Specifically, there are 4 labs, each has a different number of computers. Hence, I want to create a 2D array with pointers, but after trying different stuff, I count on you for this error (please!!!). Below is a part of my programme, up to where the annoying bug comes up.
I got a run-time error after 1 run (terminate called after throwing an instance of std::bad_array_new_length what(): std::bad_array_new_length) when I leave the line with comment //PROBLEM HERE as such.
Add a & in front of lab room, the compiler gave me the error: lvalue required as left operand of assignment.
Newbie in C++, first time with pointers, I'd appreciate any help.
#include <iostream>
using namespace std;
//Global variables
const int SIZE = 4;
typedef int* Stations;
Stations *labroom;
//Function declaration:
void numberOfComputers();//Receive number of computers in each lab
int menu();//Display menu options for users
void menu_processor(int option);//process user's option
int main()
{
numberOfComputers();
menu();
menu_processor(menu());
return 0;
}
void numberOfComputers ()
{ char ans;
for (int i=0;i<SIZE;i++)
{
cout<<"Enter the number of computer stations in lab "<<i+1<<": ";
do
{
cin.get(ans);
} while (ans!='\n');
labroom [i] = new int [ans-'0'];//PROBLEM HERE
cout<<"\n";
}
}
That's not c++ code, it's just (ugly) C.
In C++ we have array for static arrays and vector for dynamic arrays.
First of all, choose the name of your variables or function in a smart way: prefer getNumberOfComputersFromUser instead of numberOfComputers. What numberOfComputers means? A function name must describe what it is doing.
Here a simplified snippet:
#include <vector>
#include <array>
#include <iostream>
using namespace std;
using Station = int;
using LabRooms = array<vector<Station>, 4>;
LabRooms getNumberOfComputersFromUser()
{
LabRooms labRooms;
int roomIndex = 0;
for(auto& computersInLab : labRooms)
{
cout << "Enter the number of computer stations in lab " << ++roomIndex << ": ";
auto computerCount = 0;
cin >> computerCount;
computersInLab.resize(computerCount);
}
return labRooms;
}
Explain
array requires two template arguments: the type and the size. Elements are statically allocated, no need to new because we already know how many rooms we have. The list of computers in each room is not know so we use vector that can dynamically increase or decrease.
using LabRooms = array<vector<Station>, 4>; it's the same of typedef array<vector<Station>, 4> LabRooms but it's clearer I think
for( auto& computersInLab : labRooms) iterate over labRooms and get a reference to its elements (in this case a reference to a vector of Station. This is the same of:
for(int i = 0; i < labRooms.size(); ++i)
{
auto& computersInLab = labRooms[i];
...
}
computersInLab.resize(computerCount); resize the list of computers with the value specified from the user.
Now, labRooms is an array of 4 elements, each element is a list of Station.

Error in Returning a Class Object in C++

I've been working on a Matrix library for personal use lately. I've tried writing code that returns my Matrix class (such as operator overloads, transformations, and inversions), but a strange error occurs. Visual Studio says that it throws a break point, possibly due to a corrupted heap, and then it says something about a debug error. I've tried several members of my code, and only the code that returns a Matrix fails in this manner.
I was thinking about passing a preallocated object's pointer through the member's arguments, but that just doesn't work with the operator overloads apparently. Any help?
Here are the error messages:
Windows has triggered a breakpoint in Project Sapphire.exe.
This may be due to a corruption of the heap, which indicates a bug in
Project Sapphire.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while Project
Sapphire.exe has focus."
"Debug Assertion Failed!
Program: ...\Desktop\Programs\Project Sapphire\Debug\Project
Sapphire.exe file: minkernal\crts\ucrt\src\appcrt\heap\debug_heap.cpp
line 888
Expression: _CrtlsValidHeapPointer(block)
For information on how your program can cause an assertion failure,
see the Visual C++ documentation on asserts
(Press Retry to debug the application)
Here's the code:
Matrix.h
#pragma once
#include "stdafx.h"
#include <vector>
class Matrix
{
private:
std::vector<std::vector<float>> data;
public:
std::vector<int> getSize();
//Operator overloads
std::vector<float> operator[](int index);
Matrix operator+(const Matrix& fuz);
//Constructor and destructor
Matrix(int dim1, int dim2);
~Matrix();
};
Matrix.cpp
#include "stdafx.h"
#include "Matrix.h"
std::vector<int> Matrix::getSize() //This seems to work well
{
std::vector<int> size(2);
size[0] = data.size();
size[1] = (data.size() >= 1 ) ? data[0].size() : 0; //Makes sure to not try to access an empty vector
return size;
}
//Operator Overloads
std::vector<float> Matrix::operator[](int index)
{
return data.at(index); //Does the same thing as data[], from what I can tell
}
Matrix Matrix::operator+(const Matrix& fuz)
{
if (( fuz.data.size() == this->getSize()[0]) && (fuz.data[0].size() == this->getSize()[1])) //Makes sure that the matrix dimensions align
{
Matrix ret = *this; //The return matrix. Starts out as a copy of this matrix
for (int i = 0; i < this->getSize()[0]; i++)
{
for (int j = 0; j < (int) this->getSize()[1]; j++)
{
ret[i][j] += fuz.data[i][j]; //Goes through and adds the two matrices
}
}
return ret; //Error happens HERE
}
return Matrix(1, 1); //Otherwise, return a scalar
}
//Constructor and Destructor
Matrix::Matrix(int dim1, int dim2)
{
data.resize(dim1); //Allocate the first dimension of the matrix
for (int i = 0; i < dim1; i++) //Allocate the second dimension of the matrix
data[i].resize(dim2);
}
Matrix::~Matrix()
{
for (int i = 0; i < this->getSize()[0] - 1; i++) //Destruct each vector inside of the vector
data[i].~vector();
data.~vector(); //Delete the actual data
delete[] & data; //Finally, delete data
}
ProjectSapphire.cpp
// Project Sapphire.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <windows.h>
#include <iostream>
//#include "Node.h"
#include "Matrix.h"
//namespace SWF = System::Windows::Forms;
int main()
{
Matrix test(2,3);
int size[] = { test.getSize()[0], test.getSize()[1] };
test[0][0] = 1;
test[0][1] = 2;
test[0][2] = 3;
test[1][0] = 4;
test[1][1] = 5;
test[1][2] = 6;
Matrix foo = test;
Matrix deet = foo + test;
return 0;
}
The code in your destructor is utter nonsense. It is probably the source of your problem.
Remove all of the code in the destructor (preferably, remove the destructor entirely).
At a quick glance, your code looks OK apart from that.
It causes undefined behaviour to invoke the destructor twice for a vector. (The destructor of member variables is invoked by the compiler after the class's destructor, if any, finishes).
Just never call destructor manually. Read about RAII. All objects are destructed automatically.
Maybe Matrix's copy/move constructor is broken/deleted/private.

Array elements of a class object are not being set correctly, set() and get() member functions likely cause

This is my first time working with classes in C++ and I seem to be getting tripped up quite a lot. My program is supposed to be a rewrite of a previous program that used struct (see here: Random number generator in a for loop gives same numbers each time), but using a class instead.
#include <iostream>
#include <string>
#include <cstdlib>
#include <ctime>
using namespace std;
const int WHEEL_POSITIONS = 30;
const char wheelSymbols[WHEEL_POSITIONS + 1] = "-X-X-X-X-X=X=X=X*X*X*X*X#X#X7X";
class slotMachine
{
private:
int spinPos;
char spinSymbol;
public:
slotMachine(); // Constructor
char symbols[WHEEL_POSITIONS + 1]; // Should be private?
void setSpinSymbol(); // Spins the wheels
char getSpinSymbol() const // Returns the symbol
{ return spinSymbol; }
} wheels[3];
// Constructor initializes slot wheels to contents of wheelSymbols
slotMachine::slotMachine()
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < (WHEEL_POSITIONS + 1); j++)
{
wheels[i].symbols[j] = wheelSymbols[j];
}
}
}
void slotMachine::setSpinSymbol()
{
for (int i = 0; i < 3; i++)
{
wheels[i].spinPos = (rand() % WHEEL_POSITIONS);
wheels[i].spinSymbol = wheels[i].symbols[(wheels[i].spinPos)];
}
}
void displayResults(slotMachine fwheels[3])
{
for (int i = 0; i < 3; i++)
{
cout << fwheels[i].getSpinSymbol();
}
}
void displayResults(slotMachine []);
//bool getWinner(slotMachine []);
int main(void)
{
slotMachine wheels[3];
time_t seed;
time(&seed);
srand(seed);
displayResults(wheels);
return 0;
}
The code compiles but outputs the following:
I have a feeling this error is caused by something having gone amiss in my constructor slotMachine, my getSpinSymbol() function, or my setSpinSymbol() function, but I've looked it over several times and can't seem to figure it out. I've read a handful of material online covering classes in C++, but I'm still very new and very shaky on the concept--apologies if it's something small or obvious that I've overlooked.
There are several issues with your code:
1.Class names should be started with upper case letter. slotMachine -> SlotMachine
2.Remove wheels[3] after class definition.You are using the array declared in main() method.
3.Why you are declaring displayResults(..) again after it's definition?
4.You are not calling setSpinSymbol() before displayResults(..).
The problem was explained to me by a friend not on StackOverflow, and I will transcribe his answer here in case anyone else (for any reason) runs into the same problem:
You aren't using constructors and methods correctly. You shouldn't be
accessing wheels (the array of slotMachine objects) directly inside
those methods; you should just be performing operations on "this," the
slotMachine object on which the method was called. For example, the
constructor slotMachine::slotMachine() is automatically called for
each element of the array wheels. You just need to initialize the
current slotMachine object inside the constructor:
slotMachine::slotMachine()
{
for (int j = 0; j < (WHEEL_POSITIONS + 1); j++)
{
this->symbols[j] = wheelSymbols[j];
}
}
And slotMachine::setSpinSymbol() should just set the value of
spinSymbol for the object on which the method was called:
void slotMachine::setSpinSymbol()
{
this->spinPos = (rand() % WHEEL_POSITIONS);
this->spinSymbol = symbols[this->spinPos];
}
(In all of this code, the this-> part is actually unnecessary; you
can leave it out if you want. I put it in to try to make it clearer
that these methods are operating on fields of "the current object.")
Now, the reason you are getting garbage is because you never call
setSpinSymbol(), so the spinSymbol field is never initialized in
these objects. You probably want to call setSpinSymbol() in the
constructor, so that the spinSymbol field is guaranteed to be
initialized.
This explanation did solve my problem, and my program now outputs the correct information, so I believe it to be correct. My issues with using constructors and methods correctly has been explained here, and the reason why I was getting garbage values (as well as a few other points) was answered by another commenter.

Run time error for dynamic memory allocation in C++

I am a newbie for OOP concepts and while trying to solve Project Euler Problem 7, to find 10001th prime number, I tried to do it using a class but encountered 2 major errors.
instantiating the class prime_n
initializing its argument
I have posted the code here for reference:
#include<iostream>
#include<cstdio>
using namespace std;
class prime_n
{
int j,k;
int n;
int *store;
public:
prime_n(int num)
{
n=num;
store[n];
}
static int isPrime(int j)
{
for(int i=2;i*i<=j;i++)
{
if(j%i==0) return 0;
}
return 1;
}
void find_n()
{
for(int i=0;i<n;i++)
{
store[i]=0;
}
store[0]=2;
j=3;
k=1;
while(store[n-1]==0)
{
if(isPrime(j)) store[k++]=j;
j+=2;
}
}
int get_num()
{
int value=store[n-1];
return value;
}
};
int main()
{
int num, req_num;
printf("Enter the position at which prime number is to be found ");
scanf("%d",&num);
printf("\nnumber = %d",num);
prime_n p = new prime_n(num);
req_num = p.get_num();
printf("The required prime number is %d\n",req_num);
return 0;
}
It would be a great help if someone could help me figure out where I am actually going wrong. Thanks a lot in advance!
Use
prime_n p(num);
or (not recommended in this particular case)
prime_n * p = new prime_n(num);
// some other code
req_num = p->get_num(); // note the -> operator replacing . in case of pointers
delete p;
The first case declares p on stack and it is automatically deallocated when the program leaves the scope (main function in this case)
The second one allocates space on heap and p is the pointer to it. You have to deallocate the memory manually.
As for your second question, the C++ way would be
#include <iostream>
...
int num;
std::cout << "Enter the position at which prime number is to be found "
std::cin >> num;
std::cout << std::endl << "Number = " << num << std::endl;
You provide a constructor:
prime_n(int num)
{
n=num;
store[n];
}
I think you are under the impression that store[n] creates an array with n elements, but that is not so; it attempts to access the (n+1)th element of an an array. Since store does not point anywhere (we are in the constructor, after all), the program crashes.
You probably want to write store = new int[num] instead.
And then I cannot see any call to find_n() originating from get_num() which is called in main(), so that your program would for now just return a random value.

Debug Assertion Failed! Expression: _BLOCK_TYPE_IS_VALID [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I am getting this error message:
Debug Assertion Failed!
Expression:_BLOCK_TYPE_US_VALID(pHead->nBlockUse)
while trying to do the following
#include <vector>
#include <algorithm>
using namespace std;
class NN
{
public:
NN(const int numLayers,const int *lSz,const int AFT,const int OAF,const double initWtMag,const int UEW,const double *extInitWt);
double sse;
bool operator < (const NN &net) const {return sse < net.sse;}
};
class Pop
{
int popSize;
double a;
public:
Pop(const int numLayers,const int *lSz,const int AFT,const int OAF,const double initWtMag,const int numNets,const double alpha);
~Pop();
vector<NN> nets;
void GA(...);
};
Pop::Pop(const int numLayers,const int *lSz,const int AFT,const int OAF,
const double initWtMag,const int numNets,const double alpha)
{
popSize=numNets;
a=alpha;
nets.reserve(popSize);
for(int i=0;i<popSize;i++)
{
NN *net = new NN (numLayers,lSz,AFT,OAF,initWtMag,0,0);
nets.push_back(*net);
}
}
void Pop::GA()
{
...
sort(nets.begin(),nets.end());
...
}
The error appears to be related to the sort function. I check all instances of nets vector and they seem to be OK, having different sse's. The funny thing is that I created a simpler case of the above code (see below) and it worked without any errors. I am wrecking my brain. Please help.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Student
{
public:
string name;
double grade;
Student(string,double);
bool operator < (const Student &st) const {return grade < st.grade;}
};
Student::Student(string stName,double stGrade)
{
name = stName;
grade = stGrade;
}
int main()
{
vector<Student> group;
Student *st;
st = new Student("Bill",3.5);
group.push_back(*st);
st = new Student("John",3.9);
group.push_back(*st);
st = new Student("Dave",3.1);
group.push_back(*st);
sort(group.begin(),group.end());
for each(Student st in group)
cout << st.name << " " << st.grade << endl;
cin.get();
return(0);
}
The _BLOCK_TYPE_IS_VALID assertion gets fired, when you overwrite the header of an block allocated by new. This happens when you slice objects, use dead objects, etc.
You should have a look at your complete code, and try to work from the data you have in your debugger. This short code snippet contains several 'curious' usage of C++, but no obvious point at which this produces the described error (at least for me).
from my experience- This type of error could be caused by Heap corruption. so.. you must first check for memory leaks. If you are using Visual studio use _CrtCheckMemory().
Thanks everybody. First, I clear the memory allocated for nets vector inside the Pop destructor by
Pop::~Pop()
{
//nets.clear();
nets.~vector<NN>();
}
The error message does not say much and I would appreciate if somebody shows me how to make MSVC 2008 to show a more detailed info. Here is what it says (I can't cut and paste it for some reason, so I am retyping it):
Debug assertion failed!
Programm: ... GANN.exe
File: ... dbgedl.cpp
line: 52
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
For information how ...
When I press debug, the compiler shows me line 52 of file dbgdel.cpp:
_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));
inside
void operator delete(void *pUserData)
Here is a more of my code showing what happens before I try to sort
double Pop::GA(...)
{
for (int gen=0;gen<ngen;gen++)
{
int istart=0;
if(gen>0) istart=eliteSize;
for(int i=istart;i<popSize;i++)
nets[i].getSSE(in,tgt,ntr,discount);
for(int i=istart;i<popSize;i++)
{
cout << i << " " << nets[i].sse << endl;
}
sort(nets.begin(),nets.end());
Everything works properly up to the sort() point. The lSz pointer is used inside NN to hold the number of nodes in each layer of the neural network, for example lSz[3]={12,5,1} (12 inputs, one hidden layer with 5 neurons and one output). It is used to create a 3D array of the weights for each connection of the network. Each network NN (there are 100 of them) inside the Population has its own weight array. But they share the same lSz[] and other structural parameters, which unfortunately get copied from other NN instance to the other. I wanted to use static to declare these shared class members, but that would prevent parallelization.
I just discovered that if I do Pop construction like this
Pop::Pop(const int numLayers,const int *lSz,const int AFT,const int OAF,
const double initWtMag,const int numNets,const double alpha)
{
popSize=numNets;
a=alpha;
cout << "defined a\n";
nets.reserve(popSize);
NN *net = new NN (numLayers,lSz,AFT,OAF,initWtMag,0,0);
for(int i=0;i<popSize;i++)
{
//NN *net = new NN (numLayers,lSz,AFT,OAF,initWtMag,0,0);
nets.push_back(*net);
}
}
Then everything works, including sort(). But, that does not work for me because now the nets vector contains the same instance of NN popSize times. The idea was to intialize each of these instances individually. Each instance of NN is supposed to have its own array of weights, randomly initialized inside the NN constructor:
NN::NN(const int numLayers,const int *lSz,const int AFT,const int OAF,const double initWtMag,
const int UEW,const double *extInitWt)
{
// set number of layers and their sizes
nl=numLayers;
ls=new int[nl];
for(int i=0;i<nl;i++) ls[i]=lSz[i];
// set other parameters
aft=AFT;
oaf=OAF;
binMid=0.0;
if(aft==0) binMid=0.5;
// allocate memory for output of each neuron
out = new double*[nl];
for(int i=0;i<nl;i++) out[i]=new double[ls[i]];
// allocate memory for weights (genes)
// w[lr #][neuron # in this lr][input # = neuron # in prev lr]
w = new double**[nl];
for(int i=1;i<nl;i++) w[i]=new double*[ls[i]];
for(int i=1;i<nl;i++) // for each layer except input
for(int j=0;j<ls[i];j++) // for each neuron in current layer
w[i][j]=new double[ls[i-1]+1]; // w[][][ls[]] is bias
// seed and assign random weights (genes)
SYSTEMTIME tStart,tCurr;
GetSystemTime(&tStart);
for(;;)
{
GetSystemTime(&tCurr);
if(tCurr.wMilliseconds!=tStart.wMilliseconds) break;
}
srand(tCurr.wMilliseconds);
int iw=0;
for(int i=1;i<nl;i++) // for each layer except input
for(int j=0;j<ls[i];j++) // for each neuron in current layer
for(int k=0;k<=ls[i-1];k++) // for each input of curr neuron incl bias
if(UEW==0) w[i][j][k]=initWtMag*2.0*(rand()/(double)RAND_MAX-0.5);
else w[i][j][k]=extInitWt[iw++];
}
Sometimes its because you have a string of length x and you have accidentally put a longer word into it... thats what happened in my case.