Is it possible to create a vector of vector?

  • Thread starter Ramon F Herrera
  • Start date
R

Ramon F Herrera

Newbie alert: I come from the C side, struggling to learn C++.

I need a two-dimensional data structure. I first tried a regular
vector and added the 2nd dimension with my own structs and pointers. I
couldn't make it work. Too many illegal assignments.

My next attempt was to create a vector of vector (or list of vector,
etc.). The compiler (MSVC++) doesn't seem to like such structure. I
guess I could try gcc, but let's hear the experts' opinions.

Your suggestions are most welcome.

-RFH
 
L

LR

Ramon said:
My next attempt was to create a vector of vector (or list of vector,
etc.).

This seems a very reasonable approach.

The compiler (MSVC++) doesn't seem to like such structure.

Can you please post a small example that demonstrates the problem.

Can you also be more specific about the problem that you're having.


LR
 
M

Mauro Ciancio

Newbie alert: I come from the C side, struggling to learn C++.

I need a two-dimensional data structure. I first tried a regular
vector and added the 2nd dimension with my own structs and pointers. I
couldn't make it work. Too many illegal assignments.

My next attempt was to create a vector of vector (or list of vector,
etc.). The compiler (MSVC++) doesn't seem to like such structure. I
guess I could try gcc, but let's hear the experts' opinions.

Your suggestions are most welcome.

-RFH

Mi english is not so good. Im trying to explain.

For example:

std::vector< std::vector<int> > myVector; // this creates a vector of
vector of integers

Now, you can do this:

std::vector<int> vector;
vector.push_back(1);

myVector.push_back(vector);

then:

std::cout << myVector[0][0] << std::endl; // this prints 1

If you want to initialize a vector of vector with a fixed size use the
following line:

std::vector< std::vector<int> > myVector (number_of_rows,
std::vector<int>(number_of_colums, default_value));

Read http://www.sgi.com/tech/stl/Vector.html to understand the
constructor calls.

I hope you understand.

Regards
 
D

Daniel Pitts

Ramon said:
Newbie alert: I come from the C side, struggling to learn C++.

I need a two-dimensional data structure. I first tried a regular
vector and added the 2nd dimension with my own structs and pointers. I
couldn't make it work. Too many illegal assignments.

My next attempt was to create a vector of vector (or list of vector,
etc.). The compiler (MSVC++) doesn't seem to like such structure. I
guess I could try gcc, but let's hear the experts' opinions.

Your suggestions are most welcome.

-RFH

#include <vector>

int main(int argc, char *argv[]) {
std::vector<std::vector<int> > vectovect;
vectovect.resize(20);
for (std::vector<std::vector<int> >::iterator i = vectovect.begin();
i != vectovect.end(); ++i) {
i->resize(30);
}
}
 
D

Daniel Pitts

Daniel said:
Ramon said:
Newbie alert: I come from the C side, struggling to learn C++.

I need a two-dimensional data structure. I first tried a regular
vector and added the 2nd dimension with my own structs and pointers. I
couldn't make it work. Too many illegal assignments.

My next attempt was to create a vector of vector (or list of vector,
etc.). The compiler (MSVC++) doesn't seem to like such structure. I
guess I could try gcc, but let's hear the experts' opinions.

Your suggestions are most welcome.

-RFH

#include <vector>

int main(int argc, char *argv[]) {
std::vector<std::vector<int> > vectovect;
vectovect.resize(20);
for (std::vector<std::vector<int> >::iterator i = vectovect.begin();
i != vectovect.end(); ++i) {
i->resize(30);
}
}
Ah, listen to Mauro's advice. I didn't know about those constructors
that would ease your use :)
 
R

Ramon F Herrera

This seems a very reasonable approach.


Can you please post a small example that demonstrates the problem.


Well, I figured out that it is possible to create such contraptions.
There are at least two ways:

typedef vector<RadioButtonNode> RadioButtonGroup;
vector<RadioButtonGroup> ListOfRadioButton;

and the more succinct:

vector<vector<RadioButtonNode>> ListOfRadioButton;

Now I have to investigate the kind suggestions from Mauro and Daniel.

Thanks, Daniel!
Grazie tanti, Mauro!

-Ramon
 
