Vector of Struct

How to make a vector of structs?

  • (2 Pages)
  • +
  • 1
  • 2

21 Replies - 19354 Views - Last Post: 10 January 2010 - 11:41 AM Rate Topic: -----

#1 4D1  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 225
  • Joined: 22-October 09

Vector of Struct

Posted 09 January 2010 - 09:08 AM

Hi Guys,

I am looking to make a vector of a struct, however my struct will be within a class, I am fairly new to C++ and I dont know how to access a nested struct or class and I only came accross Vectors as a potential solution to my memory needs the the other day. I have searched google for some sample code or a tut on how to do this, but all google returns is examples where the struct is not nested within a class or examples that have a million lines of code that I cannot desipher.

basically I have:

class game
{
	struct score
	{
		string name;
		int score;
	};
	
	vector<score>scores;

//Some other class functions and variables etc 
};



I want to be able to add data to the struct and be sure that int's and string's go where they are supposed to, and then access the struct like an array and create a sorting function.

I have:

// functions to read in int's and strings from a file and save them to tempname and tempscore

int tempscore;
string tempname;

//How do I add these to the vector struct?

//Is this anywhere near right?

game::score.name.pushback(tempscore);

//Or

game::score->name.pushback();

//and then to output

scre[i].name;




Would someone be so kind as to point me in the right direction?

This post has been edited by 4D1: 09 January 2010 - 09:10 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Vector of Struct

#2 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Vector of Struct

Posted 09 January 2010 - 09:29 AM

If your struct is a part of your Class' internal implementation then you should have no reason to want to access it from outside of the class.

