Problems with two-dimensional vector in c++ - c++

I'm trying to write a class in c++, that presents a group of people (each person has its own row), and the numbers in the rows represent this person's friends. If person a is person's b friend, then the person b is person's b friend as well.
I came up with something like this:
class Friends {
public:
Friends(int n);
// Creates a set of n people, no one knows each other.
bool knows(int a, int b);
// returns true if the 2 people know each other
void getToKnow(int a, int b);
// Person a & b meet.
void mutualFriends(int a, int b);
// cout's the mutual friends of person a & b
void meeting(int a);
//all friends of person a also become friends
int max();
//return the person with the highest number of friends
private:
vector<vector<int>> friends;
};
Friends::Friends(int n) {
vector<vector<int>> friends;
}
bool Friends::knows(int a, int b) {
for(int i=0; i<friends[a].size(); i++) {
if (friends[a][i]==b) {
return true;
}
}
return false;
}
void Friends::getToKnow(int a, int b) {
friends[a].push_back(b);
friends[b].push_back(a);
}
void Friends::mutualFriends(int a, int b) {
for (int i=0; i<friends[a].size(); i++) {
for (int j=0; j<friends[b].size(); j++) {
if (friends[a][i]==friends[b][j])
cout << friends[a][i] <<", ";
}
}
}
void Friends::meeting(int a) {
for (int i=0; i<friends[a].size(); i++) {
for(int j=0; j<friends[a].size();j++) {
if(i!=j && i!=a && j!=a) {
getToKnow(i,j);
}
}
}
}
int Friends::max() {
int maks = 0;
for (int i=0; i<friends[i].size(); i++) {
if (friends[i].size()<friends[i+1].size())
maks = i;
}
return maks;
}
int main() {
Friends f1 (4);
f1.getToKnow(1,3);
}
So far, every time I try to add something to the vector (f.e. with the function getToKnow) the compiler can't compile the program, pointing that
friends[a].push_back(b);
friends[b].push_back(a);
is wrong. The exact information displayed is "Thread 1: EXC_BAD_ACCESS (code=1, address=0x20)". I don't know what I'm doing wrong and if I'm using the 2d vector correctly.

In the line
Friends::Friends(int n) {
vector<vector<int>> friends;
}
you are creating a local vector of vectors which will be deallocated upon leaving the function.
What you are looking for is:
Friends::Friends(int n) {
friends.resize(n);
}
Which will allocate n vectors, allowing you to access any element below that threshold.

I'm just guessing here, but you should probably create a constructor initialize list to set the size of the member variable:
Friends::Friends(int n)
: friends(n)
{
// Empty
}

Related

How to fix the error in C++ vector operation?

The f() function in the class MapSquare works properly.. When I add the other class MapTriple, it is not working. f() function in the MapSquare should find the square of the elements in the vector and in the MapTriple should multiply 3 to all elements.
MapGeneric is the base class which contains the function map() which is a recursive function to access the vector elements and the f() function is a pure virtual function.
MapSquare and MapTriple are two derived classes overrides the f() function to find the square of vector elements and to multiply 3 with all the vector elements.
MapSquare works properly... but when I add MapTriple, segmentation fault occures. Please help to solve this.
#include<vector>
#include<iostream>
#include<cstdlib>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class MapGeneric
{
public:
virtual int f(int){};
vector<int> map(vector<int>, int);
};
class MapSquare:public MapGeneric
{
public: int f(int);
};
class MapTriple:public MapGeneric
{
public: int f(int);
};
class MapAbsolute:public MapGeneric
{
public: int f(int);
};
vector<int> MapGeneric::map(vector<int> v, int index)
{
if(index>=1)
{
v[index]=f(v[index]);
return map(v,index-1);
}
return v;
}
int MapSquare::f(int x)
{
return x*x;
}
int MapTriple::f(int x)
{
return 3*x;
}
int MapAbsolute::f(int x)
{
return abs(x);
}
int main()
{
//mapping square
MapSquare ob;
vector<int> L,L1,L2;
for (int i = 1; i <= 5; i++)
L.push_back(i);
L1=ob.map(L,sizeof(L));
cout<<"Square = ";
for ( vector<int>::iterator i = L1.begin(); i != L1.end(); ++i)
cout << *i<<" ";
//mapping triple
MapTriple t;
L2=t.map(L,sizeof(L));
cout<<endl<<"Triple = ";
for(vector<int>::iterator i=L2.begin();i!=L2.end();++i)
cout<<*i<<" ";
return 0;
}
A number of problems here. It looks as though you think that C++ indices start at 1, rather than zero?
if(index>=1)
{
v[index]=f(v[index]);
return map(v,index-1);
}
To me that immediately looks wrong, surely you mean:
// use size_t for indices (which cannot be negative)
vector<int> MapGeneric::map(vector<int> v, size_t index)
{
// make sure the index is valid!
if(index < v.size())
{
v[index] = f(v[index]);
return map(v, index - 1);
}
return v;
}
Secondly, the sizeof() operator does not do what you expect!! It returns the size of std::vector (which is usually 24bytes on 64 bit systems - basically 3 pointers). You should use the size() method to determine the length of the array.
// remember that indices are zero based, and not 1 based!
L1=ob.map(L, L.size() - 1);