R

red floyd

Ramon said:
Well, I figured out that it is possible to create such contraptions.
There are at least two ways:

typedef vector<RadioButtonNode> RadioButtonGroup;
vector<RadioButtonGroup> ListOfRadioButton;

and the more succinct:

vector<vector<RadioButtonNode>> ListOfRadioButton;

Your problem is here. The compiler is interpreting the closing >> as a
single token. Put a space between them:

vector<vector<RadioButtonNode> > ListOfRadioButton;

Note the space.
 
W

William Xu

red floyd said:
Your problem is here. The compiler is interpreting the closing >> as a
single token. Put a space between them:

vector<vector<RadioButtonNode> > ListOfRadioButton;

Note the space.

Which is really annoying...

--
William

http://williamxu.net9.org

<devkev> yeah i saw the lightning gun and where you were going, thinking
you were gonna kick some ass :)
<devkev> didnt realise it would be your own :)
 
K

Kai-Uwe Bux

Daniel said:
Don't make a vector of vectors. Better would be to make a matrix class
that is inherently 2D. See the FAQ for an example.

That depends very much on whether the 2D structure is rectangular or whether
it is ragged like a text broken up into lines of different length.

For a rectangular array, a matrix like container class is probably the way
to go as it guarantees the invariants for rectangularity. For a ragged
structure, I don't see what is wrong with a vector of vectors. Of course,
one can always encapsulate that in a class to hide implementation details.
But whether that is worth the effort cannot be said without knowing the
particulars of the project. (And, for all we know, the OP might be asking
about how to implement the internals of a text buffer class.)


Best

Kai-Uwe Bux
 
L

LR

Ramon said:
Well, I figured out that it is possible to create such contraptions.
There are at least two ways:

typedef vector<RadioButtonNode> RadioButtonGroup;
vector<RadioButtonGroup> ListOfRadioButton;

and the more succinct:

vector<vector<RadioButtonNode>> ListOfRadioButton;


The names that you've given these things makes me wonder what it is
you're trying to do.

Why is a std::vector<RadioButtonNode> a RadioButtonGroup and a
std::vector<std::vector<RadioButtonNode> > a ListOfRadioButton?

Perhaps a ListOfRadioButtonGroups? Or a GroupOfRadioButtonGroups?


LR
 
B

Bo Persson

red said:
Your problem is here. The compiler is interpreting the closing >>
as a single token. Put a space between them:

vector<vector<RadioButtonNode> > ListOfRadioButton;

Note the space.

This depends on what version of the compiler you have. Recent editions
have already noticed that >> should work as well, accordning to the
next language revision.


Bo Persson
 
R

Ramon F Herrera

The names that you've given these things makes me wonder what it is
you're trying to do.

Why is a std::vector<RadioButtonNode> a RadioButtonGroup and a
std::vector<std::vector<RadioButtonNode> > a ListOfRadioButton?

Perhaps a ListOfRadioButtonGroups? Or a GroupOfRadioButtonGroups?

LR

Good point.

-RFH
 
R

Ramon F Herrera

That depends very much on whether the 2D structure is rectangular or whether
it is ragged like a text broken up into lines of different length.

For a rectangular array, a matrix like container class is probably the way
to go as it guarantees the invariants for rectangularity. For a ragged
structure, I don't see what is wrong with a vector of vectors. Of course,
one can always encapsulate that in a class to hide implementation details.
But whether that is worth the effort cannot be said without knowing the
particulars of the project. (And, for all we know, the OP might be asking
about how to implement the internals of a text buffer class.)

Best

Kai-Uwe Bux


You are absolutely right, Kai-Uwe. The side of my structure happens to
be completely ragged.

What I am saving is a set of radio button (or check mark) widgets.
Some of them belong to a logical group, which is used to provide the
mutual exclusivity. When the user clicks on one, the other N-1 are
automatically turned off.

See below how I ended up implementing the insertion. If two buttons
have the same name, they belong in the same logical group. Observant
readers will notice this is of PDF.

-RFH

------------

