How do I properly implement a display function of a class? - c++

I have a class called magicSquare with a constructor and a display function called display. The constructor creates the magic square, and the display function displays the results. In my main function, I created an instance of magicSquare called ms and gave it a value 7. To display it, shouldn't it work if I just did ms.display()?
class magicSquare
{
private:
int size, square;
vector<vector <int> > finalvec;
public:
magicSquare(int a):finalvec(a, std::vector<int>(a))
{
int i = 0;
int j = a/2;
size = a;
square = a * a;
vector<int>vec(a);
vector<vector<int> > finalvec(a,vec);
for (int i = 0; i < size; i++)
{
for (int j = 0; j< size; j++)
cout << finalvec[i][j];
cout << endl;
}
for (int k=0; k < square; ++k)
{
finalvec[i][j] = k;
i--;
j++;
if (k%a == 0)
{
i = i+ 2;
--j;
}
else
{
if (j==a)
j = j- a;
else if (i<0)
i = i+ a;
}
}
}
void display()
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j< size; j++)
cout << finalvec[i][j];
cout << endl;
}
}
};
int main()
{
magicSquare ms(3);
ms.display();
return 0;
}

Your Error
As pointed by #Retired Ninja, the vector > finalvec(a,vec); hide your member variable finalvec, as you redefine it as a new vector...
What can correct it
You could construct your vector inside a Member initializer list like this
magicSquare(int a) : finalvec(a, std::vector<int>(a, 0)) {
/* your constructor */
}
And delete the two line:
vector<int>vec(a);
vector<vector<int> > finalvec(a,vec);
In your code
How to not make this error
Seeing which value are a class member, method parameter or even context variable can be sometime difficult:
What i can recommend you is to do the following:
class member -> m_NAME_OF_YOUR_CLASS_MEMBER
method parameter -> t_NAME_OF_YOUR_METHODE_PARAMETER
context variable -> c_NAME_OF_YOUR_CONTEXT_VARIABLE
by doing this error like you've done is a bit harder to do!
EDIT: After testing your code
I see there's error in it, effectively, the first time you go in that line:
finalvec[i][j] = k;
i > size, so you access further that your vector allow it, which result in a segfault! please repair your code!
hope that can help

Related

Replacing the value of map elements isnt working

I'm just Learning about std::map and its functions . I recently got this problem. I tried making a program which prints out a grid type data where I used std::map for the keys and values . The program prints out fine but I wanted to make a program where once I erased a data in that grid, other data above that should move down one step and the topmost would have 0 in it . somehow I tried but it doesn't seem to work . I don't know where I did wrong in that . My code:
in class header:
#pragma once
#include<iostream>
#include<string>
#include<vector>
#include<map>
#define x_Pair std::pair<unsigned int,unsigned int>
class MapCheck
{
public:
std::map<x_Pair, unsigned int>m_MapData;
void SetMapData();
x_Pair GetBlockCell(int num);
void EraseCell(int cell);
};
in class cpp:
void MapCheck::SetMapData()
{
int count = 1;
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
m_MapData[{i, j}] = count;
count++;
}
}
}
x_Pair MapCheck::GetBlockCell(int num)
{
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
if (m_MapData[{i, j}] == num)
{
return x_Pair(i, j);
}
}
}
return x_Pair(-1, -1);
}
void MapCheck::EraseCell(int cell)
{
x_Pair pair = GetBlockCell(cell);
for (int i = pair.second; i < 20; i++)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
m_MapData[{pair.first, i - 1}] = 0;
}
}
-and in main:
#include"MapCheck.h"
int main()
{
MapCheck mc;
mc.SetMapData();
std::string input;
do
{
system("cls");
for (int j = 0; j < 20; j++)
{
for (int i = 0; i < 10; i++)
{
std::cout << mc.m_MapData[{i, j}] << " ";
}
std::cout << std::endl;
}
std::cout << "Enter a number to erase or E to exit";
std::cin >> input;
mc.EraseCell(std::atoi(input.c_str()));
} while (input != "E");
return 0;
}
the output without any inputs :
after entering number 191 in the input :
expected result:
All Except the printing is fine . I dont Get Where I did Wrong. Any help would be appreciated. Thanks in advance!!
The order of
for (int i = pair.second; i < 20; i++)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
m_MapData[{pair.first, i - 1}] = 0;
}
is element found to the bottom. When you want to move everything above the item removed down one slot, this isn't all that useful. So lets flip it around.
for (int i = pair.second; i > 0; i--)
{
m_MapData[{pair.first, i}] = m_MapData[{pair.first, i - 1}];
}
m_MapData[{pair.first, 0}] = 0;
This starts at the item being removed and goes up to slot 1, copying each item down one slot. To handle the top of the column, we have m_MapData[{pair.first, 0}] = 0; to set the top item to zero, something we only need to do once.
Side note: Unless we have a sparse array, this would be a lot more efficient with a 2D array in place of the map.
You have following:
x_Pair MapCheck::GetBlockCell(int num)
which is used as
x_Pair pair = GetBlockCell(cell);
This will invoke copy constructor of std::pair<>.
I think you need to return and use reference:
x_Pair& MapCheck::GetBlockCell(int num)
which is used as
x_Pair& pair = GetBlockCell(cell);

