Simple 2D Array header file, print fails - c++

I am writing a simple header file that can make a dynamic 2d array and put 0 in the row and col, print the array, and delete the array.
In Debug when stepping through, the 2d array gets initialized, it puts 0 in there, however when my_array.Print_Array(); called, the compiler skips it.
when i try to print the array from the main file it fails. any help would be appreciate it.
HEADER FILE:
class twoD_Array
{
public:
int **Array;
int *col, *row;
int size_col, size_row;
twoD_Array(int, int);
~twoD_Array();
void Print_Array();
};
twoD_Array::twoD_Array(int size_c, int size_r)
{
size_col = size_c;
size_row = size_r;
Array = new int *[size_col];
for (int i = 0; i < size_col; i++)
{
Array[i] = new int[size_row];
for (int j = 0; j < size_row; j++)
Array[i][j] = 0;
}
}
void twoD_Array::Print_Array()
{
for (int y_i = 0; y_i<size_col; y_i++)
{
for (int x_i = 0; x_i<size_col; x_i++)
std::cout << Array[y_i][x_i];
std::cout << std::endl;
}
}
twoD_Array::~twoD_Array()
{
for (int i = 0; i < size_row; i++)
delete[] Array[i];
delete[] Array;
}
Main File:
#include "stdafx.h"
#include <iostream>
#include "2D_Array.h"
int main()
{
int x, y;
std::cout << "how many x variables?" << std::endl;
std::cin >> x;
std::cout << "how many y variables?" << std::endl;
std::cin >> y;
twoD_Array my_array(x, y);
my_array.Print_Array();
return 0;
}

You are using the local variables in the constructor, but you're using the member variables in the Print_Array method, which are not initialized. You need to initialize the member variables size_col and size_row in the constructor where they are provided. Also, another thing to point out, in Print_Array method, you are using size_col instead of size_row for the x_i loop, which looks like a logical error.
I've rewritten the constructor and Print_Array to look this way:
twoD_Array::twoD_Array(int size_col, int size_row)
{
this->size_col = size_col;
this->size_row = size_row;
Array = new int *[size_col];
for (int i = 0; i < size_col; i++)
{
Array[i] = new int[size_row];
for (int j = 0; j < size_row; j++)
{
Array[i][j] = 0;
}
}
}
void twoD_Array::Print_Array()
{
for (int y_i = 0; y_i < size_col; y_i++)
{
for (int x_i = 0; x_i < size_row; x_i++)
{
std::cout << Array[y_i][x_i];
}
std::cout << std::endl;
}
}

In
twoD_Array::twoD_Array(int size_col, int size_row)
int size_col defines a new temporary and local to the constructor variable named size_col. This size_col has nothing to do with the member variable size_col and because they have the same name the local variable hides the member variable.
End result is in Print_Array the member variable size_col has not been set to anything, so Crom only knows what will happen.
Solution:
Set the member variable:
twoD_Array::twoD_Array(int col, int row): size_col(col), size_row(row)
The colon (:) tells the compiler that a Member Initializer List is coming. The Member Initializer List allows you to initialize class member before entering the body of the constructor. This is very important when you have a member variable that has no default constructor or requires expensive initialization you don't want to be forced to do twice. It' also allows you to initialize a base class.
Note that I also changed the names of the parameters to prevent future confusion.
And while we are here, let's head off what is likely to be OP's next problem by asking What is The Rule of Three? Seriously. Click the link. Save you a ton of debugging.

Related

Having a problem with getting the right value with private variable