void insertGroupedRadioButton(RadioButtonNode *radio)
{
int i;
RadioButtonGroup *empty_vector = new RadioButtonGroup();

for (i = 0; i < (int)ListOfRadioButton.size() && radio->name !=
ListOfRadioButton[0].name; i++);

if (i == ListOfRadioButton.size()) {
ListOfRadioButton.push_back(*empty_vector);
}

ListOfRadioButton.push_back(*radio);
}
 
K

Kai-Uwe Bux

Ramon said:
What I am saving is a set of radio button (or check mark) widgets.
Some of them belong to a logical group, which is used to provide the
mutual exclusivity. When the user clicks on one, the other N-1 are
automatically turned off.

See below how I ended up implementing the insertion. If two buttons
have the same name, they belong in the same logical group. Observant
readers will notice this is of PDF.

-RFH

------------

void insertGroupedRadioButton(RadioButtonNode *radio)
{
int i;
RadioButtonGroup *empty_vector = new RadioButtonGroup();

for (i = 0; i < (int)ListOfRadioButton.size() && radio->name !=
ListOfRadioButton[0].name; i++);

if (i == ListOfRadioButton.size()) {
ListOfRadioButton.push_back(*empty_vector);
}

ListOfRadioButton.push_back(*radio);
}


It looks to me that

std::multimap< std::string, RadioButtonNode* >

is something that might be of interest to you. E.g.:

#include <string>
#include <map>
#include <cassert>
#include <iostream>
#include <ostream>

class RadioButtonNode {

std::string the_name;

public:

RadioButtonNode ( std::string const & name )
: the_name ( name )
{}

std::string const & name ( void ) const {
return ( the_name );
}

void on ( void ) {
std::cout << "on: " << name() << " [" << this << "]\n";
}

void off ( void ) {
std::cout << "off: " << name() << " [" << this << "]\n";
}

};


class ButtonCollection {

typedef std::multimap< std::string, RadioButtonNode* > map_type;

map_type the_data;

public:

void insert ( RadioButtonNode * radio ) {
the_data.insert( make_pair( radio->name(), radio ) );
}

void on ( RadioButtonNode * radio ) {
assert( radio != 0 );
for ( map_type::iterator iter = the_data.lower_bound( radio->name() );
iter != the_data.upper_bound( radio->name() ); ++iter ) {
if ( iter->second == radio ) {
iter->second->on();
} else {
iter->second->off();
}
}
}

};


int main ( void ) {
RadioButtonNode * n1 = new RadioButtonNode ( "n" );
RadioButtonNode * n2 = new RadioButtonNode ( "n" );
RadioButtonNode * n3 = new RadioButtonNode ( "n" );
RadioButtonNode * n4 = new RadioButtonNode ( "n" );
RadioButtonNode * q1 = new RadioButtonNode ( "q" );
RadioButtonNode * q2 = new RadioButtonNode ( "q" );
RadioButtonNode * q3 = new RadioButtonNode ( "q" );
RadioButtonNode * q4 = new RadioButtonNode ( "q" );

ButtonCollection the_collection;
the_collection.insert( n1 );
the_collection.insert( n2 );
the_collection.insert( n3 );
the_collection.insert( n4 );
the_collection.insert( q1 );
the_collection.insert( q2 );
the_collection.insert( q3 );
the_collection.insert( q4 );

the_collection.on( n2 );
}



Best

Kai-Uwe Bux
 
K

Kai-Uwe Bux

Kai-Uwe Bux said:
Ramon said:
What I am saving is a set of radio button (or check mark) widgets.
Some of them belong to a logical group, which is used to provide the
mutual exclusivity. When the user clicks on one, the other N-1 are
automatically turned off.

See below how I ended up implementing the insertion. If two buttons
have the same name, they belong in the same logical group. Observant
readers will notice this is of PDF.

-RFH

------------

void insertGroupedRadioButton(RadioButtonNode *radio)
{
int i;
RadioButtonGroup *empty_vector = new RadioButtonGroup();

for (i = 0; i < (int)ListOfRadioButton.size() && radio->name !=
ListOfRadioButton[0].name; i++);

if (i == ListOfRadioButton.size()) {
ListOfRadioButton.push_back(*empty_vector);
}

ListOfRadioButton.push_back(*radio);
}


It looks to me that

std::multimap< std::string, RadioButtonNode* >

is something that might be of interest to you. E.g.:

