Iterator and constant interator in C++ - c++

Whats the difference?
I want to be able to see if an element is in a HashMap and I just found out that if I do h[element], it will return the default element if it is not found, and not null. How would I use the iterator find method to see if the element is there?
Thanks

Assuming you're talking about STL and not some 3rd party library... m[key] doesn't just return the default object if key isn't in the map. It will create a new element in the map with that key and a default-constructed object as value.
You could use this:
map<string, int> mymap;
//add items to it
map<string, int>::iterator it = mymap.find("key");
if (it != myMap.end()) {
// 'key' exists; (it->second) is the corresponding int
}
Or if you don't need to get the object (you just want to know if it exists):
map<string, int> mymap;
//add items to it
if (mymap.count("key") == 1) {
// 'key' exists
}

You use the find method to see if something is in a std::map
std::map<std::string, std::string> myMap
std::map<std::string, std::string>::iterator it = myMap.find("foo");
if(it != myMap.end()) {
//foo is in the map
} else {
// foo isn't in the map
}
A const_iterator is an iterator that when de-referenced returns a const version of whatever it points to. In the example above, if it was a const_iterator then de-referencing it would yield a const std::string

The main difference is that const_iterator cannot be used to modify the value of an element in the map.
using find method
hash_map <int, int> hm1;
hash_map <int, int> :: const_iterator hm1_RcIter = hm1.find( 2 );
if ( hm1_RcIter == hm1.end( ) )
cout << "The hash_map hm1 doesn't have an element "
<< "with a key of 2." << endl;
else
cout << "The element of hash_map hm1 with a key of 4 is: "
<< hm1_RcIter -> second << "." << endl;

As the other answers explain, for a std::map you can use find.
To answer the question in the headline:
For iterators, const can refer to the iterator itself, or the to the contents, the iterator points to. Both properties are orthogonal. With STL notation you have the following cases:
iterator Contents and iterator can be modified.
const_iterator Contents is const, the iterator can be modified
const iterator Contents can be modified, the iterator is const.
const const_iterator Contents and iterator are constant.
It is similar for pointers. There, the const can also refer to the contents or the pointer itself.

const iterators are need when you want an iterator to iterate through a const container. Trying to assign a non-const modifiable iterator onto a const container will return a compiler error. This is because the non-const iterator could potentially modify the const container.

Related

Using std::map with std::pair as a key and list as value

