Transform range-based for normal loop - c++

for (const auto & rRec : m_map_handshake)
{
if (rRec.second->GetHostName() == inet_ntoa(c_rSockAddr.sin_addr))
{
return true;
}
}
I have code like this, but range-based for loop won't work on old gcc compiler.
Is there any way to work aroung this? I am not an expert on C++

You can use a normal for loop. Looks like it's std::map. Use iterator to traverse the elements and match the condition.
for(const <map-type>::iterator it = m_map_handshake.begin(); it != m_map_handshake.end();++it){
if (it->second->GetHostName() == inet_ntoa(c_rSockAddr.sin_addr))
{
return true;
}
}
Here <map-type> will be the type of m_map_handshake.

Related

Turning while + if else to simpler std::remove_if

I am trying to clean up some loops, and move from while and if/else into std::remove_if and have never done this before, can anyone show me how to turn the below into a remove_if that will achieve the same results? Ideally I want to eliminate the if(obj->IsQueuedForRemoval).
Thank you in advance!
Initial:
void ObjectCollection::ProcessRemovals()
{
bool removed = false;
auto objIterator = objects.begin();
while (objIterator != objects.end())
{
auto obj = *objIterator;
if (obj->IsQueuedForRemoval())
{
objIterator = objects.erase(objIterator);
removed = true;
}
else
{
++objIterator;
}
}
if (removed)
{
drawables.ProcessRemovals();
collidables.ProcessRemovals();
}
}
The part I'm getting tripped up on is how I can keep the bool, trigger it if it removes anything and only go to drawables and collidables process removals if it was removed from there.
std::remove_if returns an iterator to end of the range of not removed elements. You can split the erase-remove into two steps:
auto it = std::remove_if(objects.begin(), objects.end(),predicate)
bool removed = (it != objects.end());
if (removed) {
objects.erase(it,objects.end());
drawables.ProcessRemovals();
collidables.ProcessRemovals();
}
Where predicate can be a lambda that checks if the object is queued for removal (assuming IsQueuedForRemoval is const):
auto predicate = [](const Object& obj){ return obj.IsQueuedForRemoval();};
I'll leave it to you to adjust the lambda in case the containers elements type is something else than Object.

Removing an object from vector while iterating through it