[snip]

There even is a way to hide the collection:

#include <string>
#include <map>
#include <cassert>
#include <iostream>
#include <ostream>

class RadioButtonNode {

std::string the_name;


class ButtonCollection {

typedef std::multimap< std::string, RadioButtonNode* > map_type;

map_type the_data;

public:

void insert ( RadioButtonNode * radio ) {
the_data.insert( make_pair( radio->name(), radio ) );
}

void erase ( RadioButtonNode * radio ) {
assert( radio != 0 );
for ( map_type::iterator iter =
the_data.lower_bound( radio->name() );
iter != the_data.upper_bound( radio->name() ); ++iter ) {
if ( iter->second == radio ) {
the_data.erase( iter );
return;
}
}
}

void on ( RadioButtonNode * radio ) {
assert( radio != 0 );
for ( map_type::iterator iter =
the_data.lower_bound( radio->name() );
iter != the_data.upper_bound( radio->name() ); ++iter ) {
if ( iter->second == radio ) {
iter->second->turn_on();
} else {
iter->second->turn_off();
}
}
}

void off ( RadioButtonNode * radio ) {
assert( radio != 0 );
for ( map_type::iterator iter =
the_data.lower_bound( radio->name() );
iter != the_data.upper_bound( radio->name() ); ++iter ) {
if ( iter->second == radio ) {
iter->second->turn_off();
} else {
iter->second->turn_on();
}
}
}

};

ButtonCollection & the_collection ( void ) {
static ButtonCollection dummy;
return ( dummy );
}

protected:

virtual
void turn_on ( void ) {
std::cout << "on: " << name() << " [" << this << "]\n";
}

virtual
void turn_off ( void ) {
std::cout << "off: " << name() << " [" << this << "]\n";
}

public:

RadioButtonNode ( std::string const & name )
: the_name ( name )
{
the_collection().insert( this );
}

~RadioButtonNode ( void ) {
the_collection().erase( this );
}

std::string const & name ( void ) const {
return ( the_name );
}

void on ( void ) {
the_collection().on( this );
}

void off ( void ) {
the_collection().off( this );
}

};

int main ( void ) {
RadioButtonNode * n1 = new RadioButtonNode ( "n" );
RadioButtonNode * n2 = new RadioButtonNode ( "n" );
RadioButtonNode * n3 = new RadioButtonNode ( "n" );
RadioButtonNode * n4 = new RadioButtonNode ( "n" );
RadioButtonNode * q1 = new RadioButtonNode ( "q" );
RadioButtonNode * q2 = new RadioButtonNode ( "q" );
RadioButtonNode * q3 = new RadioButtonNode ( "q" );
RadioButtonNode * q4 = new RadioButtonNode ( "q" );

n2->on();
std::cout << '\n';
delete n1;
n2->off();
}


Best

Kai-Uwe Bux
 
K

Kai-Uwe Bux

Kai-Uwe Bux said:
Kai-Uwe Bux said:
Ramon said:
What I am saving is a set of radio button (or check mark) widgets.
Some of them belong to a logical group, which is used to provide the
mutual exclusivity. When the user clicks on one, the other N-1 are
automatically turned off.

See below how I ended up implementing the insertion. If two buttons
have the same name, they belong in the same logical group. Observant
readers will notice this is of PDF.

-RFH

------------

void insertGroupedRadioButton(RadioButtonNode *radio)
{
int i;
RadioButtonGroup *empty_vector = new RadioButtonGroup();

for (i = 0; i < (int)ListOfRadioButton.size() && radio->name !=
ListOfRadioButton[0].name; i++);

if (i == ListOfRadioButton.size()) {
ListOfRadioButton.push_back(*empty_vector);
}

ListOfRadioButton.push_back(*radio);
}


It looks to me that

std::multimap< std::string, RadioButtonNode* >

is something that might be of interest to you. E.g.:

[snip]

There even is a way to hide the collection:

[snip]

Come to think of it: using multiset and a custom predicate, one can avoid
storing the name string twice:

#include <string>
#include <set>
#include <cassert>
#include <iostream>
#include <ostream>