Segmentation fault - reading array of initialized pointers

could you help me with little problem?
I have following class;
class Link
{
private:
Demand *demand_[NUMBER_OF_CORES][NUMBER_OF_SLICES];
public:
Link()
{
for (int i = 0; i < NUMBER_OF_CORES; i++)
{
for (int j = 0; j < NUMBER_OF_SLICES; j++)
{
demand_[i][j] = NULL;
}
}
}
int virtualPut();
}
There will be problem with demand_ array. In the constructor everything is fine, after initialization I can use if (demand_[i][j] == NULL).
Problem starts in virtualPut()
int Link::virtualPut()
{
for (int i = 0; i < NUMBER_OF_CORES; i++)
{
for (int j = 0; j < NUMBER_OF_SLICES; j++)
{
std::cout << "We're in " << i << " " << j << " \n" << std::flush;
if (demand_[i][j] == NULL) //SEGMENTATION FAULT
{
std::cout << "EMPTY\n";
}
}
}
}
And also - if I call virtualPut() in constructor (just for test) it works fine.
But outside Link class I use.
void someFunction(Link *tab, int links)
{
tab = new Link[links];
tab[0].virtualPut(); //also just for test
}
What could be a problem here? I know that I can use vector, but that won't help me understand this memory problem.
One more thing - Dr. Memory says:
UNADDRESSABLE ACCESS: reading 0x0000000000000009-0x0000000000000011 8 byte(s)
But why?
EDIT!
Problem solved in comments, thank you
The code you show us is okay. I ran it on my side with huge values, and there is no Segfault.
You declared a "Demand* array of array" in your Link class, and this is a valid declaration, the memory should be allocated.
What I do suspect is that NUMBER_OF_CORES and/or NUMBER_OF_SLICES doesn't have the same value in the code where you defines the Link class and in the code where you defined the virtualPut method.
Something like :
#define NUMBER_OF_CORES 10
#define NUMBER_OF_SLICES 10
class Link
{
private:
Demand *demand_[NUMBER_OF_CORES][NUMBER_OF_SLICES];
...
}
and
#define NUMBER_OF_CORES 5000
#define NUMBER_OF_SLICES 5000
int Link::virtualPut()
{
for (int i = 0; i < NUMBER_OF_CORES; i++)
{
for (int j = 0; j < NUMBER_OF_SLICES; j++)
{
// here you will have buffer overflow
...
}
What I would do :
use std::vector
probably use a single entry array, and wrap it up
don't use #define, it's messy
don't use arrays, it generates buffer overflow
That would be something like this :
class Link
{
private:
std::vector<Demand*> demand_;
const int NUMBER_OF_CORES = 10;
const int NUMBER_OF_SLICES = 50;
private:
int getIdx(int i, int j)
{
return i*NUMBER_OF_SLICES + j;
}
public:
Link()
{
demand_.resize(NUMBER_OF_CORES * NUMBER_OF_SLICES);
for (int i = 0; i < NUMBER_OF_CORES; i++)
{
for (int j = 0; j < NUMBER_OF_SLICES; j++)
{
demand_[getIdx(i,j)] = NULL;
}
}
}
int virtualPut();
};
Note : additionaly, you showed us a virtualPut() that should return an int but doesn't.

C++ Program crashes on passing object by value

Error occurs when I pass another object to a function -> a.Concat(b);
I have just reverted to C++ from Java for a project. When I pass object by value in this code, then an error occurs. Almost every time it is displaying a different error message, sometimes bad alloc, sometimes displaying half the output. I tried passing by reference and also made a copy constructor but both attempts failed.
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class NFA
{
public:
NFA(string);
NFA(vector<vector<string> >);
NFA Concat(NFA other_nfa);
NFA Union(NFA);
NFA KleeneStar();
void display();
int GetNFASize(){ return ALPHABET_SIZE; }
int getNoOfStates(){ return NO_OF_STATES; }
vector<vector<string> > table;
int ALPHABET_SIZE;
int NO_OF_STATES;
private:
};
NFA::NFA(string input)
{
table.resize(2);
NO_OF_STATES = 2;
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
ALPHABET_SIZE = 3;
}
void NFA::display()
{
for(int i = 0; i < table.size(); i++)
{
for(int j = 0; j < ALPHABET_SIZE; j++)
{
cout << table[i][j] << "\t";
}
cout << endl;
}
}
NFA NFA::Concat(NFA other_nfa)
{
vector<vector<string> > ans_vector;
ans_vector.resize(ALPHABET_SIZE + other_nfa.ALPHABET_SIZE);
for(int i = 0; i < NO_OF_STATES; i++)
{
for(int j = 0; j < ALPHABET_SIZE; j++)
{
ans_vector[i][j] = table[i][j];
}
}
for(int i = other_nfa.NO_OF_STATES - 1; i < other_nfa.NO_OF_STATES; i++)
{
for(int j = 0; j < other_nfa.ALPHABET_SIZE; j++)
{
ans_vector[i][j] = other_nfa.table[i][j];
}
}
ans_vector[NO_OF_STATES - 1][3] = other_nfa.table[0][0];
NFA ansNFA(ans_vector);
}
NFA::NFA(vector<vector<string> >)
{
}
int main()
{
NFA a("a");
a.display();
NFA b("b");
b.display();
NFA ab = a.Concat(b);
system("pause");
return 0;
}
In
NFA::NFA(string input)
{
table.resize(2);
NO_OF_STATES = 2;
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
ALPHABET_SIZE = 3;
}
You variable initializations are out of order. When you use
table[i].resize(ALPHABET_SIZE + 1);
ALPHABET_SIZE contains garbage as you have not set a value yet. Just move ALPHABET_SIZE = 3; before the for loop and you should be okay.
I would also suggest you use a member initialization list for all variables to you can. In this case your constructor would look like
NFA::NFA(string input) : NO_OF_STATES(2), ALPHABET_SIZE(3)
{
table.resize(2);
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
}
You resize a vector<vector<string> but fail to resize any of the contained vectors:
ans_vector.resize(ALPHABET_SIZE + other_nfa.ALPHABET_SIZE);
And then later you index into the nested vectors, which goes out of bounds:
for(int i = 0; i < NO_OF_STATES; i++)
{
for(int j = 0; j < ALPHABET_SIZE; j++)
{
ans_vector[i][j] = table[i][j];
}
}
You'll need to call resize for every vector inside ans_vector, or use push_back, emplace_back etc, which would probably be safer for you.
AlPHABET_SIZE is not defined in:
table[i].resize(ALPHABET_SIZE + 1);
by default, it contains some garbage value. This might be your problem.
NFA::NFA(string input)
{
table.resize(2);
NO_OF_STATES = 2;
for(int i = 0; i < NO_OF_STATES; i++)
{
table[i].resize(ALPHABET_SIZE + 1);
}
table[0][0] = "2";
table[0][1] = input;
table[1][0] = "3";
ALPHABET_SIZE = 3;
}
ALPHABET_SIZE is being used in the ctor of NFA though it was not initialized. it causes weird behaviour.
You are creating three objects a,b,ab. during construction of the object program crashes. it has nothing to do with pass by reference/value or using copy ctor.
From the first look I would say the problem lays in the vector-access of table, which would go out-of-range.
From design-point, several issues:
It seems you _other_nfa can be declared const reference:
NFA NFA::Concat(const NFA& other_nfa)
There is no return. At the end of your Concat method there should be sth. like:
return ansNFA;
It seems within Concat you don't change your member variables like table (which btw. is no good name for a member-variable). If Concat dosn't change the class members, you should declare it const:
NFA NFA::Concat(const NFA& other_nfa) const

How to generate dynamic empty 2D array without default constructor in C++

I have a class named Test and I'd like to create empty 2D array that will hold instances of that class and than add them later one by one using constructor that accepts parameters.
Basically, I'd just like to reserve memory that I will fill in later with objects. It needs to bee on a heap since I will have class that will generate 2D arrays of different sizes.
This was my first approach but it doesn't really work since Test class doesn't have default constructor:
Test** arr;
arr = new Test*[10];
for (int i = 0; i < 10; i++)
arr[i] = new Test[10];
[EDIT]
Here is my full test code. All in all, I'm getting wrong values out, it should be numbers from 0 to 99:
#include <iostream>
using namespace std;
class Test {
private:
short number;
public:
Test(short n) {
this->number = n;
}
short getNumber() {
return number;
}
};
int main() {
Test** arr;
arr = new Test*[10*10];
for (int i = 0; i < 100; i++)
arr[i] = new Test(i);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++)
cout << arr[i][j].getNumber() << " ";
cout << endl;
}
}
Maybe try using a default constructor with default parameters?
Test(int i = 0) {. . .}