Edit object in vector

How can i edit a object in a vector?
Right now my vector is vector<PCB> M3M;
Inside it are a few objects from my class below.
class PCB
{
public:
void setPID (int a)
{
PID = a;
}
int retrievePID()
{
return PID;
}
int retrieveLimit()
{
return Limit;
}
void setLimit (int a)
{
Limit = a;
}
int retrieveBase()
{
return Base;
}
void setBase (int a)
{
Base = a;
}
int retrieveHoleTrueOrFalse()
{
return HoleTrueOrFalse;
}
void setHoleTrueOrFalse (int a)
{
HoleTrueOrFalse = a;
}
private:
int PID;
int Limit;
int Base;
int HoleTrueOrFalse;
};
How would i be able to edit the PID part in any place i choose in my object?
For example i want to set a new PID in my vector at M3M[4]. How do i go about doing that?
M3M[4].setPID(<new PID>);
You also can have an iterator that can point to an element in your array and set a new PID to that. Example:
std::vector<PCB>::iterator it = M3M.begin();
//this will advance your iterator by 3
it += 3;
it->setPID(5); // this will set the 3rd element's PID to 5
Keep in mind that your vector needs to have at least 4 elements in order for the code above to execute. In order to you fill your vector, you can use push_back() method of your vector.
M3M.push_back(PCB(0));
M3M.push_back(PCB(1));
M3M.push_back(PCB(2));
M3M.push_back(PCB(3));
M3M.push_back(PCB(4));

Unable to decipher "error: expected unqualified-id before 'int'"