class RadioButtonNode {

std::string the_name;

class ButtonCollection {

typedef bool (*RadioCompare)( RadioButtonNode*, RadioButtonNode*);

static
bool radio_cmp ( RadioButtonNode* lhs, RadioButtonNode* rhs ) {
assert( lhs != 0);
assert( rhs != 0 );
return ( lhs->name() < rhs->name() );
}

typedef std::multiset< RadioButtonNode*, RadioCompare > map_type;

map_type the_data;

public:

ButtonCollection ( void )
: the_data( &radio_cmp )
{}

void insert ( RadioButtonNode * radio ) {
the_data.insert( radio );
}

void erase ( RadioButtonNode * radio ) {
assert( radio != 0 );
for ( map_type::iterator iter =
the_data.lower_bound( radio );
iter != the_data.upper_bound( radio ); ++iter ) {
if ( *iter == radio ) {
the_data.erase( iter );
return;
}
}
}

void on ( RadioButtonNode * radio ) {
assert( radio != 0 );
for ( map_type::iterator iter =
the_data.lower_bound( radio );
iter != the_data.upper_bound( radio ); ++iter ) {
if ( *iter == radio ) {
(*iter)->turn_on();
} else {
(*iter)->turn_off();
}
}
}

void off ( RadioButtonNode * radio ) {
radio->turn_off();
}

};

ButtonCollection & the_collection ( void ) {
static ButtonCollection dummy;
return ( dummy );
}

protected:

virtual
void turn_on ( void ) {
std::cout << "on: " << name() << " [" << this << "]\n";
}

virtual
void turn_off ( void ) {
std::cout << "off: " << name() << " [" << this << "]\n";
}

public:

RadioButtonNode ( std::string const & name )
: the_name ( name )
{
the_collection().insert( this );
}

~RadioButtonNode ( void ) {
the_collection().erase( this );
}

std::string const & name ( void ) const {
return ( the_name );
}

void on ( void ) {
the_collection().on( this );
}

void off ( void ) {
the_collection().off( this );
}

};

int main ( void ) {
RadioButtonNode * n1 = new RadioButtonNode ( "n" );
RadioButtonNode * n2 = new RadioButtonNode ( "n" );
RadioButtonNode * n3 = new RadioButtonNode ( "n" );
RadioButtonNode * n4 = new RadioButtonNode ( "n" );
RadioButtonNode * q1 = new RadioButtonNode ( "q" );
RadioButtonNode * q2 = new RadioButtonNode ( "q" );
RadioButtonNode * q3 = new RadioButtonNode ( "q" );
RadioButtonNode * q4 = new RadioButtonNode ( "q" );

n2->on();
std::cout << '\n';
delete n1;
n3->on();
}


Best

Kai-Uwe Bux
 
E

Eric Pruneau

red floyd said:
Your problem is here. The compiler is interpreting the closing >> as a
single token. Put a space between them:

vector<vector<RadioButtonNode> > ListOfRadioButton;

Note the space.

When I have something like this I often use a typedef to make thing clearer

typedef vector<RadioButtonNode> vecOfRadioButtonNode;
vector<vecOfRadioButtonNode> MatrixOfRadioButton;

That way you cannot struggle with the >> problem.
 
F

Frank Birbacher

Hi!
void insertGroupedRadioButton(RadioButtonNode *radio)
{
int i;
RadioButtonGroup *empty_vector = new RadioButtonGroup();

for (i = 0; i < (int)ListOfRadioButton.size() && radio->name !=
ListOfRadioButton[0].name; i++);

if (i == ListOfRadioButton.size()) {
ListOfRadioButton.push_back(*empty_vector);
}

ListOfRadioButton.push_back(*radio);
}


Looks like a memory leak, by the way. The object to which "empty_vector"
points is neither explicitly deleted nor is it held by auto_ptr. Maybe
you just need a regular stack based instance:

void insertGroupedRadioButton(RadioButtonNode *radio)
{
int i;
RadioButtonGroup empty_vector;

for (i = 0; i < (int)ListOfRadioButton.size() && radio->name !=
ListOfRadioButton[0].name; i++);

if (i == ListOfRadioButton.size()) {
ListOfRadioButton.push_back(empty_vector);
}

ListOfRadioButton.push_back(*radio);
}

There is no "new" and so no leak.

Frank
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top