trouble working with map iterators in c++ - c++

I am trying to go through my map of patient IDs, find the sequential ones that match, and find the difference squared for each pair of results (for the same patient). However I am having some trouble with the "itid" iterator in the line, "for (itid = nx; itid != mymap.end(); itid++) {" and I'm not sure why. When I take out the code with "itid" it works just fine. I am a programming beginner, so any advice would be greatly appreciated!
map <int,struct testInfo> mymap;
map <int,struct testInfo>:: iterator it;
pair<map<int,struct testInfo>::iterator,bool> ret;
map <int,struct testInfo>:: iterator itid;
int arraySize = 10000;
double diffsq[arraySize];
int count = 1;
for ( it=mymap.begin() ; it != mymap.end(); it++ ) {
auto nx = next(it);
//comparing each patientID to the next patientID
if ((it->second.patientID == nx->second.patientID) && it->second.patientID != 0) {
for (itid = nx; itid != mymap.end(); itid++) {
if ((it->second.patientID == itid->second.patientID) && it->second.patientID != 0) {
diffsq[count] = pow((it->second.result - itid->second.result), 2);
count++;
} else
itid = mymap.end();
}
}
}

I think it is because the next give a constant iterator and itid is not constant... try it in same way as you have done auto nx try same for itid.
auto itid = nx inside the for loop.

Related

How to iterate over two sets at the same time? [duplicate]

This question already has answers here:
What's the best way to iterate over two or more containers simultaneously
(11 answers)
How to iterate over two containers sequentially
(3 answers)
Closed last month.
I have two sets:
std::set<int> one;
std::set<int> two;
Each set contains indices of some objects - I need to deactivate the indices only in one, and activate the indices only in two. The indices that are in both will remain as is.
If these were sorted vectors, I would do something like:
int c1 = 0; int c2 = 0;
while(true){
if(one[c1] < two[c2]){
one[c1].deactivate();
c1++;
}else if(one[c1]==two[c2]){
c1++; c2++;
}else{
two[c2].activate();
c2++;
}
if(c1 == one.size() || c2 == two.size()){
break;
}
}
while(c1<one.size()){
one[c1].deactivate();
c1++;
}
while(c2<two.size()){
two[c2].activate();
c2++;
}
Example:
one = {1,3,5,6,7,8,10}
two = {2,4,6,8,10,12}
Before running the algorithm:
Active: 1,3,5,6,7,8,20
After running the algorithm:
Active: 2,4,6,8,10,12
But as these are sets, I'm not sure how to iterate over them this way. How do I accomplish the same thing ?
How to iterate over two sets at the same time?
You can use iterators for this:
auto it1 = one.begin();
auto it2 = two.begin();
while (it1 != one.end() && it2 != two.end()) {
int i1 = *it1;
int i2 = *it2;
// Do something with indexes
it1++;
it2++;
}

Why is the cycle endless?

