I have got a map defined inside a class in header file like this:
std::map<int, char> mCompletedIds;
I can do with a vector here, as I just need to store the ids which have been completed. But to have fast find, I am using map. So, I always put second argument of pair as 0.
Now, In one of the fns. of class, I am doing find.
std::map<int, char>::iterator it = mCompletedIds.find(id); //id is defined above
On this statement, I am getting SIGBUS. Is it because map is empty at the moment? Can anyone pls. help me understand the reason.
Thanks,
sg
If you just want a store of numbers you can use std::set<int>
To see if a value is present use
std::set<int> mCompletedIds;
bool found = mCompletedIds.count(id) != 0;
Your SIGBUS error will usually be caused by bad alignment or some other corruption that happened in your code, and a tool like valgrind may indicate to you where your real error is.
std::set is what you need : cppRef
int id = 0;
std::set<int> idList;
std::set<int>::iterator it = idList.find(id); //see also count function
if (it != idList.end()) { // find will return set::end if the element is not found
// id is in your list
} else {
// id isn't in your list
}
Related
Novice question, but I searched for this and couldn't find something clearly solving my issue - apologies if this is obvious.
I have defined a map which looks like this:
map<int, string> testmap = {
{ 0, "a" },
{ 1, "b" },
{ 2, "c" }
}
However, I need to retrieve a value from testmap using a uint64_t value provided by another function.
When I do testmap[my_uint64_t_value] it returns an empty string, so I think this is because it's adding my_uint64_t_value as a key and setting the value to NULL.
This is the same if I set the map type to <uint64_t, string>, at least the way I'm currently defining my keys.
However, is there a way that I either:
convert the uint64_t value to a regular int
define the map as <uint64_t, string>, and be able to define my
keys as the 'correct' type?
It seems like int type conversion isn't that common, is this something that should be avoided?
The reason why you get an empty string is std::map::operator[] returns a reference to the value if and only if it exists, otherwise it performs an insertion. I suspect you have the latter case.
You need to use std::map::find for search.
uint64_t keyToFind = 1;
if (auto iter = testmap.find(keyToFind); iter != testmap.cend())
{
// do something
std::cout << "Found!\n";
}
else { std::cout << "Not Found!\n"; }
Like #Rene mentioned in the comments, casting from uint64_t to int can cause overflow. Therefore, making the key to larger type(as per requirement) would be a good idea.
std::map<uint64_t, std::string> testmap;
As said in another answer, the [] operator of the map class will perform an insertion with a default-constructed value if the key is not present in the map.
You can first use the count method to determine if the key is present in the map before accessing it.
if(testmap.count(keyToFind))
return testmap[keyToFind];
else
report_key_not_found();
An alternative solution is to use the at method to access the value. It will throw an std::out_of_range exception if the key is not present instead of inserting a new key.
I'm using C++ and have a number of data structures that I need to update things in. I use a map from double to multi maps of int and my struct. It looks like this:
std::map<double, std::multimap<int, dnode*> *> m_ptable;
My struct definition looks like this:
struct dnode{
std::string ticker;
double buy;
double sell;
//(sell/buy)
double result;
bool hasDuplicate;
};
The issue is that I need to iterate through all of the dnodes in the multi map and update their value of "sell" and "result" because this has to be computed after all of the nodes are already in the multi map. Here is the function I wrote to do that:
void dataProcessor::addCloseToEntry(double close){
map<double, std::multimap<int, dnode*> *>::iterator it;
multimap<int, dnode*>::iterator mm_it;
for(it = m_ptable.begin(); it != m_ptable.end(); it++){
for(mm_it = (it->second)->begin(); mm_it != (it->second)->end(); mm_it++){
mm_it->second->sell = close;
mm_it->second->result = close/(mm_it->second->buy);
}
}
return;
}
When I step through this code I see that the values for "sell" and "result" are not changing, but remain as 0 (I initialize them to zero when I add a new node into the map.)
Is there something I'm doing incorrectly with the iterators here that's causing this?
Thanks!
Ok this code works fine. My logic was messed up in the lines before this. This function was called inside a while loop with a parameter that was reinitialized to zero before it was called every time.
Wow.
Thanks anyway guys!
I have a recurrent pattern with the use of std::map.
I want to retrieve the value only when the key is present, otherwise I don't want to insert element. Currently I'm using count(key) or find(key) (which one is better? from the documentation the complexity seems to be the same) and if them returns a positive value that I access the map. However I would like to avoid the use of two operations on the map. Something like:
map<string, int> myMap;
int returnvalue;
boole result = myMap.get("key1",returnValue)
if(result){
\\ use returnValue
}
Reading the std::map documentation on cplusplus.com I found two functions for accessing map elements:
at(): which throws an excpetion if the key is not present
[]: which insert a new value if the key is not present
None of them satisfy my necessity.
Use map::find:
auto it = myMap.find(key);
if (it != myMap.end())
{
// use it->second
}
else
{
// not found
}
This part was easy. The harder problem is when you want to look up if an element exists and return it if it does, but otherwise insert a new element at that key, all without searching the map twice. For that you need to use lower_bound followed by hinted insertion.
using count() for sure the key is exists
then uses find() to get the k/v pair
if (myMap.count(key))
{
auto it = myMap.find(key)
}
else
{
// not found
}
I have std::set which contains come int values. Now i use iterator to find out whether set contans value.
But my application use this search very ofter and search using iterator too slow, can i do something like that:
std::set<int> fdsockets;
void myfunc(int fd)
{
if(fdsockets[fd] != fdsockets.end())
{
// my code
}
}
But i have error when compile using G++
no match for 'operator[]' in 'fdsockets[fd]'
Maybe i can use something instead of std::set?
Thanks!
std::unorered_set or an ordered vector with binary search are more effective for simple membership test. If the maximum value of intergers is low a lookup table might be an alternative.
It sounds like you want set::find()
if( fdsockets.find(fd) != fdsockets.end() )
{
// my code
}
There is no operator[] in std::set.
You probably mean
if(fdsockets.find(fd) != fdsockets.end())
If you don't need the iterator that set::find returns (you're just testing existence, not actually going to access the fdsocket), here's an alternative:
if(fdsockets.count(fd))
{
// my code
}
I can do:
map<char*, int> counter;
++counter["apple"];
But when I do:
--counter["apple"] // when counter["apple"] ==2;
I got debugger hung up in VS 2008.
Any hints?
Do you rely on the value of it? A string literal is not required to have the same address in different uses of it (especially when used in different translation units). So you may actually create two values by this:
counter["apple"] = 1;
counter["apple"] = 1;
Also you get no kind of any sorting, since what happens is that it sorts by address. Use std::string which does not have that problem as it's aware of the content and whose operator< compares lexicographical:
map<std::string, int> counter;
counter["apple"] = 1;
assert(++counter["apple"] == 2);
A map of the form:
map <char *, int> counter;
is not a very sensible structure, because it cannot manage the char pointers it contains effectively. Change the map to:
map <string, int> counter;
and see if that cures the problem.
I found the problem.
If I change it to:
map<string,int> counter;
counter["apple"]++;
if(counter["apple"]==1)
counter.erase("apple");
else
counter["apple"]--; //this will work
In the Key/value pair, if value is a int and value ==1, I somehow could not do map[key]--, ('cause that will make the value ==0?)