I've been looking around and haven't come up with any tangible solutions. It sounds like it is looking for a default constructor instead of the one in place but I have one below. Moving it up as the first listed constructor didn't change the error messages so I'm wrong about that. Here's the full error message (using jGRASP):
In file included from intset.h:47:0,
from IntSet.cpp:1:
IntSet.cpp:12:11: error: expected unqualified-id before 'int'
IntSet(int a, int b, int c, int d, int e) {
^
IntSet.cpp:12:11: error: expected ')' before 'int'
Here's the IntSet.cpp code:
#include "intset.h"
//#include <algorithm>
//#include <iostream>
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
//Constructors
IntSet(int a, int b, int c, int d, int e) {
size = a;
if(b > size) {
size = b;
}
if(c > size) {
size = c;
}
if(d > size) {
size = d;
}
if(e > size) {
size = e;
}
set = new bool[size];
for(int i = 0; i <= size; i++) {
if(i == a || i == b || i == c || i == d || i == e) {
insert(i);
} else {
remove(i);
}
}
}
IntSet(int a, int b, int c, int d) {
IntSet(a, b, c, d, -1);
}
IntSet(int a, int b, int c) {
IntSet(a, b, c, -1, -1);
}
IntSet(int a, int b) {
IntSet(a, b, -1, -1, -1);
}
IntSet(int a) {
IntSet(a, -1, -1, -1, -1);
}
//Copy constructor
IntSet(const IntSet& x) {
size = x.size;
for (int i = 0; i <= x.size; i++ ) {
set[i] = x.set[i];
}
}
//Destructor
~IntSet()
{
//for(int i = this.length(); i >= 0; i--) {
// this[i]
//}
}
////////////////////////
bool insert(int a) {
if(a <= size && a >= 0) {
set[a] = true;
return true;
}
else if(a >= 0) {
//removed "new" from line below
IntSet temp = IntSet(a);
&this += temp;
set[a] = true;
return true;
}
return false;
}
bool remove (int a) {
if (isInSet(a)) {
set[a] = false;
return true;
}
return false;
}
bool isEmpty() {
bool retVal = true;
for (int i = 0; i <= size; i++) {
if (set[i] == true) {
retVal = false;
}
}
return retVal;
}
bool isInSet (int a) {
if (set[a]){
return true;
}
return false;
}
/////////////////////////////////////////////
IntSet operator + (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] || a.set[i]){
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator * (IntSet a) {
IntSet c = IntSet(max(size, a.size));
for (int i = 0; i <= c.size; i++) {
if (set[i] && a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
}
return c;
}
IntSet operator - (IntSet a) {
IntSet c = IntSet();
c.size = 0;
for (int i = 0; i <= size; i++) {
if (set[i] && !a.set[i]) {
c.set[i] = true;
}
else {
c.set[i] = false;
}
c.size++;
}
return c;
}
IntSet operator = (const IntSet a) {
return IntSet(a);
}
IntSet operator += (IntSet a) {
return IntSet(operator+(a));
}
IntSet operator *= (IntSet a) {
return IntSet(operator * (a));
}
IntSet operator -= (IntSet a) {
return IntSet(operator - (a));
}
IntSet operator == (const IntSet a) const{
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return false;
}
}
return true;
}
IntSet operator != (IntSet a) {
for(int i = 0; i < size; i++) {
if(set[i] != a.set[i]) {
return true;
}
}
return false;
}
IntSet operator << (IntSet a) {
cout << "{";
for(int i = 0; i < size; i++) {
if(set[i]) {
cout << " " << i;
}
}
cout << "}";
}
IntSet operator >> (IntSet a) {
int index;
while(cin >> index && index != SENTINEL) {
insert(index);
}
}
Here is the attached intset.h code:
#ifndef INTSET_H
#define INTSET_H
#include <iostream>
#include <algorithm>
using namespace std;
class IntSet {
public:
//Constructors
IntSet();
IntSet(int);
IntSet(int, int);
IntSet(int, int, int);
IntSet(int, int, int, int);
IntSet(int, int, int, int, int);
IntSet(const IntSet&); // M: Added the &; must be a pointer or reference
~IntSet();
//Overloaded Operators M: Added 'IntSet' in front of the word 'operator.'
// It was required syntax.
IntSet operator+(IntSet);
IntSet operator*(IntSet);
IntSet operator-(IntSet);
IntSet operator=(IntSet);
IntSet operator+=(IntSet);
IntSet operator*=(IntSet);
IntSet operator-=(IntSet);
IntSet operator==(IntSet);
IntSet operator!=(IntSet);
IntSet operator<<(IntSet);
IntSet operator>>(IntSet);
//Functions
bool insert(int);
bool remove(int);
bool isEmpty();
bool isInSet(int);
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
#include "IntSet.cpp"
#endif
I haven't had much experience with header files so it wouldn't surprise me if I formatted something incorrectly but I'm looking at plenty of other samples provided by the professor and there isn't anything unusual about mine. I thought maybe it had something to do with the order listed in the .h file and that I wasn't following the same exact order in the .cpp but nothing changed when I had everything listed in the same order.
There is a lot that is wrong with your code. We are going to have to jump around a bit between the header and the implementation. Ready?
In your header you do this:
class IntSet {
/* stuff */
private:
bool set[];
};
First of all, the name set is a bad choice: it is the name of a class in namespace stdw which you are importing by having using namespace std in your header file. This can be confusing at best.
More importantly, the syntax bool set[] isn't correct in this context. Even if your compiler allows it, it's an extension. Who knows what it does and how it will behave on other compilers? Avoid it.
If you want to declare an array, declare an array. If you want to declare a pointer, declare a pointer. Just remember: an array isn't a pointer.
Unfortunately you don't, becase later on in your code you do this:
set = new bool[size];
What is this supposed to do? set isn't a pointer, it's some kind of array, and you cannot assign a pointer to an array.
Now, we get to the second problem: you declare some member variables for your class, in your header file:
class IntSet {
/* some stuff here */
private:
const int MAXSIZE;
int size;
bool set[];
const int SENTINEL;
};
Then in your implementation you have the following code floating up at the top:
int size;
const int MAXSIZE = 25000;
bool set[MAXSIZE];
const int SENTINEL = -1;
I don't think that this does what you think it does. It seems that your intention is to initialize those variables, but that's not what happens. Remember, those variables only exist as members variables that belong to a particular instance of a class, and they are not "free-standing". So what's happening here?
Well, this declares all these variables again, so you have variables called MAXSIZE, size, set and SENTINEL that are valid anywhere in that translation unit (i.e. the .cpp file), independent of the member variables in the class.
This, of course, means that the member variables with those names aren't initialized (well, except set which you assign a pointer to, which we already know is wrong). This will cause your code to exhibit undefined behavior. After all, the value of an uninitialized variable can be anything at all.
If your intention had been to initialize the class members, then you should remove that code and initialize those variables in your constructor(s):
IntSet::IntSet(int a, int b, int c, int d, int e)
: size(a), MAXSIZE(25000), SENTINEL(-1)
{
/* whatever*/
}
Notice, by the way, how I used IntSet:: in front of the constructor name? This is called the scope resolution operator. Remember, there is no constructor called IntSet. The constructor belongs to a class, which is called IntSet, and outside of that class, it's proper name is IntSet::IntSet. A small example may help:
class Test
{
int Length;
public:
/* notice how inside the class, you only need Test
* when providing a body for the constructor. This
* makes sense. You know which class you inside of.
*/
Test()
: Length(0)
{
}
Test(int len);
};
/* Now we are outside the class. We need to help
* the compiler out and tell it what class the
* function belongs to.
*/
Test::Test(int len)
: Length(len)
{
}
A tangential point as to do with the names that you are using. What's a? Why do you use a to initialize something called size? You should choose meaningful variables names that help document the code so that when you have to read it back your head doesn't explode.
Another tangential point is that if variables like MAXSIZE and SENTINEL are going to be shared between all instances of the class, then, for future reference, you should probably consider making them static class members.
Lastly, you have this bit of code in your header file
#include "IntSet.cpp"
This is, almost certainly, not correct. You should never do this (there may be some who think that there are exceptions, but don't learn bad habits at this point. When you know enough to stumble on this legitimately, then you will know enough to determine whether it's the right thing to do or not).
What makes it worse is that your implementation file contains:
#include "IntSet.h"
Think about what you are doing here: when the compiler is processing the file IntSet.h you are telling to also process the file IntSet.cpp. The file IntSet.cpp tells the compiler to process the file IntSet.h. Which tells the compiler to process the file IntSet.cpp. And so on and so forth.
Generally speaking, implementation files (.cpp) will include header files. Header files will only include other header files.
There are a few other issues, but you should probably fix all these things, and then, if you are still having issues, post a new question and we can go from there.
Good luck!
You need to put the name of the class and :: before defining a member function.
IntSet::IntSet(int a, int b, int c, int d, int e) {
//^^^^^^^^
//here
Do the same with the other constructors, the operators and methods.

Dyanamic Array Class, Program runs well but with Error

This is my Code
#ifndef INTLIST_H_INCLUDED
#define INTLIST_H_INCLUDED
#include <iostream>
using namespace std;
class intList
{
int upper_bound;
int arr[0];
public:
intList(){ arr[0] = 0; upper_bound = 0; }
void append(int x);
void sort();
friend ostream & operator << (ostream &, intList&);
inline int len(){ return upper_bound; }
inline int &operator [](int x){ return arr[x]; }
private:
void increment(int *a, int &l);
void swap(int &a, int &b);
};
void intList::swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void intList::increment(int *a, int &b)
{
b++;
a[b] = 0;
}
void intList::append(int num)
{
arr[upper_bound] = num;
increment(arr, upper_bound);
}
void intList::sort()
{
for(int i = 0; i < upper_bound; i++)
{
int minLoc = i;
for(int j = i+1; j<upper_bound; j++)
{
if(arr[j] < arr[minLoc])
minLoc = j;
}
if(minLoc != i)
swap(arr[i], arr[minLoc]);
}
}
ostream& operator << (ostream & dout, intList &a)
{
dout << "[ ";
for(int i = 0; i<a.upper_bound-1; i++)
dout << a.arr[i] << ", ";
dout << a.arr[a.upper_bound-1] << " ]";
return dout;
}
#endif // INTLIST_H_INCLUDED
The Code does its work perfectly fine. But at the end the Program Crashes. Giving some error like
process returned -1073741819 (0xC0000005) execution time : some seconds.
Just didn't get where am I going wrong.
This looks bad:
int arr[0];
First, C++ doesn't allow zero-sized fixed size arrays. Second, your code certainly needs more than a zero sized array.
Whatever use you make of this code is undefined behaviour (UB). UB includes code seemingly "working perfectly fine".
Your code has several problems.
For example, you have a fixed array of 0 size. If you want a dynamically growable array, you can use std::vector: you can add new items at the end of the vector (dynamically resizing it) using push_back() method:
#include <vector>
// Start with an empty vector
std::vector<int> v;
// Add some items to it
v.push_back(10);
v.push_back(20);
....
Note also that in header files it's not good to insert a using namespace std;. In this way you pollute the global namespace with STL classes, which is bad. Just use std:: prefix in header files.
Moreover, if you want to print the class content to an output stream, you may want to take the class as a const reference, since instances of the class are input parameters (you observe them and print their content to the stream):
std::ostream& operator<<(std::ostream& os, const IntList& a)
{
....
}

deleting element objects of a std vector using erase : a) memory handling and b) better way?