So I have the following map parseTable
std::map<std::pair<Symbol, Symbol>, list<Symbol> > parseTable;
I am confused on how to access to the list value if I have my map initialized this way:
std::map<std::pair<Symbol, Symbol>, list<Symbol> > parseTable = {
{{Symbol::Input, Symbol::OpenPar}, {Symbol::Expr, Symbol::Semicolon, Symbol::InputP}},
{{Symbol::Input, Symbol::Ident}, {Symbol::Expr, Symbol::Semicolon, Symbol::InputP}},
{{Symbol::Input, Symbol::Number}, {Symbol::Expr, Symbol::Semicolon, Symbol::InputP}}
};
I want to access to each of the values of my list individually when I use the find() function of my map.
This is what I have come up with but I am not able to get a reference to that index value:
if (parseTable.find(std::pair(stack_symbol.top(), current_symbol)))
std::map::find will return an iterator to the found element, or to end if not found. That iterator will point to a std::pair<const Key, Value>, which in your case would translate to
std::pair< const std::pair<Symbol, Symbol>, list<Symbol> >
What you want is something like this
auto it = parseTable.find(std::pair(stack_symbol.top(), current_symbol));
if (it != parseTable.end()) { // A match was found
//it->first is std::pair<Symbol, Symbol>
//it->second is list<Symbol>
for (auto& symbol : it->second) {
//symbol is each individual value in the list
... do something with symbol
}
}
This is not the greatest choice for map key, it won't let the map to be used efficiently.
std::map::find() return an iterator to the place where it found searched item or std::map::end() if not found. So, in your if statement, you need to check against that:
std::map<std::pair<Symbol, Symbol>, list<Symbol> >::iterator iter =
parseTable.find(std::pair(stack_symbol.top(), current_symbol)) //or auto with C++11
if (iter != parseTable.end())
find returns an iterator, to access the object (which will be of type std::pair<std::pair<Symbol, Symbol>, list<Symbol>>, you'll need dereference operator *
Symbol currentSymbol = (*iter).first.second; //dummy example to show the use
std::list<Symbol> myList = (*iter).second'

If I find an alement in a vector pairs using std:find, how can I get the values from the vector into a string?

After using the find function to check if string check; is in a vector<pair<string, string>> by checking the pair[i].first, i would like to get the elements in pair[i].second into a separate string string holder;
how would I do this without using loops or is it inevitable and that's the only way? Can the find function return the value in addition to the true or false?
std::find returns an iterator to the found item or end() if it is not found. So you have an iterator to your pair if it's found.
Dereference the iterator returned by the std::find function. The underlying value the iterator points to is of type std::pair. To access the pair's underlying member objects called first and second via an iterator use ->first and ->second respectively:
std::vector<std::pair<std::string, std::string>> v { {"aa", "bb"}, { "cc", "dd" }};
auto mypair = std::make_pair<std::string, std::string>("cc", "dd");
auto foundit = std::find(std::begin(v), std::end(v), mypair);
std::string s1;
std::string s2;
if (foundit != std::end(v)) {
s1 = foundit->first; // first element
s2 = foundit->second; // second element
}
else {
std::cout << "v does not contain the pair." << '\n';
}

Dereference the first part of the pair object for an unordered map

I have a C++ 03 compliant compiler. I am using a pair object when inserting the element into an unordered map using the following code:
unordered_map<char, string> mymap;
pair<unordered_map<char, string>::iterator,bool> ret;
ret = mymap.insert(make_pair('A',"A string of some sort."));
if (ret.second==false)
cout << "Could not insert an element into an unordered map.\n";
else
cout << // how to print the ret.first value here
I am having trouble accessing the value pointed to by ret.first. How to print out , dereference iterator that is ret.first?
You could do something like this
cout << (ret.first)->first;
Output
A
Working demo
When you say ret.first you are accessing the iterator from the returned std::pair<std::unordered_map<char, std::string>::iterator, bool>.
Once you have the iterator, the next ->first gets at the char, which serves as the key. Similarly ->second would get at the std::string value for that key.

Unordered map containing an Iterator to a Vector - Iterator not Dereferencable C++

I have an unordered map that stores a string as its key and an iterator to a spot in a vector as its data. Each element in the vector holds a string and an int (number of times the string appears). I have coded an increaseCount(std::string, int) function that is supposed to insert the new string into the unordered map, unless it is already within the container. If this is the case, the function should find the key in the unordered map, got to the corresponding location in the vector that the iterator points to, and add one to the int parameter of the vector element. However, when executing the second case, the error "Vector iterator not dereferencable" shows up. Here is what I have coded.
void ourTrends::increaseCount(std::string s, unsigned int amount){
// check to see if key is already in
if(wordStoreTable.find(s) == wordStoreTable.end()){
// add the element into the hash table
std::vector<std::pair<std::string, int>>::iterator it;
std::pair<std::string, std::vector<std::pair<std::string, int>>::iterator> word (s, it);
wordStoreTable.insert(word);
// add element to back of vector
std::pair<std::string, int> p1 (s, amount);
sortedVector.push_back(p1);
//std::swap(sortedVector.front(), sortedVector.back());
// set the iterator of the hash pair to the end of the current vector size
it = sortedVector.end();
--it;
wordStoreTable.find(s)->second = it;
isSorted = false;
} else{
int x = wordStoreTable.find(s)->second->second;
std::pair<std::string, int> p1 (s, x + amount);
sortedVector.erase(wordStoreTable.find(s)->second);
sortedVector.push_back(p1);
//std::swap(sortedVector.begin(), sortedVector.end());
std::vector<std::pair<std::string, int>>::iterator it = sortedVector.end();
--it;
wordStoreTable.find(s)->second = it;
std::cout << wordStoreTable.find(s)->first << std::endl;
}
}
I know that this means the iterator is pointing to an empty location in memory, but I cannot figure out where it loses track of its destination.
The reason this code doesn't work, is that vector::push_back invalidates the iterators, that is, an iterator you had for a vector of size 3, might not work if you make the vector larger by adding a new element. From cppreference: If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.
You certainly could reserve enough space for the vector ahead of time, so that iterators do not invalidate, but as a general rule, you're better off with using numerical indices.

Difference between std::vector::front() and begin()

Help on vector says of front()
Returns a reference to the first element in the vector container.
Unlike member vector::begin, which returns an iterator to this same element, this > function returns a direct reference.
Help on vector says of begin()
Returns an iterator referring to the first element in the vector container.
Notice that unlike member vector::front, which returns a reference to the first element, > this function returns a random access iterator.
And this code outputs:
char arr[] = { 'A', 'B', 'C' };
vector<char> vec(arr, arr+sizeof(arr));
cout << "address of vec.front() " << (void*)&vec.front() << endl;
cout << "address of vec.begin() " << (void*)&vec.begin() << endl;
address of vec.front() 00401F90
address of vec.begin() 0030F494
I don't understand what 'direct reference' means? In the case of begin() isn't a random access iterator just a pointer?
Can someone please point out the difference?
According to Stroustrup in The C++ Programming Language, Section 16.3.3; think of front() as the first element and begin() as a pointer to the first element.
In the case of begin() isn't a random access iterator just a pointer?
No, an iterator has some pointer semantics, but it's actually a class.
And even if it was, that should answer the question. It's like asking why the address of a pointer isn't the same as the address of the object it points to.
You'd get the same value if you dereference the iterator, which will give you the first element:
&(*vec.begin())
because
*vec.begin() == vec.front()
For a vector, begin() and end() return random access iterators. They might return a plain pointer; that's okay, because it meets the requirements to be a random access iterator. In particular, you can write *begin() to get a reference to the first object in the sequence (assuming there is one). front() gives you a reference to the first object in the sequence, without going through the intermediate iterator. Like this:
vector<int> v;
v.push_back(3);
int i = *v.begin(); // i == 3
int j = v.front(); // j == 3
Assuming you have at least 1 element in the vector,
vec.front()
is the same as
*vec.begin()
To keep it clear in your mind, always try to remember the following two lines assuming that you have a vector from STL called v:
v.front() = * v.begin()
&&
v.back() = * v.end()
that means if you have a vector:
v = {1,2,3,4};
and you have an iterator called IT, and you want to access the first and the last element
you can either do:
IT = v.begin();
std::cout<<*IT<<std::endl; // output : 1
IT = v.end();
std::cout<<*IT<<std::endl; // output : 4
or you can easily do this:
std::cout<<v.front<<std::endl; // output : 1
std::cout<<v.back<<std::endl; // output : 4
both will print the same output, the difference is just between if you want to use an iterator or not.