Hi guys!
I want to switch to UE4 and am now trying to repeat the function of finding a way by waypoints, it works well in Unity, but there were problems in C ++. the function turned out with an infinite loop, as I understand it, openList cannot become empty. my c ++ knowledge is not enough to solve the problem. I will be glad of any help!
TArray<FVector> UWaypointsPathfinding::GetPath(UWaypoint* startNode, UWaypoint* goalNode)
{
UWaypoint* beginNode = startNode;
set<UWaypoint*> openList;
vector<UWaypoint*> closedList;
openList.insert(startNode);
startNode->previous = nullptr;
startNode->distance = 0;
while (!openList.empty())
{
startNode = *openList.begin();
openList.erase(openList.begin());
float dist = startNode->distance;
closedList.push_back(startNode);
if(startNode == goalNode) break;
int l = startNode->nearest.Num();
for (int i = 0; i < l; i++)
{
UWaypoint* node = startNode->nearest[i]->FindComponentByClass<UWaypoint>();
if(find(closedList.begin(),closedList.end(),node) != closedList.end() || openList.find(node) != openList.end())
continue;
node->previous = startNode;
node->distance = dist + FVector::Dist(node->GetOwner()->GetActorLocation(), startNode->GetOwner()->GetActorLocation());
node->distance += FVector::Dist(node->GetOwner()->GetActorLocation(), goalNode->GetOwner()->GetActorLocation());
openList.insert(startNode);
}
}
// create path...
return TArray<FVector>();
}
supposedly the problem is in this piece
if(startNode == goalNode) break;
int l = startNode->nearest.Num();
for (int i = 0; i < l; i++)
{
UWaypoint* node = startNode->nearest[i]->FindComponentByClass<UWaypoint>();
if(find(closedList.begin(),closedList.end(),node) != closedList.end() || openList.find(node) != openList.end())
continue;
node->previous = startNode;
node->distance = dist + FVector::Dist(node->GetOwner()->GetActorLocation(), startNode->GetOwner()->GetActorLocation());
node->distance += FVector::Dist(node->GetOwner()->GetActorLocation(), goalNode->GetOwner()->GetActorLocation());
openList.insert(startNode);
}
The logic is strange so this is a mistype probably.
You insert startNode to openList at the beginning, then erase it in the loop and insert again. So the openList will always have a single member startNode and all cycles are identical.
Perhaps you meant openList.insert(node); instead of openList.insert(startNode); at the last line of the loop?

BAD_ACCES iterator on map c++

I'm trying to implement a function using a map in a map like that :
typedef std::map<int, float> inner_map;
typedef std::map<int, inner_map> outer_map;
I'm filling the map this way. The idea is the first map contains a int key and an other map which contains another key and a float. If the pair I obtain is known, I increment the value otherwise I fill the map.
for (int y = 2; y < imgSize.y - 2; y++){
for (int x = 2; x < imgSize.x - 2; x++) {
thisPos = x + y*imgSize.x ;
{SOME CODE}
lj = labelMap[thisPos] ;
if (condition) {
// get the 2 label
li = pro_label_mod[thisPos] ;
// look if it lj is in the map
is_lj = pi_matrix.count(lj) ;
// this lj has already been observed
if (is_lj == 1) {
is_li = pi_matrix[lj].count(li);
// this pair is known -> I increment
if (is_li==1) {
pi_matrix[lj][li] += 1.0f ;
}
else {
pi_matrix.at(lj).insert(pi_matrix[lj].end(), std::make_pair(li, 1.0f)) ;
}
}
else {
inner_map inter ; inter.insert(std::make_pair(li, 1.0f)) ;
pi_matrix.emplace(lj, inter) ;
}
}
numb_lj[lj] += 1.0f ;
}
}
And then, I would like to iterate throught the map in my code. I did that with iterators such as :
std::vector<std::pair<int,float> > max_pi(size_lj) ;
float maxValue, thisValue ; int label_max ;
for (outer_map::iterator it_lj = pi_matrix.begin(), it_lj_end = pi_matrix.end(); it_lj != it_lj_end; ++it_lj) {
maxValue = 0.0f ;
label_max = 0 ;
inner_map &innerMap = it_lj->second;
for(inner_map::iterator it_li = innerMap.begin(), it_li_end = innerMap.end(); it_li != it_li_end; ++it_li) {
thisValue = it_li->second / numb_lj[it_lj->first] ;
if (thisValue >= maxValue) {
maxValue = thisValue ;
label_max = it_li->first ;
}
}
max_pi[it_lj->first] = std::make_pair(label_max, maxValue) ;
i+=1;
}
However, i'm getting a segmentation fault at the lines of the for loop (either the first one or the second one). BUT ! Not every time. I'm calling this function at each frame and I can have 5 calls without a BAD_ACCESS and suddenly, it crashes.. Sometimes after the first call and then the 10th.
I really can't see why and how to solve it..
Thank you in advance for any clues/comments which could be helpful !
It appears that your design of a nested map is causing all sorts of unnecessary complications. More natural appears a single map with a pair<int,int> as key:
using key_type = std::pair<int,int>;
using map_type = std::map<key_type,float>;
void add_to_map(map_type&map, key_type const&key)
{
map[key] += 1.f; // also works as desired if map.count(key)==0
}
// find key and value of first element with maximum value
map_type::value_type find_max(map_type const&map)
{
auto max = map.begin();
for(auto it=max; it!=map.end(); ++it)
if(it.second > max.second)
max = it;
return *max;
}
no need to juggle with map::count or map::iterator.