I'm new to C++ so I'm having trouble figuring out how to best remove an object from a vector while still iterating through it.
Basically, I need to iterate through two vectors. For every item, if the ID's match, I can remove them.
//For every person, check to see if the available bags match:
for(std::vector<Person>::iterator pit = waitingPeopleVector.begin(); pit != waitingPeopleVector.end(); ++pit) {
for(std::vector<Bag>::iterator bit = waitingBagsVector.begin(); bit != waitingBagsVector.end(); ++bit) {
int pId = pit->getId();
int bId = bit->getId();
if(pId == bId){
//a match occurs, remove the bag and person
}
}
}
Working with iterators is a bit confusing, I know I can use the .erase() function on my vectors, but I can't really pass pit or bit. Any help appreciated. Thanks
From the standard:
The iterator returned from a.erase(q) points to the element
immediately following q prior to the element being erased. If no such
element exists, a.end() is returned.
I would use it in something like using the erase method:
std::vector<Person>::iterator pit = waitingPeopleVector.begin();
std::vector<Bag>::iterator bit = waitingBagsVector.begin();
while (pit != waitingPeopleVector.end())
{
bool didit;
while (bit != waitingBagsVector.end())
{
didit = false;
if (pit->getId() == bit->getId() && !didit)
{
bit = waitingBagsVector.erase(bit);
pit = waitingPeopleVector.erase(pit);
didit = true;
}
else
{
++bit;
}
}
if (didit)
continue;
else
++pit;
}
Using the erase-remove idiom will achieve this objective, the below offers an (untested) way using lambdas and <algorithm> functions to remove elements from wPL which have the same ID as wBL. It shouldn't be too much effort to extend this to both lists. Note, we have used std::list instead of std::vector for faster removal.
std::list<Person> wPL;
std::list<Bag> wBL;
//...
wPL.erase(std::remove_if(wPL.begin(), wPL.end(),
[&wBL](auto x) { return std::find_if(wBL.begin(), wBL.end(), [](auto y)
{ return x.getId() == y.getId();); }), wPL.end() };

Check if strings in std::vector contain substring in C++

Is there an efficient way of executing a function if any string inside a vector contains a substring?
Something along these lines
if(vector.contains(strstr(currentVectorElement,"substring"))) {
//do something
}
if(vector.contains(strstr(currentVectorElement,"substring2"))) {
//do something else
}
The only thing I can think of is iterating over each string and check if the substring exists.
You can use std::find_if with a lambda expression
if(std::find_if(vec.begin(), vec.end(), [](const std::string& str) { return str.find("substring") != std::string::npos; }) != vec.end()) {
...
}
What you need is std::search()
http://en.cppreference.com/w/cpp/algorithm/search

unordered_set erase not working in C++

Consider the following situation
void first(){
unordered_set<int> validPorts;
int roundNum=0, preFunctionSize, postFunctionSize,j=0 ;
while(j <100){
if(some_condition_A){
validPorts.insert(some_int_value);
}
j++;
}
do{
preFunctionSize = validPorts.size();
second( validPorts, some_int_value );
postFunctionSize = validPorts.size();
}while(roundNum<12);
}
void second( unordered_set<int> & validPorts, int some_int_value ){
for (auto it = validPorts.begin(); it != validPorts.end();) {
if (it == validPorts.find(some_int_value)) {
validPorts.erase(it++); // <== CODE enters here, I checked
} else {
++it;
}
}
}
So I expect that the postFunctionSize should be less than the preFunctionSize since I know that it went till the erase function. But it looks like the erase function does not work since i get the same value for the two of them. I am not really sure whats happening here and what is causing it. Can you guys please help me out on what might be wrong with this?
Your code is pseudo of course in places but you need to do:
it = validPorts.erase( it );
in a loop where you are iterating through a collection erasing some of them.
However that is also not really what you want to do. You are trying to erase a value from your unordered_set so just do
validPorts.erase( some_int_value );
and no loop.

Search vectors in returned iterator

Context:
I perform a std::find with a std::string on a <-string,vector->map. It then returns me an iterator of vectors, I keep the returned iterator in a const-iterator.
Problem:
I now want to iterate through the returned const-iterator, and string compare every vector at index 0. so something like:
while (iterator != map.end())
if ( myStr == iterator.at(0) )
break;
else
iterator++
That approach works just fine for me, I was wondering if there is a more elegant way of doing this, am I missing something?
Thanks for your help with this =]
Instead of explicitly coding the search you could use std::find_if():
std::vector<std::vector<std::string>> vstring
{
{ "no", "yes" },
{ "help", "yes" },
{ "true", "false" }
};
const std::string myStr = "help";
auto f = std::find_if(vstring.begin(), vstring.end(),
[&](std::vector<std::string>const & vs)
{
return !vs.empty() && myStr == vs[0];
});
if (f != vstring.end())
{
// Found.
}
See demo at http://ideone.com/nkI7fk .
One way to make this more "elegant" would be something like this:
// C++11 allows `using` to be used instead of `typedef`
using map_type = std::map<std::string, std::vector<some_type>>;
// First find the starting point of our secondary search
const auto itr = map.find(some_string);
// Do secondary search
const auto found = std::find_if(itr, map.end(),
[](const map_type::value_type& pair)
{
return (!pair.second.empty() &&
pair.second[0] == myStr);
});
if (found != map.end())
{
// Found the item
}
There is a very poor way I can imagine. It's not ordinary and should(or even must) never be used. Overloade comparison operator for vector, so it would compare only 0 positions. And then use map::find() method. Just fun.