Am i doing this right, I want a map with a Integer as key, and struct as value. What is the easiest way to, say I want the object at 1. How do I retrieve the value of isIncluded? The last two lines in the code, I tried doing it, but then I realized I donĀ“t really know what is the way to retrieving values of structs in a numbered Map array.
Do I need to call cells.get(1) and assign that to a new temporarely struct to get its values?
/** set ups cells map. with initial state of all cells and their info*/
void setExcludedCells (int dimension)
{
// Sets initial state for cells
cellInfo getCellInfo;
getCellInfo.isIncluded = false;
getCellInfo.north = 0;
getCellInfo.south = 0;
getCellInfo.west = 0;
getCellInfo.east = 0;
for (int i = 1; i <= (pow(dimension, 2)); i++)
{
cells.put(i, getCellInfo);
}
cout << "Cells map initialized. Set [" << + cells.size() << "] cells to excluded: " << endl;
cells.get(getCellInfo.isIncluded);
cells.get(1);
}
the Map, is declared as an private instance variable like this:
struct cellInfo {
bool isIncluded;
int north; // If value is 0, that direction is not applicable (border of grid).
int south;
int west;
int east;
};
Map<int, cellInfo> cells; // Keeps track over included /excluded cells
From the documentation for Map, it appears that .get() returns a ValueType.
You would use it thus:
// Display item #1
std::cout << cells.get(1).isIncluded << "\n";
std::cout << cells.get(1).north << "\n";
Or, since the lookup is relatively expensive, you could copy it to a local variable:
// Display item #1 via initialized local variable
cellInfo ci = cells.get(1);
std::cout << ci.isIncluded << " " << ci.north << "\n";
// Display item #2 via assigned-to local variable
ci = cells.get(2);
std::cout << ci.isIncluded << " " << ci.north << "\n";
My best advice is to use the standard library's std::map data structure instead:
// Expensive way with multiple lookups:
std::cout << cells[1].isIncluded << " " << cells[1].north << "\n";
// Cheap way with one lookup and no copies
const cellinfo& ci(maps[1]);
std::cout << ci.isIncluded << " " << ci.north << "\n";
Related
I am creating std::list of struct elements. With a certain criterion, I want to store addresses of few elements (because those addresses don't change(?)) from the list into std::vector for quick access in another usage. An example of the things is given below
#include <iostream>
#include <vector>
#include <list>
struct Astruct{
double x[2];
int rank;
};
int main(int argc, char *argv[]) {
std::list<Astruct> ants;
std::vector< Astruct* > ptr;
for (auto i = 0; i != 20; ++i) {
Astruct local;
local.x[0] = 1.1;
local.x[1] = 1.2;
local.rank = i;
// put in list
ants.push_back(local);
// store address of odd numbers
// rather than temperory address, permenent address from list is needed
if(local.rank %2 == 0) ptr.push_back(&local);
}
// print the selected elements using addresses from the list
for(int num = 0; num != ptr.size(); num++){
Astruct *local;
local = ptr.at(num);
std::cout << " rank " << local->rank << "\n";
}
/*
// quick way to check whether certain address (eg 3rd element) exists in the std::vector
std::list<Astruct>::iterator it = ants.begin();
std::advance(it , 2);
for(int num = 0; num != ptr.size(); num++){
if(it == ptr.at(num)) std::cout << " exists in vector \n " ;
}
*/
// print memory in bytes for all variables
std::cout << " sizeof Astruct " << sizeof(Astruct) << "\n";
std::cout << " sizeof ants " << sizeof(ants) << "\n";
std::cout << " sizeof ptr " << sizeof(ptr) << "\n";
}
What's the way to access an address of a particular element from the list?
Is it efficient method to add elements to list? (in first for loop)
What is the quickest way to check whether certain address exists in the vector? (shown in comment block)
How to determine the memory size in bytes for different variables here? (end of the code)
Thanks.
What's the way to access an address of a particular element from the list?
address=&(*iterator);
Is it efficient method to add elements to list? (in first for loop)
the first loop does not use the list at all! (Ah, OK, after edition it does)
all the addresses which are stored in the vector refer to a local variable which disappears after each iteration; this is undefined behaviour (very probably, but nothing is certain, all these addresses are the same)
What is the quickest way to check whether certain address exists in the vector? (shown in comment block)
usualy std::find() from <algorithm> is suitable.
How to determine the memory size in bytes for different variables here? (end of the code)
std::cout << " sizeof Astruct " << sizeof(Astruct) << "\n"; is OK
std::cout << " sizeof ants " << size(ants)*sizeof(Astruct) << "\n"; is an approximation since we don't know the overhead of the list and its nodes
std::cout << " sizeof ptr " << size(ptr)*sizeof(Astruct *) << "\n"; is an approximation since we don't know the overhead of the vector
Take the following simple program:
struct Foo
{
int x;
int y;
int z;
string s;
};
int main()
{
Foo f1 = { 42,21,11, "Hello world" };
std::map<int, Foo> foomap;
foomap[400] = f1;
Foo* ptr = &foomap[400]; // cache a pointer to the element we just inserted.
cout << ptr->x << " " << ptr->y << " " << ptr->z << " " << ptr->s << std::endl;
// fill the map up with a bunch of other random items at random indices
for (int x = 0; x < 10000; x++)
{
int i = rand();
Foo f = { rand(), rand(), rand(), "Another string" };
if (foomap.find(i) == foomap.end())
{
foomap[i] = f;
}
}
Foo* ptr2 = &foomap[400];
cout << "f1 insert location has " << ((ptr == ptr2) ? "not changed" : "changed") << std::endl;
cout << ptr->x << " " << ptr->y << " " << ptr->z << " " << ptr->s << std::endl;
return 0;
}
So the program above caches a pointer to an item in the map. Then adds a whole lot more items into the map, and then validates if the first inserted item has changed location.
I was somewhat surprised when I ran it. The cached pointer stays intact:
42 21 11 Hello world
f1 insert location has not changed
42 21 11 Hello world
I would have assumed that as the map grows with respect to the number of items in it, the implementation might move items around - just like std::vector absolutely does.
So my question is this: Are items inserted into a map guaranteed to be at the same address as long as it's not removed from the map or replaced? Or is this implementation specific?
Yes, insertion / emplacement operations on map never invalidate iterators or references to existing items.
26.2.6 Associative containers [associative.reqmts]
9 The insert and emplace members shall not affect the validity of iterators and references to the container, and the erase members shall invalidate only iterators and references to the erased elements.
I am building a 2d game and I am storing all my enemy objects in an array. Right now I am trying to implement a quadtree. Currently I am just trying to build the quadtree and am not concerned with collisions. The code that pushes items to the quadtree is the following :
for (std::vector<Enemy>::iterator i=m_enemies.begin(); i != m_enemies.end(); ++i) {
std::cout << &(*i) << "Address of the object" << std::endl;
m_quad.Insert(&(*i));
}
The code for the Insert is the following :
void Quad::Insert(sf::RectangleShape* l_gameObject){
std::cout << &l_gameObject << "dsa1" << std::endl;
std::cout << "called insert " << m_objects.size() << std::endl;
m_objects.push_back(l_gameObject);
if (m_level < m_maxLevel) {
if (m_objects.size() > 3) {
std::cout<< "creating subregions " << m_objects.size() << std::endl;
m_subRegions.push_back(Quad(m_x,m_y,m_width/2.f, m_height/2, m_level + 1, m_maxLevel-1));
m_subRegions.push_back(Quad(m_x+m_width/2.f,m_y,m_width/2.f,m_height/2.f, m_level + 1, m_maxLevel-1));
m_subRegions.push_back(Quad(m_x+m_width/2.f, m_y + m_height/2.f, m_width/2.f, m_height/2.f, m_level + 1, m_maxLevel-1));
m_subRegions.push_back(Quad(m_x, m_y + m_height/2.f, m_width/2.f, m_height/2.f, m_level + 1, m_maxLevel-1));
std::vector<int> temp;
for (int i=0; i < m_objects.size(); i++){
for (int j=0; j< m_subRegions.size(); j++) {
if (m_subRegions[j].Contains(m_objects[i])) {
m_subRegions[j].Insert(m_objects[i]);
temp.push_back(i);
break;
}
}
}
for (int i = temp.size(); i > -1; i--){
m_objects.erase(m_objects.begin() + temp[i]);
}
}
}
}
When I print the address that I am passing to the Insert function and the one I have in the function I see that they are different. In fact the on in is always the same and the one I pass is always different as it should be. Could anyone clarify why that is the case ?
EDIT : Thanks to gsamaras for pointing out that I was printing the address of the parameter.
Followup question
When I use the methods of the object I am addressing in the first for loop I get the correct results, but when I do the same thing in the Insert function I get 0. Why is that ?
You are printing the address of the address.
Change this:
std::cout << &l_gameObject << "dsa1" << std::endl;
to this:
std::cout << l_gameObject << "dsa1" << std::endl;
in order to print the same thing as outside your of your function.
Inside Insert, you're printing the address of the parameter.
Outside Insert, you're printing the parameter's value.
You want
std::cout << l_gameObject << "dsa1" << std::endl;
since l_gameObject is the address you're passing in.
I'm trying to build a relational database for the class I'm in.
what's happening is that when I process my "Facts" and "Queries" input, I create a new relation object. And then I print them out. If I run one at a time they process just fine, but if I run them back to back, the second one modifies the contents of the vector of tokens within the other relation object.
Database.h
class Database
{
private:
datalogProgram program;
Relation theSchemes;
Relation theFacts;
std::vector<Token> FactsOrder;
public:
Database(datalogProgram input);
Database();
~Database();
Relation processSchemes(datalogProgram processme);
Relation processFacts(datalogProgram processme);
};
Database.cpp
And I apologize for all of the cout's I've been trying to debug this things for hours!
#include "Database.h"
#include <sstream>
Database :: Database(datalogProgram input)
{
// So first I will make a map with relations representing the Schemes Facts and Queries
// Thus I will have a database of schemes facts and queries, rules excluded and ignored for now.
program = input;
theSchemes = processSchemes(program);
theFacts = processFacts(program);
// just checking on progress.
std::cout << "SCHEMES" << std::endl;
theSchemes.printRelation();
std::cout << "FACTS" << std::endl;
theFacts.printRelation();
}
Database :: Database() {}
Database :: ~Database() {}
Relation Database :: processSchemes(datalogProgram input)
{
Relation temp;
// LETS START WITH SCHEMES
std::cout << "processing schemes" << std::endl;
std::vector<Scheme>* schemes = input.returnSchemeList();
// Process First Scheme
// Populate this first vector with ID's from schemes.
// std::vector<Token*> firstTuple;
std::vector<Token*> firstTuple;
std::vector<Token> idListONE;
firstTuple.push_back(input.returnFirstScheme()->returnFirstID());
// std::vector<Token> idListONE;
idListONE = input.returnFirstScheme()->returnCLEANidLIST();
for(int i = 0; i < input.returnFirstScheme()->returnCLEANidLIST().size(); i++)
firstTuple.push_back(&idListONE[i]);
temp = *new Relation(input.returnFirstScheme()->returnName(), firstTuple);
// NOW I NEED TO PROCESS THE REST OF THE SCHEMES
//Take a scheme off of the list, and work on it just like I did above.
for(int j = 0; j < schemes->size(); j++) {
// Populate this first vector with ID's from schemes.
std::vector<Token*> first;
first.clear();
first.push_back(schemes->at(j).returnFirstID());
std::vector<Token> idLista;
idLista.clear();
idLista = schemes->at(j).returnCLEANidLIST();
for(int i = 0; i < schemes->at(j).returnCLEANidLIST().size(); i++)
first.push_back(&idLista[i]);
temp.relationInsert(schemes->at(j).returnName(), first);
}
return temp;
//
// At this point I shoudl have a map with "Schemes" pointing to Relation Objects.
// I want to verify that this is working, so print out all data collected so far.
}
Relation Database :: processFacts(datalogProgram input)
{
Relation temporary;
// NOW WE PROCESS FACTS
// Order does matter, so I will create a vector to use as a key.
std::cout << "procesing facts" << std::endl;
std::vector<Fact>* facts = input.returnFactList();
std::string OUT2;
std::ostringstream convert2;
convert2 << facts->size();
OUT2 = convert2.str();
std::cout << "THE NUMBER OF FACTS IS " << OUT2 << std::endl;
// NOW I NEED TO PROCESS THE REST OF THE
//Take a scheme off of the list, and work on it just like I did above.
std::vector<Token*> firstTuple;
std::vector<Token> idListONE;
for(int j = 0; j < facts->size(); j++) {
std::cout << "NEW ITERATION:" << std::endl;
if(j==0) {
std::cout << "processing first fact" << std::endl;
// is the first Fact!
firstTuple.clear();
std::cout << "processing first fact --> tuple" << std::endl;
firstTuple.push_back(facts->at(j).returnFirstString());
idListONE.clear();
std::cout << "FIRST STRINGLIST" << std::endl;
idListONE = *facts->at(j).returnCleanStringList();
for(int i = 0; i < idListONE.size(); i++) {
std::cout << "FIRST STRING ITER" << std::endl;
firstTuple.push_back(&idListONE[i]);
}
FactsOrder.push_back(*facts->at(j).returnName());
std::cout << "creating first fact" << std::endl;
temporary = Relation(facts->at(j).returnName(), firstTuple);
} else {
std::cout << "processing A fact (ITER)" << std::endl;
// Populate this first vector with ID's from schemes.
std::vector<Token*> first;
first.clear();
std::cout << "processing fact, firststring (ITER)" << facts->at(j).returnFirstString()->getTokensValue() << std::endl;
first.push_back(facts->at(j).returnFirstString());
std::vector<Token> idLista;
idLista.clear();
std::cout << "getting stringlist (ITER)" << std::endl;
idLista = *facts->at(j).returnCleanStringList();
for(int i = 0; i < idLista.size(); i++) {
std::cout << "processing stringlist (ITER) ITER" << std::endl;
first.push_back(&idLista[i]);
}
FactsOrder.push_back(*facts->at(j).returnName());
std::cout << "adding fact" << std::endl;
temporary.relationInsert(facts->at(j).returnName(), first);
}
}
return temporary;
}
relation.cpp
Just so you can see it
Relation :: Relation(Token* key,std::vector<Token*> tuple)
{
std::pair<Token*,std::vector<Token*> > mypair (key,tuple);
contents.insert(mypair);
}
Relation :: Relation() {}
Relation :: ~Relation() {}
void Relation :: relationInsert(Token* key,std::vector<Token*> tuple)
{
std::pair<Token*,std::vector<Token*> > mypair (key,tuple);
contents.insert(mypair);
}
void Relation :: printRelation()
{
std::cout << "PRINT RELATION CALLED" << std::endl;
std::multimap<Token*,std::vector<Token*> >::iterator mapIT;
for(mapIT = contents.begin() ; mapIT != contents.end() ; mapIT ++) {
std::cout << "Key: " << mapIT->first->getTokensValue() "\nValues:" << std::endl;
for(int x = 0; x< mapIT->second.size() ; x++)
std::cout << " " << mapIT->second.at(x)->getTokensValue() << std::endl;
}
}
To solve your problem you must figure out object / pointer ownership in your code. Relation holds a relation between a pointer to Token and a list of other pointer to Tokens. It is ok to keep Token* rather then a copy of Token. (Especially if tokens can be large words you don't want to copy). But who "owns" and manages the tokens?
Lets look at an example
std::vector<Token*> firstTuple;
std::vector<Token> idListONE;
idListONE is a vector to actual Tokens. It is a function local variable so it will be discarded when we exit the function.
firstTuple is a vector to pointers of Tokens.
You push into it in the following manner:
firstTuple.push_back(&idListONE[i]);
So firstTuple tokens are pointers to the internal tokens inside idListONE. That might be valid but you must remember that as soon as idListONE is released or its memory is changed (its size increased for instance) firstTuple becomes invalid, because it will now point at memory that was released and using it may have undefined results and will likely crash the program.
Actually a few lines later you make that mistake:
temporary = Relation(facts->at(j).returnName(), firstTuple);
temporary is a Relation that holds a list to pointer of Tokens. It copies the list that means that it copies the token pointers. However the pointers it copies are to Tokens that belong to idListONE as soon as you exit the function idListONE is released and the pointers inside the Relation are no longer valid and using them is likely one source of the problems you are seeing. There might be additional problems like this in the code
In general there seems to be a lot of confusion about working with pointers vs working with objects.
Look at the following statement:
temp = *new Relation(input.returnFirstScheme()->returnName(), firstTuple);
new Relation(...) will allocate memory on the heap and initialize a Relation.
temp = *<ptr> will use operator= to copy the content on the right into temp. The Relation on the heap is forgotten and its memory is leaked.
Another example:
idListONE.clear();
std::cout << "FIRST STRINGLIST" << std::endl;
idListONE = *facts->at(j).returnCleanStringList();
first you clear idListONE then you use the operator= to overwrite it with a new list.
Why did you clear a list you are writing over?
Why do you return a pointer to a list from returnCleanStringList()? instead of a copy list or a const ref to an internal list? If you decided returnCleanStringList() should return a list by pointer rather then by value then why is the first thing you do is copying it?
Finally you really should choose one style and conform to it. In the long run it makes code clearer.
If you Camelize variable names then always do: idListONE -> idListOne
Also avoid members like 'idListONE', do you really need a different variables for the first index?
I have a somewhat unique situation that I can't quite get working.
I've followed a lot of examples of using maps of maps but the vector of shared pointers seems to throw me off a bit.
Suppose I have the following:
typedef boost::shared_ptr<RecCounts> RecCountsPtr;
typedef std::vector<RecCountsPtr> RecCountsPtrVec;
typedef std::map<std::string, RecCountsPtrVec> InnerActivityMap;
typedef std::map< std::string, InnerActivityMap > ActivityMap;
Where RecCounts is a simple structure.
Now, I think I've figured out how to populate my ActivityMap properly.
RecCountsPtr recCountsPtr(new RecCounts());
config.actType = "M";
config.mapDate = "2010/07";
recCountsPtr->iHousehold = "50";
recCountsPtr->iZero = "150";
config.actMap[config.actType][config.mapDate].push_back(recCountsPtr);
Yes? I don't get any compile/runtime errors for this...but since I haven't figured out how to access all the different elements of the map I can't confirm this!
This is the config structure:
struct Config
{
std::string actType;
std::string mapDate;
// Map
ActivityMap actMap;
InnerActivityMap innerActMap;
//Iterator
ActivityMap::iterator actMapIter;
InnerActivityMap::iterator innerActMapIter;
};
Now, suppose I want to access each element of the ActivityMap. How would I get the following elements?
The outer map Key?
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = "
<< (*config.actMapIter).first << std::endl;
}
This seemed to do the trick.
The inner map Key?
I can't figure this out.
The inner map vector elements?
I can do it like this if I know the two keys:
config.actMap[config.actType][config.mapDate][0]->iHouehold
config.actMap[config.actType][config.mapDate][0]->iZero
...but can't seem to figure out how to iterate through them. :(
This is what I've done to try and iterate through all elements.
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
for (config.innerActMapIter = config.innerActMap.begin();
config.innerActMapIter != config.innerActMap.end();
++config.innerActMapIter)
{
std::cout << "Inner Key = "
<< (*config.innerActMapIter).first << std::endl;
for (size_t i = 0;
i < config.actMap[(*config.actMapIter).first]
[(*config.innerActMapIter).first].size();
++i)
{
std::cout << "iHousehold = "
<< config.actMap[(*config.actMapIter).first]
[(*config.innerActMapIter).first]
[i]->iHousehold << std::endl;
std::cout << "iZero = "
<< config.actMap[(*config.actMapIter).first]
[(*config.innerActMapIter).first]
[i]->iZero << std::endl;
}
}
}
I don't get any errors but I only get the outer key print to the screen:
Outer Key = M
I suspect something is amiss with my inner iterator...in that it's not associated the ActivityMap. Even if I am correct I don't know how to make such an association.
Any suggestions?
ANSWER (thanks to crashmstr):
Here is a verbose version of the answer suggested by crashmstr.
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
InnerActivityMap innerActMap = (*config.actMapIter).second;
InnerActivityMap::iterator innerActMapIter;
for (innerActMapIter = innerActMap.begin();
innerActMapIter != innerActMap.end();
++innerActMapIter)
{
std::cout << "Inner Key = " << (*innerActMapIter).first << std::endl;
for (size_t i = 0;
i < config.actMap[(*config.actMapIter).first][(*innerActMapIter).first].size();
++i)
{
std::cout << "iHousehold = "
<< config.actMap[(*config.actMapIter).first]
[(*innerActMapIter).first]
[i]->iHousehold << std::endl;
std::cout << "iZero = "
<< config.actMap[(*config.actMapIter).first]
[(*innerActMapIter).first]
[i]->iZero << std::endl;
}
}
}
I get the following printed to the screen:
Outer Key = M
Inner Key = 2010/07
iHousehold = 50
iZero = 150
When iterating over a map, .first is the "key", and .second is the data that belongs to that key.
So in your case:
for (config.actMapIter= config.actMap.begin();
config.actMapIter != config.actMap.end();
++config.actMapIter)
{
std::cout << "Outer Key = " << (*config.actMapIter).first << std::endl;
//(*config.actMapIter).second is a std::map<std::string, RecCountsPtrVec>
//create a new for loop to iterate over .second
}