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

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);

Related

Problems with two-dimensional vector in 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
}

Can't copy newly created objects in the Class constructor to its vector member in C++

In the class constructor, I am initializing other objects and pushing these objects to my class vector member. From what I understand, the vector create a copy of the object and stores it so that it doesn't go out of scope. However, when verifying the objects in another class function, they are not initialized anymore. Here's a example code to explain the behaviour:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class Square {
private:
int size_ = 0;
int colour_ = 0;
public:
Square(){
size_ = 0;
colour_ = 0;
}
void init(int size, int colour) {
size_ = size;
colour_ = colour;
}
int get_size() { return size_; }
};
class SetSquares {
private:
std::vector<Square> squares_;
int number_;
public:
SetSquares(): number_(0) {}
void init(int num) {
number_ = num;
squares_.clear();
squares_.resize(num);
for (int i=0; i < num; i++) {
Square square;
square.init(i, i);
squares_.push_back(square);
}
}
void sample(int i) {
if (i >= number_) { return; }
std::cout << "Square size is: " << squares_[i].get_size() << std::endl;
}
};
int main()
{
SetSquares set_of_squares;
set_of_squares.init(7);
set_of_squares.sample(4);
return 0;
}
resize(n) will create n default constructed elements in a vector and push_back will append new elements after those n elements. Use reserve and push_back or resize and index operator as suggested in comment.

default values and negative indexes when creating vector class

I decided to train myself in classes and build a vecofint class, that would resemble a vector container with several methods.
My program works great, but I have found that I do not entirely understand some principles.
1. Default values:
Here is my class:
class vecofint {
public:
vecofint() : vec(new int[size1]) { zeros(); }
~vecofint() { delete vec; }
vecofint(const int size) { set(size); vec = new int[size1]; zeros(); }
vecofint& operator = (const vecofint& other) { vec = other.vec; size1 = other.size1; vec1 = other.vec1; }
vecofint(const vecofint& other) : vec(other.vec), size1(other.size1), vec1(other.vec1) {}
int getin(const int a) { return vec[a]; }
int get() { return size1; }
void set(const int a) { size1 = a; }
void setin(const int a, const int val) { vec[a] = val; }
int* pushback(const int val);
int* pushfront(const int val);
int* it;
void resize();
void resize1();
void zeros() {int * i = vec; fill(i, i + size1, 0);}
void print() { copy(vec, vec + size1, ostream_iterator<int>(cout, "\n")); }
private:
int size1 = 32;
int* vec;
int* vec1;
};
As you can see I assign all values of my created vector to 0. I do this for 2 reasons:
a) I have found that
vector <int> a(10);
copy(a.begin(), a.end(), ostream_iterator<int>(cout, " "));
prints 0 0 0 0 0 0 0 0 0 0;
b) I need some default values to implement my pushback method:
int* vecofint::pushback(const int val) {
int k = 0;
int* it = vec;
while (*it!=0) {
if (k == size1) {
resize();
it = vec+size1/2;
}
++k;
++it;
}
vec[k] = val;
return vec;
}
And I use zeros. But I do not like that, because it means that I cannot use 0 as not-default values.
First question:
How can I basically avoid these assignments to zeros, but still have basic values to iterate through the vector? Or maybe there are other methods on how to iterate through newly created space?
2) Negative indexes
Suppose I am trying, by mistake, access a negative index.
Second question:
What my program should write in this case? Some error?
I have found that in real vector nothing happens, at least until a destructor is called.

implementation of IntSetLIst

here is implementation IntSetList in c++
#include <iostream>
using namespace std;
class IntSetList{
private:
int n;
struct node{
int val;
node *next;
node(int v,node *p){val=v;next=p;}
};
node *head,*sentinel;
node *rinsert(node *p,int t){
if (p->val<t){
p->next=rinsert(p->next,t);
}
else if (p->val>t){
p=new node(t,p);
n++;
}
return p;
}
public:
IntSetList(int maxelens,int maxval){
sentinel=head=new node(maxval,0);
n=0;
}
int size() { return n;}
void insert(int t){ head=rinsert(head,t);}
void report(int *v){
int j=0;
for (node *p=head;p!=sentinel;p=p->next)
v[j++]=p->val;
}
void display (int *v){
for (int i=0;i<sizeof(v)/sizeof(v[0]);i++){
cout<<v[i];
}
}
};
int main(){
IntSetList s(10,15);
int v[10];
s.insert(7);
s.insert(2);
s.insert(1);
s.insert(11);
s.insert(13);
s.insert(14);
s.insert(5);
s.insert(6);
s.insert(12);
s.insert(9);
s.report(v);
s.display(v);
return 0;
}
but it does not show me any output of course there is c++ standart library but i need to implement myself so i am making practises please help what is wrong?
No output at all? I suspect that it is outputting at least one number, since sizeof(v) is at least as big as sizeof(v[0]), but probably only just as big, since a pointer is the same size as an int on most 32-bit computers.
The sizeof(v)/sizeof(v[0]) trick only work on arrays, not pointers. A common trick to get around this is to declare the function as a template, thus:
template <int N>
void display (int (&v)[N])
{
for (int i = 0; i < N; ++i)
{
cout << v[i];
}
}
A more conventional solution is to pass the length explicitly:
void display (int *v, int n)
{
for (int i = 0; i < n; ++i)
{
cout << v[i];
}
}
A couple of points to note:
This will mash all the numbers together because you haven't put any whitespace in between them.
The display function doesn't have to be a member of IntSetList, since it doesn't interact with the class at all.
The simplest solution, BTW, is to not write the function at all:
std::copy(v, v + sizeof(v)/sizeof(v[0]), std::ostream_iterator<int>(std::cout));

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());}
}