identifying duplicate values in linked list C++

I want to identify which ones and how many values are duplicate in a linked list that was user's input. And this is the code I wrote for it:
int count;
int compare, compare2;
for (p = first; p != NULL; p = p->next){
compare = p->num;
for (j = first; j != NULL; j = j->next){
if (compare == j->num){
compare2 = j->num;
count++;
}
}
if (count > 1){
cout << "There are at least 2 identical values of: " << compare2 << " that repeat for: " << count << "times" << endl;
}
}
Basically the idea of it was that I take the first element in the first loop and compare it to all the elements in the second loop and count if there are cases of them being similar, and print the result after - then I take next element and so on.
However the output is all the elements and it doesn't count correctly either. I'm just lost at how to adjust it.
I tried using the same p variable in both loops as it is the same list I want to loop, but then the .exe failed as soon as I'd finished input.
I saw a few examples around where there was function for deleting duplicate values, but the comparison part run through with while loop, and I'm just wondering - what am I doing wrong on this one?!
Your O(N*N) approach :
// Pick an element
for (p = first; p != NULL && p->next !=NULL ; p = p->next)
{ // Compare it with remaining elements
for (j = p->next ; j != NULL; j = j->next)
{
if ( p->num == j->num)
{
count++;
}
if( cout > 1 )
{
std::cout << p->num << " occurs "<< count << times << '\n' ;
}
}
Its better to use a HashMap to solve this is O(N) time with N extra space
std::unordered_map<int, int> m ;
for( p = first; p != NULL ; p = p->next )
{
m[ p->num ]++;
}
for (const auto &pair : m )
{
if( pair.second > 1 )
std::cout << pair.first << ": " << pair.second << '\n';
}
Your logic is flawed since both p and j iterate over the entire list. When p == j, the values are bound to match.
Change the block
if (compare == j->num){
compare2 = j->num;
count++;
}
to
if (p != j && compare == j->num){
compare2 = j->num;
count++;
}
Also, you don't need the line
compare2 = j->num;
since compare2 will be equal to compare.
You can reduce the number of tests by changing the inner for loop a bit. Then, you won't need the p != j bit either.
for (j = p->next; j != NULL; j = j->next){
if (compare == j->num){
count++;
}
}
The problem is that you don't exclude element you compare to (compare). So for every element it found at least one duplicate - itself!
Try to compare element in inner loop only followed by current (p).

C++ character count (Project Euler 17 wrong answer) [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 11 years ago.
I am getting a wrong answer when I wrote a code to solve Prob 17 in Project Euler.
I am outputting every string to make the count more clear.
The link is posted here: http://codepad.org/wE54t7Qi
Can someone help me to determine where the problem is?
map<long int, string> CharNumberValue;
int main()
{
CharNumberValue[0] ="zero";
CharNumberValue[1] ="one";
CharNumberValue[2] ="two";
CharNumberValue[3] ="three";
CharNumberValue[4] ="four";
CharNumberValue[5] ="five";
CharNumberValue[6] ="six";
CharNumberValue[7] ="seven";
CharNumberValue[8] ="eight";
CharNumberValue[9] ="nine";
CharNumberValue[10] ="ten";
CharNumberValue[11] ="eleven";
CharNumberValue[12] ="twelve";
CharNumberValue[13] ="thirteen";
CharNumberValue[14] ="fourteen";
CharNumberValue[15] ="fifteen";
CharNumberValue[16] ="sixteen";
CharNumberValue[17] ="seventeen";
CharNumberValue[18] ="eighteen";
CharNumberValue[19] ="nineteen";
CharNumberValue[20] ="twenty";
CharNumberValue[30] ="thirty";
CharNumberValue[40] ="forty";
CharNumberValue[50] ="fifty";
CharNumberValue[60] ="sixty";
CharNumberValue[70] ="seventy";
CharNumberValue[80] ="eighty";
CharNumberValue[90] ="ninety";
CharNumberValue[100] ="hundred";//Sameer,remember 100 is one hundred
CharNumberValue[1000] ="thousand";//Sameer,remember 1000 is one thousand
long int count = 0;
string printword ="";
for(int i=1; i< 1000; i++)
{
if(i<=100)
{
int ten = (i/10)*10;
int unit = i%10;
map<long int, string>:: iterator it = CharNumberValue.find(i);
map<long int, string>:: iterator it1 = CharNumberValue.find(unit);
map<long int, string>:: iterator it2 = CharNumberValue.find(ten);
if(i<10)
{
count += it1->second.length();
printword = it1->second;
cout<<printword<<endl;
}
if(i>=10 && i<=20)
{
count += it->second.length();//These are unique
printword = it->second;
cout<<printword<<endl;
}
if(i>20 && i<=100)
{
count += it2->second.length();
printword = it2->second ;
if ((i != 30)&&(i != 40)&&(i != 50)&&(i != 60)&&(i != 70)&&(i != 80)&&(i!= 90)&&(i!= 100))
{
count += it1->second.length();
printword = it2->second + " " + it1->second ;
}
cout<<printword<<endl;
}
}
if(i>100 && i<1000)
{
int hun = i/100;
int ten=i%100;
int mten = (ten/10)*10;//modified ten
int unit = ten%10;
map<long int, string>:: iterator it = CharNumberValue.find(unit);
map<long int, string>:: iterator it1 = CharNumberValue.find(mten);
map<long int, string>:: iterator it2 = CharNumberValue.find(ten);
map<long int, string>:: iterator it3 = CharNumberValue.find(hun);
int counttemp = CharNumberValue[100].length();
count += it3->second.length() + CharNumberValue[100].length();
printword = it3->second + " " + CharNumberValue[100];
if((i != 200)&&(i != 300)&&(i != 400)&&(i != 500)&&(i != 600)&&(i != 700)&&(i != 800)&&(i != 900))
{
if( ten<=20)
{
count += 3/*for and */+ it2->second.length() ;//These are unique
printword = it3->second + " " + CharNumberValue[100] + " and " + it2->second ;
cout<<printword<<endl;
}
if(ten>20 && ten<=99)
{
count += 3/*for and */+ it1->second.length();
printword = it3->second + " " + CharNumberValue[100] + " and " + it1->second;
if ((ten != 30)&&(ten != 40)&&(ten != 50)&&(ten != 60)&&(ten != 70)&&(ten != 80)&&(ten!= 90)&&(ten!= 100))
{
count += it->second.length();
printword = it3->second + " " + CharNumberValue[100] + " and " + it1->second +" "+ it->second ;
}
cout<<printword<<endl;
}
}
else
{
cout<<printword<<endl;
}
}
}
count += 11;//for one thousand
cout<< count;
return 0;
}
You're outputting "hundred" instead of "one hundred".
You can simplify most of the tests containing enumeration of cases :
if ((i != 30)&&(i != 40)&&(i != 50)&&(i != 60)&&(i != 70)&&(i != 80)&&(i!= 90)&&(i!= 100))
As (i>20 && i<=100), you can just check if i is a multiple of 10 (using variable unit for instance)
if((i != 200)&&(i != 300)&&(i != 400)&&(i != 500)&&(i != 600)&&(i != 700)&&(i != 800)&&(i != 900))
As (i>100 && i<1000), you can just check if i is a multiple of 100
if ((ten != 30)&&(ten != 40)&&(ten != 50)&&(ten != 60)&&(ten != 70)&&(ten != 80)&&(ten!= 90)&&(ten!= 100))
As (ten>20 && ten<=99), you can just check if ten is a multiple of 10.
More generally, the shorter your code is, the easier it will be to find a mistake. This includes removing useless tests (a few of the conditions above were useless because of the bounds of the variables), removing duplicate code, etc.