Home > Software design >  C convert iterator from map to object pointer
C convert iterator from map to object pointer

Time:08-10

Trying to find an object in a map, and set a member class pointer variable.

# Animations.h
#ifndef _ANIMATIONS_H
#define _ANIMATIONS_H

#include <map>
#include "Animation.h"

using namespace std;

class Animations {
  public:
    Animations();
    void add(Animation* animation, string name);
    void play(string name);

    Animation* animation;
    map<string, Animation*> animations;
};

#endif

# Animations.cpp
...
void Animations::play(string name) {
  std::map<string, Animation*>::iterator itr = animations.find(name);

  if (itr != animations.end()) {
    animation = itr->second;
  }
}

I've seen lots of examples with itr->second in couts and printing, which I've tested, works fine. However I need to convert it to an Animation * somehow, but don't know how. When I use the variable from above, it compiles, but the data is all messed up (frame should be 0 and instead is some huge int) so probably wrong memory address. I did verify the frame of the original Animation object is 0, and a pointer to it is 0 too before adding it to the map.

The closest I've come is this &(*itr); via https://stackoverflow.com/a/2160319/1183537 and what I'm doing is close to c Find map value and key although I want to assign the variable, not just print it out, which are the examples I usually find on map#find like https://cplusplus.com/reference/map/map/find/ and https://www.guru99.com/cpp-map-stl.html

Can anyone lend some help?

I'm newish to C , and rusty on C, but programming for 10 years, so I should be able to handle this.

edit: here's how i'm adding animations:

# Animations.cpp
void Animations::add(Animation* animation, string name) {
  animations[name] = animation;

  cout << "> Animations::add " << name << " frame: " << animation->frame << endl;
}

and here's how I'm testing the set animation pointer:

# Animations.cpp
void Animations::update() {
  cout << "> Animations::update" << endl;
  if (animation != NULL) {
    cout << "> Animations::update animation frame: " << animation->frame << " " << animation->width << "x" << animation->height << endl;
    animation->update();
  }
  cout << "> Animations::update done" << endl;
}

here's where I was creating the Animations and calling animations.add:

# Player.cpp
...
void Player::initAnimations(ALLEGRO_BITMAP* sheet) {
  Animation spark(FPS, true, true);
  Animation explosion(FPS / 3, true, true);

  spark.add(sheet, 34, 0, 10, 8);
  spark.add(sheet, 45, 0, 7, 8);
  spark.add(sheet, 54, 0, 9, 8);

  animations.add(&spark, "spark");
  animations.play("spark");
}

I've tried not using pointers, from the comment suggestions. But I'm getting error error: no matching constructor for initialization of 'Animation' around the place where I do

animation = itr->second;

not sure if it needs to be itr.second instead, I think I tried both.

CodePudding user response:

I switched to non pointers in the map

# Animations.h

map<string, Animation> animations;
Animation* animation;

while leaving the animation a pointer. Then thanks to @EtiennedMartel's comment I used &itr->second to set the Animation* animation pointer. The other thing I needed to do was to add a default Animation() constructor, which I originally didn't have, which was needed from the map/iterator.

# Animations.cpp

void Animations::play(string name) {
  std::map<string, Animation>::iterator itr = animations.find(name);

  if (itr != animations.end())
    animation = &itr->second;
}
  • Related