I have a vec_A that stores instances of class A as: vec_A.push_back(A());
I want to remove some elements in the vector at a later stage and have two questions: a) The element is deleted as: vec_A.erase(iterator) Is there any additional code I need to add to make sure that there is no memory leak? .
b) Assume that condition if(num <5) is if num is among a specific numberList. Given this, is there a better way to delete the elements of a vector than what I am illustrating below?
#include<vector>
#include<stdio.h>
#include<iostream>
class A {
public:
int getNumber();
A(int val);
~A(){};
private:
int num;
};
A::A(int val){
num = val;
};
int A::getNumber(){
return num;
};
int main(){
int i =0;
int num;
std::vector<A> vec_A;
std::vector<A>::iterator iter;
for ( i = 0; i < 10; i++){
vec_A.push_back(A(i));
}
iter = vec_A.begin();
while(iter != vec_A.end()){
std::cout << "\n --------------------------";
std::cout << "\n Size before erase =" << vec_A.size();
num = iter->getNumber() ;
std::cout << "\n num = "<<num;
if (num < 5){
vec_A.erase(iter);
}
else{
iter++;
}
std::cout << "\n size after erase =" << vec_A.size();
}
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
a) The element is deleted as:
vec_A.erase(iterator) Is there any
additional code I need to add to make
sure that there is no memory leak? .
Yes, that's all you need to do. There will be no memory leak. Since you didn't allocate yoour object on heap, when you did vec_A.push_back(A()) a new object is copied into the vector. When you do erase, vector will take care of deleting the elements.
Assume that condition if(num <5) is if
num is among a specific numberList.
Given this, is there a better way to
delete the elements of a vector than
what I am illustrating below?
Yes, you can remove/erase idiom. This is an example:
class A
{
public:
A(int n) : m_n(n)
{
}
int get() const
{
return m_n;
}
private:
int m_n;
};
bool lessThan9(const A& a)
{
return a.get() < 9;
}
//Or if you want for a generic number
struct Remover : public std::binary_function<A,int,bool>
{
public:
bool operator()(const A& a, int n)const
{
return a.get() < n;
}
};
int main()
{
std::vector<A> a;
a.push_back(A(10));
a.push_back(A(8));
a.push_back(A(11));
a.push_back(A(3));
a.erase(std::remove_if(a.begin(), a.end(), lessThan9), a.end());
//Using the user-defined functor
a.erase(std::remove_if(a.begin(), a.end(), std::bind2nd(Remover(), 9)), a.end());
return 0;
}
1) Resource handling is done by the class itself. The destructor of a class is responsible to ensure that there is no memory leak.
2) Removing elements from a vector is best done back-to-front:
for (std::vector<A>::reverse_iterator it = vec_A.rend(); it != vec_A.rbegin(); --it)
{
if (it->getNumber() < 5) {vec_A.erase(it.base());}
}