c++ vector iterator deference inconsistency - c++

I have the following code. When dereference in line 5, I got wrong value of (*it)->sec. while in line 8, I can obtain correct value. The only difference I noticed is one is inside the for loop, the other is outside the for loop. Is there some subtle point I missing here. I basically want to obtain the member value of the first element in the vector. What's the correct way of obtaining the first (*it)->sec before(outside) the for loop?
void print_allAddresses(std::vector<EntryObj *> EntryObj_vec){
std::cout << "time(sec:microsec) dataType memoryValue" << std::endl;
std::vector<EntryObj *>::iterator it;
it = EntryObj_vec.begin();
std::cout << (*it)->sec << std::endl; //EntryObj_vec.front()->sec also wrong here.
for(it = EntryObj_vec.begin(); it != EntryObj_vec.end(); ++it){
if(!(*it)->parameters.empty()){
std::cout << (*it)->sec << "." << (*it)->microsecond << " ";
std::map<std::string, std::string>::iterator it_map;
for (it_map = (*it)->parameters.begin(); it_map != (*it)->parameters.end(); it_map++){
std::cout << "(" << it_map->first<< ")" << " " << it_map->second << std::endl;
}
}
}
return;
}

Related

Attempting to access data in second portion of a map of maps C++

I am sorry if this has been asked before (It seems as though every question has been asked before but with the plethora of questions asked on stack overflow it is sometimes hard to find). I have created a map of maps and am attempting to access the data in the second map. However, this is giving me issues in that I am unable to do iter->second.first or iter->second.second. I am able to do iter->first and iter-> second, but iter-> second is just a map and I am attempting to get the values in the second. I currently have "iter-second[x]" (just trying to find different ways to access the values) but I'm sure there is an easier way to do this. Attached are images of my code, what the map looks like while debugging, and the map creation, if there is anything else you need please let me know.
When I create the map I am assigning the incoming vector of arrays to the first key (works great, then I am assigning an int variable "lineCount" that is keeping track of the lines that have been read in, then incrementing the value of the second key by one if it has already been found.
assigning key's and value code in map:
void Reggie::assignMap(std::vector <std::string> &incVector)
{
//std::string word;
for (int i = 0; i < incVector.size(); i++) {
wordMap[incVector[i]][lineCount] +=1;
}
}
printMap Code
void Reggie::printMap()
{
int nextLineCounter{ 0 };
for (std::map<std::string, std::map<int, int>>::iterator iter = wordMap.begin(); iter != wordMap.end(); iter++) {
//for (std::map<std::string, std::map<int, int>>::iterator secondIter = iter->second.begin(); iter != wordMap.end(); secondIter++) {
std::cout << iter->first << " (" << iter->second[2] << " : " << iter->second[1] << " )" << std::endl;
nextLineCounter++;
}
}
Creation of map of maps
std::map<std::string, std::map<int, int>, Compare>wordMap;
printMap debugging image
I'm a bit confused why you commented out the second loop. I mean it's wrong but surely you realise that you can't iterate through a map of maps with only one loop?
Here's the code corrected
for (std::map<std::string, std::map<int, int>>::iterator iter = wordMap.begin();
iter != wordMap.end();
iter++)
{
for (std::map<int, int>::iterator secondIter = iter->second.begin();
secondIter != iter->second.end();
secondIter++)
{
std::cout << iter->first <<
" (" << secondIter->first <<
" : " << secondIter->second <<
" )" << std::endl;
}
}
Of course it's code like this that auto was invented for
for (auto iter = wordMap.begin();
iter != wordMap.end();
iter++)
{
for (auto secondIter = iter->second.begin();
secondIter != iter->second.end();
secondIter++)
{
std::cout << iter->first <<
" (" << secondIter->first <<
" : " << secondIter->second <<
" )" << std::endl;
}
}
Or range based for loops were invented for
for (const auto& pair : wordMap)
{
for (const auto& secondPair : pair.second)
{
std::cout << pair.first <<
" (" << secondPair.first <<
" : " << secondPair.second <<
" )" << std::endl;
}
}

Is map::find safe?

I'm trying to test if "find" is safe in std:map so I've erased an element after I use "find" to test it but the iterator to the element is still valid. Even if I use find again it finds the erased element again.
According to documentation:
Iterators, pointers and references referring to elements removed by the function are invalidated.
All other iterators, pointers and references keep their validity.
Why does the second iterator auto it_2 = numeros.find("uno"); finds the element if it was erased?
Why does std::cout << it->first << " : " << it->second << std::endl; after "erase" prints the element? It means find is safe when the element is removed from the map?
This is my example.
#include <iostream>
#include <map>
int main(int argc, char *argv[])
{
std::map<std::string,unsigned int> numeros = { {"uno",1}, {"dos",2}, {"tres",3}};
auto it = numeros.find("uno");
std::cout << it->first << " : " << it->second << std::endl;
std::cout << std::endl;
numeros.erase("uno");
std::cout << it->first << " : " << it->second << std::endl;
std::cout << std::endl;
auto it_2 = numeros.find("uno");
std::cout << it_2->first << " : " << it_2->second << std::endl;
std::cout << std::endl;
for (auto i=numeros.begin(); i!=numeros.end(); ++i)
std::cout << i->first << " : " << i->second << std::endl;
return 0;
}
Output
uno : 1
uno : 1
uno : 1
dos : 2
tres : 3
Thank you!
numeros.erase("uno"); invalidates the iterator it as per your quote. This means that you are not allowed to dereference the iterator anymore. Doing so anyway has undefined behavior.
Therefore your program has undefined behavior because you dereference the iterator in the next line
std::cout << it->first << " : " << it->second << std::endl;
Undefined behavior means your program could do anything. There are no guarantees that anything specific will happen anymore. There are no guarantees that you will get any error or warning either.
(Assuming you corrected the undefined behavior above:)
The second find in
auto it_2 = numeros.find("uno");
does not find the erased element. If .find does not find any element it returns the past-the-end iterator numeros.end(), which is what is happening here. Dereferencing the past-the-end iterator also has undefined behavior. So the following line
std::cout << it_2->first << " : " << it_2->second << std::endl;
which dereferences the past-the-end iterator also causes undefined behavior and your program to have no behavior guarantees.
You need to always check the result of find against end to verify that it found an element:
if(it_2 != numeros.end()) {
std::cout << it_2->first << " : " << it_2->second << std::endl;
} else {
std::cout << "uno not found!" << std::endl;
}

I want to printout my vector from vector list

I want to printout my vector from vector list
std::list < std::vector< unsigned int >> lista;
for (std::list< std::vector< unsigned int > >::iterator i = lista.begin(); i != lista.end(); ++i){
std::cout << std::hex << whats_here << " " << std::endl;
}
I don't know what should I place on whats_here. Any help will be appreciated.
Really simple:
for (auto &list_item : lista)
{
for (auto &item : list_item)
{
std::cout << std::hex << item << " " << std::endl;
}
std::cout << std::endl;
}
Make any required adjustment to get the desired output. Since the expected output is not given in the question, the above code is my best guess given your non working code.

Issue with output for nested std::map

std::map<int, std::map<std::string, std::pair<int, std::string>>>mfvs;
I want to output the std::string the first part of inner map.
for (const auto& iter :mfvs)
{
std::cout << iter.second.first << "\n";
}
this gives me an error
iter.second is an std::map, and as such it doesn't have first.
If you want to print the first (with lowest key) element (and you are sure it exists), then do this:
std::cout << iter.second.begin()->first << "\n";
.begin() will return you the first element of the map, and ->first will get its key. If you want to print the value of it as well, something along the lines of the following code will work
auto firstElem = iter.second.begin();
std::cout << firstElem->first << ": " << firstElem->second.first << ", " << firstElem->second.second << "\n";

unordered_map pair of values c++

I am trying to use the unordered_map in C++, such that, for the key I have an int, while for the value there is a pair of floats. But, I am not sure how to access the pair of values. I am just trying to make sense of this data structure. I know to access the elements we need an iterator of the same type as this unordered map declaration. I tried using iterator->second.first and iterator->second.second. Is this the correct way to do access elements?
typedef std::pair<float, float> Wkij;
tr1::unordered_map<int, Wkij> sWeight;
tr1::unordered_map<int, Wkij>:: iterator it;
it->second.first // access the first element of the pair
it->second.second // access the second element of the pair
Thanks for your help and time.
Yes, this is correct, but don't use tr1, write std, since unordered_map is already part of STL.
Use iterators like you said
for(auto it = sWeight.begin(); it != sWeight.end(); ++it) {
std::cout << it->first << ": "
<< it->second.first << ", "
<< it->second.second << std::endl;
}
Also in C++11 you can use range-based for loop
for(auto& e : sWeight) {
std::cout << e.first << ": "
<< e.second.first << ", "
<< e.second.second << std::endl;
}
And if you need it you can work with std::pair like this
for(auto it = sWeight.begin(); it != sWeight.end(); ++it) {
auto& p = it->second;
std::cout << it->first << ": "
<< p.first << ", "
<< p.second << std::endl;
}