This is a program that takes an array and print the sum of the odd (named m_sumOdd) and even (named m_sumEven) numbers of that array using class. However when i run it and enter some values like (4, 6, 9, 3, 1) the m_sumEven returns 10 and m_sumOdd returns 2037769787. What's the problem with m_sumOdd ?
#include <iostream>
#include <string>
class myClass {
private:
int m_sumEven;
int m_sumOdd;
public:
myClass() {
m_sumEven = 0;
m_sumOdd = 0;
}
myClass(int arr[]) {
for (int i = 0; i < 5; i++)
{
if (arr[i] % 2 == 0) {
m_sumEven += arr[i];
}
else if (arr[i] % 2 != 0) {
m_sumOdd += arr[i];
}
}
print();
}
void print() {
std::cout << m_sumEven << "\t" << m_sumOdd << std::endl;
}
};
int main(){
int main_arr[5];
for (int j = 0; j < 5; j++)
{
std::cin >> main_arr[j];
}
myClass obj(main_arr);
std::cin.get();
}
From your comment:
the problem is from my uni textbook and it specify that the private variables shall be initialized in the default constructor and the other constructor find the sum
I'm not sure what solution the textbook is looking for, but there is a mechanism that allows one constructor to use another.
class myClass {
private:
int m_sumEven;
int m_sumOdd;
public:
myClass() {
m_sumEven = 0;
m_sumOdd = 0;
}
myClass(int arr[]): myClass() { // <-------
....
This is called delegating constructors. This makes your myClass(int arr[]) constructor use the myClass() constructor before continuing on.
When you do not initialize your variable in C++, the default value of that variable is whatever garbage value happens to already be in that memory location. So if you initialize your privates variables as zeros (as in your non-parameterized constructor), your problem will be solved.
The second constructor doesn't initialize the private variables like the first one.
m_sumEven = 0;
m_sumOdd = 0;
Put these to the second constructor as well.
Even better, put them at the declaration:
int m_sumEven = 0;
int m_sumOdd = 0;
And now you don't need the first constructor.
Unrelated: consider using std::initializer_list instead. This provides you a safe way to know how many items are passed to the constructor, while now you have a fixed 5 in mind which may change later.

how to copy Int array to int pointer using constructor in C++

I am trying to insert int array x to int *v. here is my code . please provide me with optimal solutions and the reason behind it.
there is an error in this line. Instead of copying array value its taking garbage value. line v1=x;
class vector
{
int *v;
int size;
public:
vector(int m)
{
v = new int[size = m];
for (int i = 0; i < size; i++)
v[i] = 0;
}
vector(int *a)
{
for (int i = 0; i < size; i++)
v[i] = a[i];
}
int operator *(vector &y)
{
int sum = 0;
for (int i = 0; i < size; i++)
sum += v[i] * y.v[i];
return sum;
}
void disp()
{
for (int i = 0; i < size; i++)
cout << v[i] << " ";
cout << "\n";
}
};
int main()
{
clrscr();
int x[3] = { 1,2,3 };
int y[3] = { 4,5,6 };
vector v1(3);
//v1.disp();
vector v2(3);
v2.disp();
v1 = x;
v1.disp();
//v2=y;
v2.disp();
int r = v1 * v2;
cout << "R = " << r;
getch();
return 0;
}
You forgot to add the assignment operator in your vector class:
vector & operator=(int *a)
{
for (int i = 0; i < size; i++)
v[i] = a[i];
return *this;
}
In the the line
v1=x;
May be, you are expecting it to invoke the second constructor which takes int* as argument. But it won't happen.
It can be seen as Type Conversion from Basic type to Class type. where we expect appropriate constructor will get invoked.
see http://www.hexainclude.com/basic-to-class-type-conversion/
But remember, Constructor will be invoked only once after the creation of object.
Here, in the line
vector v1(3);
the first constructor was already invoked. Then the line
v1=x;
won't invoke the second constructor now.
For every class, = operator is default overloaded . That is the reason why we can easily assign objects to one another.
Therefore, the line v1=x invokes default overloaded assignment = operator.
Here, it treats address of array x i.e., &x[0] as address of class object. As it is not address of vector class object
=> it results a Segmentation fault.
YOUR ANSWER
To assign int array to int pointer i.e., to the member variable int* v of the vector class,
overload assignment operator = inside the class .
or
Initialize the class object to array in first line itself. i.e.,
vector v1=x; // modify the class constructor to have size as a constant.

Void pointer to a class object: Initialization inside a function

I am trying to create a void pointer to a class object and have it be initialized inside a function. Unfortunately, the array member of the class cannot escape the function i.e. it cannot be accessed after initialization.
In the code below, the first call to print positions (inside the initialize function) works properly, however, the second call to print positions from outside the initialization function fails. I have a feeling that the array object created in the initialization function is destroyed and not passed along but I am not sure and also don't know how to fix it.
Any help would be greatly appreciated.
#include <iostream>
#include <iomanip>
#include <string>
class Atoms
{
double * positions;
int nAtoms;
public:
// Standard constructor prividing a pre-existant array
Atoms(int nAtoms, double * positionsArray)
{
this->nAtoms = nAtoms;
this->positions = positionsArray;
}
// Print positions to screen
void print_positions()
{
std::cout<< "nAtoms: " << this->nAtoms << std::endl;
int nDim = 3;
for (int i = 0; i < nAtoms; i++)
{
for (int j = 0; j < nDim; j++)
{
std::cout << std::setw(6) << this->positions[i * nDim + j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
};
void initialize_Atoms_void_pointer(void ** voidAtomsPointer)
{
//Create a new instance of Atoms by a pointer
int numAtoms = 5;
int numDim = 3;
int elemN = numAtoms * numDim;
double data_array[elemN];
for (int i = 0; i < numAtoms; i++)
for (int j = 0; j < numDim; j++)
{
data_array[i * numDim + j] = i * numDim + j + 10;
}
Atoms *atoms = new Atoms(numAtoms, data_array);
// Set the vPointer that the void pointer points to a pointer to Atoms object
*voidAtomsPointer = static_cast<void *>(atoms);
//Test call
std::cout << std::endl << "Initializing atoms" << std::endl;
static_cast<Atoms *>(*voidAtomsPointer)->print_positions();
}
void print_Atoms_pointer_positions(void * voidAtomsPointer)
{
//Cast the pointer as an atoms pointer
Atoms *atomsPointer = static_cast<Atoms *>(voidAtomsPointer);
atomsPointer->print_positions();
}
int main()
{
//Use the initializer function for getting a pointer
void *testVoidAtomsPointer;
initialize_Atoms_void_pointer(&testVoidAtomsPointer);
print_Atoms_pointer_positions(testVoidAtomsPointer);
}
The problem is that in
Atoms *atoms = new Atoms(numAtoms, data_array);
data_array is a local array, which is destroyed when initialize_Atoms_void_pointer quits.
Instead of copying the raw pointer, make a new allocation in Atoms's constructor and copy the content:
Atoms(int nAtoms, double * positionsArray)
{
this->nAtoms = nAtoms;
this->positions = new double[nAtoms];
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}
~Atoms()
{
delete[] this->positions;
}
A safer implementation would include the use of a std::unique_ptr, which will automatically de-allocate the memory for you when Atoms is destroyed:
#include <memory>
class Atoms {
std::unique_ptr<double[]> positions;
// ...
public:
Atoms(int nAtoms, double * positionsArray) :
positions(new double[nAtoms]) {
this->nAtoms = nAtoms;
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}
// ...
};
You'd need also to check if nAtoms is 0 or negative, if the input array is null, etc., but I think it falls out of the scope of the question.
If you need to access the raw pointer, you can use the positions.get() method (do not try to delete it or your application will crash due to a double delete).
Update
Of course, another more straightforward solution is simply to use a std::vector<double> instead ;)
#include <vector>
class Atoms {
std::vector<double> positions;
// int nAtoms; -- no longer necessary
public:
Atoms(int nAtoms, double * positionsArray) :
positions(nAtoms) {
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}
// ...
};
If you need to access the raw pointer, you can use the positions.data() method (do not try to delete it or your application will crash due to a double delete). The number of atoms can be checked using positions.size().
As mentioned in a comment, if the only purpose of the Atoms class is to store doubles but not to add any other operation, then just forget about it and directly use the std::vector<double>.

C++: Error while allocating memory for a two dimensional array using functions

I am trying to understand passing by reference and passing by value. In this program I have a two dimensional array which is declared in main and whose size is allocated in a function. In the allocate2DArrayRef() function, I obtain the two sizes and dynamically allocate and initialize the array Array2D.
Now I am trying to understand how to do the same by pointers. I have written another function allocate2DArrayPtr() in where I pass a pointer to the two dimensional array, get the value of the sizes - sizeX and sizeY and then allocate the memory to the variable secArray2D.
When I run the program it hangs when I try to print out secArray2D. I am assuming this implies that the function allocate2DArrayPtr() has not been successful in dynamically allocating memory to the array secArray2D.
My final goal is to write a program which has a function that dynamically allocated memory and initializes multiple arrays of various dimensions which are read from an input file. I know I can expand on passing by reference function allocate2DArrayRef() to achieve my goal. But I am curious to learn why my function allocate2DArrayPtr() is not working as I want to be clear on how to pass by pointers also. I do know how to change allocate2DArrayPtr() to return a pointer but I would like to pass the array as a parameter.
I am running the program on windows 7 using Codeblocks 13.12 IDE.
#include <iostream>
using namespace std;
void allocate2DArrayRef(int **&, int &, int &);
void allocate2DArrayPtr(int ***, int *, int *);
int main()
{
int sizeX, sizeY;
int **Array2D;
allocate2DArrayRef(Array2D, sizeX, sizeY);
for(int i=0; i< sizeX; i++)
{
for(int j=0; j< sizeY; j++)
{
cout << "Array2D[" << i << "][" << j << "]:" << Array2D[i][j] << endl;
}
}
cout << endl << endl;
int **secArray2D;
allocate2DArrayPtr(&secArray2D, &sizeX, &sizeY);
for(int i=0; i<sizeX; i++)
{
for(int j=0; j<sizeY; j++)
{
cout << "secArray2D[" << i << "][" << j << "]:" << secArray2D[i][j] << endl;
}
}
return 0;
}
void allocate2DArrayRef(int **&locArray, int& indexFirst, int& indexSecond)
{
indexFirst = 4;
indexSecond = 5;
locArray = new int*[indexFirst];
for(int i=0; i<indexFirst ; i++)
{
locArray[i] = new int[indexSecond];
for(int j=0; j<indexSecond; j++)
{
locArray[i][j] = i*j;
}
}
}
void allocate2DArrayPtr(int ***locArray, int *indexFirst, int *indexSecond)
{
*indexFirst = 2;
*indexSecond = 3;
int **temp = *locArray;
temp = new int*[*indexFirst];
for(int i=0; i<(*indexFirst) ; i++)
{
temp[i] = new int[*indexSecond];
for(int j=0; j<(*indexSecond); j++)
{
temp[i][j] = i+j;
}
}
}
The reason allocate2DArrayPtr does not work is you never set locArray to point to the array you create in the function. This means when you return from the function secArray2D still is uninitialized.
Adding
*locArray = temp;
To the end of allocate2DArrayPtr will fix the problem.
Or you can reference your to temp like this:
int **&temp = *locArray;

Referencing Elements of Class Arrays using C++

I am trying to switch the elements of a class array using pointers. It is not outputting what I want. I tried using pointers in the function, but it's not allowed. It's also not allowed to call the function onto the class object without using a pointer, since I declared the class object using a double pointer. I am not using this method simply to solve a small problem, but just to practice using this method for more difficult problems.
Here is my code:
#include <iostream>
#include <algorithm>
using namespace std;
class thing{
public:
int index;
int value;
thing();
private: int number;
};
thing::thing()
{
number = 0;
}
void arrange(thing array[]){
for(int i=0; i<19; ++i){
if(array[i].value<array[i+1].value){
swap(array[i], array[i+1]);
arrange(array);
}
}
}
int main(){
thing** things = new thing*[20];
for (int i=0; i < 20; ++i)
{
things[i] = new thing(); // default constructor
things[i]->index = i;
things[i]->value=rand() % 100;
}
cout << "The random array is: " << endl;
for(int i=0;i<20;++i){
cout << things[i]->value << endl;
}
arrange(*things);
cout << "The arranged array is: " << endl;
for (int i=0; i < 20; ++i)
{
cout << things[i]->value << endl;
}
return 0;
}
When you call arrange(*things), you're just passing the first element of things to the function, not the array. It should be array(things). Then the arrange function should be written to use pointers:
void arrange(thing* array[]){
for(int i=0; i<19; ++i){
if(array[i]->value<array[i+1]->value){
swap(array[i], array[i+1]);
arrange(array);
}
}
}
Here you create an array of pointers to thing:
thing** things = new thing*[20];
Here you dereference it and get a pointer to thing which is stored at thing[0]:
arrange(*things);
But this function declaration
void arrange(thing array[])
treats this pointer as an array of thing, so that *things points to it first element, which is absolutely not what it really is.
You should change your arrange() function to use correct type:
void arrange(thing* array[]){
for(int i=0; i<19; ++i){
if(array[i]->value<array[i+1]->value){
swap(array[i], array[i+1]);
arrange(array);
}
}
}
And call it as:
arrange(things);
Regarding using vectors, you don't need to use any pointers at all.
std::vector<thing> things(20);
for (int i=0; i < things.size(); ++i)
{
things[i].index = i;
things[i].value=rand() % 100;
}
arrange(things);
void arrange(std::vector<thing>& array){
for(int i=0; i + 1 < things.size(); ++i){
if(array[i].value<array[i+1].value){
swap(array[i], array[i+1]);
arrange(array);
}
}
}