Instead of sweating over the detail of how the class is going to work, think about what the class is supposed to do. then you might come up with some functions which modify and access your stored data (although be aware that you can't have a data member with the same name as the struct itself)

e.g.
game my_game;
my_game.add_score("Joe Bloggs", 50); 


For which the member function within game might look similar to
class game
{
    struct player
    {
        std::string name;
        int score;
        player(std::string n, int s) : name(n), score(s) {}
    };
    std::vector<player> high_scores;
public:
    void add_score(std::string, int);
};
void game::add_score(std::string name, int score)
{
    high_scores.push_back( player(name,score) );
} 

This post has been edited by Bench: 09 January 2010 - 09:38 AM

Was This Post Helpful? 0
  • +
  • -

#3 4D1  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 225
  • Joined: 22-October 09

Re: Vector of Struct

Posted 09 January 2010 - 10:48 AM

Hello Bench thanks for the response, I dont want to just make this work I would prefer to understand why it works or why it doesnt. In the event in future I wanted to access the struct from within a class via main function how would it be done? Also I dont understand some of your example...

player(std::string n, int s) : name(n), score(s) {} //Why is this neccessary when an int and a string have already been declared

: name(n), score(s) {} //What is this bit doing?



Does the pushback function automatically assign int's and strings to the correct struct member?
Was This Post Helpful? 0
  • +
  • -

#4 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Vector of Struct

Posted 09 January 2010 - 10:57 AM

That's an initialisation list; its a way of ensuring that name and score are initialised with values when a player struct object is created using that constructor. the colon : after the constructor signature denotes the start of the list - each initialiser is separated with a comma.
the curly brackets {} are just the start/end of the (empty) constructor body - its got no work to do since the initialisation list has already done all the work.

In this case, player::name is initialised using the constructor argument 'n', and player::score is initialised using the constructor argument 's'.

e.g, this call invokes the player(string, int) constructor to create a temporary player object before copying that object into the high_scores vector.
void game::add_score(std::string name, int score)
{
    high_scores.push_back( player(name,score) );
}
push_back knows that it needs to automatically grow the size of the high_scores vector by 1 to accommodate the new player object

This post has been edited by Bench: 09 January 2010 - 11:01 AM

Was This Post Helpful? 0
  • +
  • -

#5 4D1  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 225
  • Joined: 22-October 09

Re: Vector of Struct

Posted 09 January 2010 - 12:58 PM

Sorry I still cant get this to work???

struct score
	{
		string name;
		string user_score;
	};

	string tempuser, tempscore;
	vector <score> scores;


		int i=0;

		while(!input.eof())
		{
			getline(input, tempuser);

			getline(input, tempscore);

			scores.push_back(score(tempuser));

			scores.push_back(score(tempscore));

			cout << "\n\t\t\t" << scores[i].name << " ";

			cout << score[i].user_score << "\n";

			i++;
		}

//I have also tried the following as per your example

			scores.push_back(score(name));

			scores.push_back(score(user_score));

//And

			scores.push_back(tempuser);

			scores.push_back(tempscore);


This post has been edited by 4D1: 09 January 2010 - 01:09 PM

Was This Post Helpful? 0
  • +
  • -

#6 Anarion  Icon User is offline

  • The Persian Coder
  • member icon

Reputation: 282
  • View blog
  • Posts: 1,456
  • Joined: 16-May 09

Re: Vector of Struct

Posted 09 January 2010 - 01:18 PM

In your vector, you have objects of type score. but you pushed back strings here:
scores.push_back(tempuser);
scores.push_back(tempscore);

You have to push back objects like this:
score sc1;
//assign string for members of sc1
scores.push_back(sc1);
//or if you want to work with array
score scarray[10]; //array of score
//assigning values to members in scarray
scores.push_back(scarray[3]); //adds the 4th score object of the array to the vector


Or you can use like what Bench mentioned.

Hope it helped you

This post has been edited by Anarion: 09 January 2010 - 01:22 PM

Was This Post Helpful? 0
  • +
  • -

#7 jimblumberg  Icon User is offline

  • member icon


Reputation: 4018
  • View blog
  • Posts: 12,401
  • Joined: 25-December 09

Re: Vector of Struct

Posted 09 January 2010 - 02:29 PM

View Post4D1, on 9 Jan, 2010 - 11:58 AM, said:

Sorry I still cant get this to work???

struct score
	{
		string name;
		string user_score;
	};

	string tempuser, tempscore;
	vector <score> scores;


		int i=0;

		while(!input.eof())
		{
			getline(input, tempuser);

			getline(input, tempscore);

			scores.push_back(score(tempuser));

			scores.push_back(score(tempscore));

			cout << "\n\t\t\t" << scores[i].name << " ";

			cout << score[i].user_score << "\n";

			i++;
		}

//I have also tried the following as per your example

			scores.push_back(score(name));

			scores.push_back(score(user_score));

//And

			scores.push_back(tempuser);

			scores.push_back(tempscore);



You must push_back a score structure not a string.


#include <string>
#include <vector>

struct score
{
   string name;
   int value;
}

int main()
{
   vector<score> scores;
   score tmpScore;

   tmpScore.name = "Tommy";
   tmpScore.value = 10;

   scores.push_back(tmpScore);
}



Was This Post Helpful? 0
  • +
  • -

#8 4D1  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 225
  • Joined: 22-October 09

Re: Vector of Struct

Posted 10 January 2010 - 06:26 AM

Thanks Anarion, I understand now, obviously I was trying to push back an object member or tmpstring and not the object itself. I now have a working vector that I can access like an array, but I am struggling with the sorting.

I have a few issues:
ifstream input;

input >> tempint; 
/*This doesn't work it seems 
to just keep trying to take in 
the same line over and over*/

getline(input, tempstring);
//So I have to use this with a string

tempint=strtol(tempstring);
//I have tried converting to a long int but it isnt working

myvector.sort(myvector.begin(), myvector.end());
/*This doesnt work for vector of
struct, unless I create a boolean
function to pass at the end*/

/*I have tried a bubble sort, but I 
assume it doesnt work because it 
cannot use > or < on a string*/



This is not my actual code just an example of what I have tried, can anyone explain how I would go about converting the getline() to an int or how to create a boolean function to sort my vector?

Thanks Guys

This post has been edited by 4D1: 10 January 2010 - 06:30 AM

Was This Post Helpful? 0
  • +
  • -

#9 Kohana  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 56
  • Joined: 09-January 10

Re: Vector of Struct

Posted 10 January 2010 - 06:51 AM

Hello 4D1 im Kohana nice to meet you.

Using a struct inside a class is always a little bit odd. You see, a struct is basically a low level class. When working with classes you might want to derive a class from the main class, this is called inheritance. I see no need for a struct inside your class. If you took away the syntax for struct but kept its variables your class can still access them using METHODS. getScore, addScore, getName, changeName etc.

Write your class like this,
class game
{
	 private:
		std::string name;
		int score;
public:
void setName(std::string);
void setScore(int);

std::string getName(void);
int getScore(void);
 
};



The above blue print is perfect for adding to a vector in your main.cpp.

In main you can create a vector of type game, maybe call it gameScores. From there you will be able to call this,

gameScores[0].setScore(10);
gameScores[0].setName("Kohana");



This help?

This post has been edited by Kohana: 10 January 2010 - 06:53 AM

Was This Post Helpful? 0
  • +
  • -

#10 Anarion  Icon User is offline

  • The Persian Coder
  • member icon

Reputation: 282
  • View blog
  • Posts: 1,456
  • Joined: 16-May 09

Re: Vector of Struct

Posted 10 January 2010 - 08:01 AM

Kohana said:

Using a struct inside a class is always a little bit odd

Please explain why it is a little odd? Sometimes you Have to do this (however there might be other ways, but this is not odd).

For bubble sort, as yourself said you cannot use < or > to compare strings, instead you can use the function compare which is defined inside <string> header. Here's the reference for this function.

Edit: For the sort function with a vector, use the sort function defined in the <algorithm header. the void function you have to provide is the function which takes two arguments of you desired type (the one vector is made of) and compares them, so you implement the compare function I mentioned inside this function and give it to the sort function :D then it is done!
Here's the reference for sort function :)

This post has been edited by Anarion: 10 January 2010 - 08:06 AM

Was This Post Helpful? 0
  • +
  • -

#11 4D1  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 225
  • Joined: 22-October 09

Re: Vector of Struct

Posted 10 January 2010 - 08:06 AM

Hello Kohana, thanks for the reply, I am new to C++ and being self taught there will obviously be areas where I have put 2 + 2 together and got 5, the reason I opted for a struct was because I wanted to push back objects of the struct into the vector, this way I could essentially store the players name and score in the same array to make it easier to sort them.

Would creating a vector of my base class not use extra memory storing multiple instances of the functions? Also I dont fully understand what your functions are doing, under public: you have a few void functions, I cant see there definitions, appologies if I am being a bit thick, the problem with learning from tutorials is there are often bit missed out.
Was This Post Helpful? 0
  • +
  • -

#12 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Vector of Struct

Posted 10 January 2010 - 08:08 AM

View Post4D1, on 10 Jan, 2010 - 01:26 PM, said:

I have a few issues:
tempint=strtol(tempstring);
//I have tried converting to a long int but it isnt working 
C++ uses stringstreams to convert between string and numeric types.

#include <sstream>
bool to_int(const std::string& from, int& to)
{
    std::istringstream buffer(from)
    if(buffer >> to)
        return true;
    else
        return false;
} 

// Elsewhere..

    int tempint;
    if( !to_int(tempstring, tempint) )
    {
        // handle error if tempstring does not hold a number
    }


View Post4D1, on 10 Jan, 2010 - 01:26 PM, said:

myvector.sort(myvector.begin(), myvector.end());
/*This doesnt work for vector of
struct, unless I create a boolean
function to pass at the end*/ 
You could do that, alternatively, give your game struct an overloaded operator< (less than), which is the default operator used for sorting (the standard sort uses the std::less function which assumes that operator< is defined for a type)
struct foo
{
    std::string name;
    int score;
    bool operator<( const foo& rhs ) const
    {
        return score < rhs.score;
    }
}; 




View PostKohana, on 10 Jan, 2010 - 01:51 PM, said:

Using a struct inside a class is always a little bit odd.
Not really - it shows that his score struct represents part of the game's internal implementation, and shouldnt be known outside the game class which seems perfectly reasonable to me. data hiding applies to types just as much as it applies to data members (e.g. just think about how the STL linked list is implemented - the "node" struct/class is not known to the user of std::list, but it exists nonetheless)

View PostKohana, on 10 Jan, 2010 - 01:51 PM, said:

You see, a struct is basically a low level class.
Actually the class and struct keywords do exactly the same thing - the only difference is that a struct defaults to public, whereas a class defaults to private, other than that they're completely interchangable.

View PostKohana, on 10 Jan, 2010 - 01:51 PM, said:

When working with classes you might want to derive a class from the main class,
But this doesn't represent the same relationship at all, the OP has been trying to build a relationship involving composition.

This post has been edited by Bench: 10 January 2010 - 11:42 AM

Was This Post Helpful? 0
  • +
  • -

#13 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 855
  • View blog
  • Posts: 2,338
  • Joined: 20-August 07

Re: Vector of Struct

Posted 10 January 2010 - 08:17 AM

View Post4D1, on 10 Jan, 2010 - 03:06 PM, said:

Would creating a vector of my base class not use extra memory storing multiple instances of the functions? Also I dont fully understand what your functions are doing, under public: you have a few void functions, I cant see there definitions, appologies if I am being a bit thick, the problem with learning from tutorials is there are often bit missed out.
Member functions do not occupy memory in a vector of a struct/class, however the important question you should answer is how storing the class in a vector would help, and whether it fits in with what you're actually trying to do; as far as I can see, there's no reason to store the game class in a vector, although perhaps I've missed something.
Was This Post Helpful? 1
  • +
  • -

#14 Kohana  Icon User is offline

  • D.I.C Head

Reputation: 22
  • View blog
  • Posts: 56
  • Joined: 09-January 10

Re: Vector of Struct

Posted 10 January 2010 - 08:28 AM

Using a struct inside a class as i said is bas practice, yes it'll work but why do it?

Look at my class 4D1. In private is name and score right? See the void setName(std::string name)? This means VOID as in it returns nothing, setName is the name of the function and (std::string name) means it takes a string into the funtion called name.

remember that a class should be written inside a HEADER.h file and for each function in the class you write what it does in the HEADER.cpp file. (where HEADER is the name of your class).

Anarion, putting something inside a struct means you can group multiple data types in effectively one variable. The class he is using already does this. Please dont over complicate things for this learner. He doesn't need the struct, end of story.

"You see, a struct is basically a low level class."
Actually the class and struct keywords do exactly the same thing - the only difference is that a struct defaults to public, whereas a class defaults to private, other than that they're completely interchangable."

uhhhh, yeah........thats what i just said.

"When working with classes you might want to derive a class from the main class,"
But this doesn't represent the same relationship at all, the OP has been trying to build a relationship involving composition.

I am aware of that, i was merely pointing out how one type of struct class can link to another. He may choose to have a PLAYER class as a base that derives a "SCORE" class. I didn't mean for him to use it in current project. Sorry for the confusion.
Was This Post Helpful? 0
  • +
  • -

#15 Anarion  Icon User is offline

  • The Persian Coder
  • member icon

Reputation: 282
  • View blog
  • Posts: 1,456
  • Joined: 16-May 09

Re: Vector of Struct

Posted 10 January 2010 - 08:31 AM

OK here's the other way I told:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

struct sth {
public:
	string str;
	sth(const string& n) : str(n) { }
};

bool strIsGreater(sth c1, sth c2) {
	if(c1.str.compare(c2.str) < 0) {
		return true;
	}
	return false;
}

int main() {
	vector<sth> v;
	v.push_back( sth("Riboflavine") );
	v.push_back( sth("Apple") );
	sort(v.begin(), v.end(), strIsGreater);
	for(int i=0; i<v.size(); ++i) {
		cout<<v.at(i).str<<endl;
	}
	return 0;
}

If you are not comfortable with operator overloading (not studied it yet), you can use the above code which defines a custom comparing function which compares two structs by comparing their internal strings.

Hope that helped you :)

This post has been edited by Anarion: 10 January 2010 - 08:33 AM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2