creating multiple matrix with different constructors

I have an assignment where i need to use a matrix class of type T elements. I have a constructor using 2 int, one copy constructor, one constructor using a string and a destructor. matrix A uses first constructor and works fine, matrix B uses second and also prints out fine but i have an issue with matrix C. If I a declare it by itself(removing matrix a and b from main) it prints as well, but when all is there, it prints out something like:
3735748 3745176
3745176 3735748
(instead of
5 6
7 8)
And numbers change everytime I compile.
I feel like this should be obvious but i'm a beginner and cant figure it out.. Any help welcome! Thank you
template <class T>
class matrice
{
private :
unsigned int nLignes; //number of rows
unsigned int nColonnes; //nbr of cols
T** rep;
public :
matrice( unsigned int nl, unsigned int nc)
{
setLignes(nl);
setColonnes(nc);
rep = new T*[nl];
for(int i = 0; i < nl; i++){
rep[i] = new T[nc];
}
for(int i = 0; i < nl; i++){
for(int j = 0; j < nc; j++){
rep[i][j] = (T) i*j;
}
}
}
matrice( const matrice& mat)// my copy constructor
{
setLignes(mat.nLignes);
setColonnes(mat.nColonnes);
rep = new T*[nLignes];
for(int i = 0; i < nLignes; i++){
rep[i] = new T[nColonnes];
}
for(int i = 0; i < nLignes; i++){
for(int j = 0; j < nColonnes; j++){
rep[i][j] = (T) i*j;
}
}
}
matrice( const std::string& UnString)//constructor using a string
//"nl,nc,val1, val2.."
{
std::vector<int> vect;
std::stringstream ss(UnString);
int i;
while (ss >> i)
{
vect.push_back(i);
if (ss.peek() == ',')
ss.ignore();
}
setLignes(vect.at(0));
setColonnes(vect.at(1));
int taille = nLignes * nColonnes;
vect.erase(vect.begin(), vect.begin()+2);
if(taille == vect.size()){ // making sure enough values to
//fill array
int n = 0;
for(int i = 0; i < nLignes; i++){
rep[i] = new T[nColonnes];
}
for(int i = 0; i < nLignes; i++){
for(int j = 0; j < nColonnes; j++){
rep[i][j] = vect.at(n);
n++;
}
}
}
}
~matrice()
{
delete[] rep;
}
void afficher();//printing function
void setLignes(int l)
{
nLignes = l;
}
void setColonnes(int c)
{
nColonnes = c;
}
};
template <class T>
void matrice<T>::afficher()//printing function
{
int i,j;
for (i=0;i < nLignes;i++)
{
for(j=0;j < nColonnes;j++)
{
cout << rep[i][j] << " ";
}
cout << "\n";
}
}
/*
*
*MAIN*
******/
int main(int argc, char *argv[])
{
matrice <unsigned int> mat(5,3);//MATRIX A
matrice <unsigned int> a = mat;
a.afficher();
{
matrice <unsigned int> mat(6,6);//MATRIX B
matrice <unsigned int> b = mat;
b.afficher();
}
matrice <unsigned int> c("2,2,5,6,7,8");//MATRIX C !! problem
c.afficher();
system("pause");
return 0;
}
You forget allocate space for rep in the constructor using a string.
Moreover, your deconstructor is at risk of memory leaking, please check it yourself.