First and thrid parameters are simple, you can define them based on parameters passed to process_data function.
The second one must be a pointer to function, so you need to define that type, with typedef, for example:
typedef bool (*iterator)(struct pair_t *,void *);
int map_iterate( struct map_t *map, iterator iterator_func, struct process_t *process);
or without defining a type you can
int map_iterate( struct map_t *map, bool (*iterator)(struct pair_t *,void *), struct process_t *process);
Answer from LPs on Stack OverflowFirst and thrid parameters are simple, you can define them based on parameters passed to process_data function.
The second one must be a pointer to function, so you need to define that type, with typedef, for example:
typedef bool (*iterator)(struct pair_t *,void *);
int map_iterate( struct map_t *map, iterator iterator_func, struct process_t *process);
or without defining a type you can
int map_iterate( struct map_t *map, bool (*iterator)(struct pair_t *,void *), struct process_t *process);
Since process_data returns the result of map_iterate, and the return type of process_data is int, then the return type of map_iterate must be int:
int map_iterate( ... );
The input parameter map is passed straight through to map_iterate, and map has type struct map_t *, so the first parameter to map_iterate must have type struct map_t *:
int map_iterate( struct map_t *, ... );
Like map, process is passed straight through, and has type struct process_t *, so the last parameter must have type struct process_t *:
int map_iterate( struct map_t *, ..., struct process_t * );
Here's where things get funky. The expression iter_cb doesn't call the iter_cb function; instead, it resolves to a pointer to that function, and the type of the expression is bool (*)(struct pair_t *,void *) (pointer to function taking pointers to struct pair_t and void and returning bool), so your prototype now looks like
int map_iterate( struct map_t *, bool (*)(struct pair_t *, void *), struct process_t * );
With (short) identifiers, you get
int map_iterate( struct map_t *m, bool (*f)(struct pair_t *, void *), struct process_t *p );
Note that static is a storage class specifier, not a type specifier, so it doesn't play a role in the declaration of the second parameter in the map_iterator prototype. In the declaration/definition of the iter_cb function, it only specifies that the function name iter_cb not be exported to the linker, meaning the function cannot be called by name outside of the current translation unit (i.e., the current source file).
Hello guys,
I was wondering if you guys have any resources with regards to using maps and the iterator design pattern? I am trying to follow the one from the Head First Design Pattern books where it only has the function hasNext() and Next(). On paper it seems straightforward but I am trying to pinpoint if my problem is with the understanding of what exactly is a map iterator and what exactly I am passing. With regards to my uni textbook, it does not cover maps.
To my understanding, a map is composed of a pair struct where first is the key and the other is the value. In order to go through the whole map I need the iterator for the first element and the last element and I can get those via map.begin() and map.end() and an iterator can be progressed via the ++ operator. I am trying to protect my map by encapsulating it in a class thus an iterator class is the only way for me to go through the map. Now I am confused as to what exactly I should be passing when I am iterating and how I can control access of the iterator so as not to expose my map.
c++ - How do you loop through a std::map? - Stack Overflow
Why does std::map::insert take an iterator as a parameter?
dictionary - C++ map over an iterator? - Stack Overflow
map with iterator as key? - C++ Forum
You can achieve this like following :
map<string, int>::iterator it;
for (it = table.begin(); it != table.end(); it++)
{
std::cout << it->first // string (key)
<< ':'
<< it->second // string's value
<< std::endl;
}
With C++11 ( and onwards ),
for (auto const& x : table)
{
std::cout << x.first // string (key)
<< ':'
<< x.second // string's value
<< std::endl;
}
With C++17 ( and onwards ),
for (auto const& [key, val] : table)
{
std::cout << key // string (key)
<< ':'
<< val // string's value
<< std::endl;
}
Try the following
for ( const auto &p : table )
{
std::cout << p.first << '\t' << p.second << std::endl;
}
The same can be written using an ordinary for loop
for ( auto it = table.begin(); it != table.end(); ++it )
{
std::cout << it->first << '\t' << it->second << std::endl;
}
Take into account that value_type for std::map is defined the following way
typedef pair<const Key, T> value_type
Thus in my example p is a const reference to the value_type where Key is std::string and T is int
Also it would be better if the function would be declared as
void output( const map<string, int> &table );
So I'm learning C++ atm (coming from a C# background) and am currently playing around with all sorts of collections/containers.
I was testing some code with std::maps and I read that they are already sorted by default by the key. Later though when I tried to insert new values, I saw that std::map::insert takes an iterator as a parameter. The name for this parameter in the method is _Where, indicating that I can choose where in the map I can insert a new value.
But std::maps are already ordered by default, so inserting a value at any given iterator leads to the same result. Or doesn't it?
You can get the value by dereferencing the iterator (as if it were a pointer). This returns a key/value pair type, which has a member second that has the value:
map<string, int>::iterator itr = mValue.find(inName);
int value = itr->second;
The reason an iterator is returned is because the end() iterator is returned when a match couldn't be found:
map<string, int>::iterator itr = mValue.find(inName);
if (itr == mValue.end())
{
throw "No value could be found.";
}
int value = itr->second;
Hopefully that makes some sense.
What happens if that key does not exist in the map? What would you return for find? With an iterator, you can return mValue.end(). In addition, iterators allow iteration- an int doesn't.