Game inventory system - c++

I am trying to build an inventory system in C++ for a game that I am working on. However, there is a bug in the inventory system when I call Inventory::AddItem(Item i), no item gets added and that slot still stays blank. Currently, I handle the inventory through std::vector<Item>, where Item is a struct containing the type, if it is stackable, the maximum number of blocks in a stack, the current number of blocks in the stack, and a couple of objects for animation. Moreover, I automatically fill the inventory in with 40 slots of air blocks, which have the ID of INVENTORY_EMTPY_SLOT_ID.
Here is the code:
typedef struct item {
int type; // this is whether the block is a foreground of background tile
int id; // use this for the id of objects
bool stackable; // true indicates that the block can be stacked
int max_num; // maximum number of blocks in a stack
int num; // the current number of blocks in the stack
Animation* use_animation; // the animation of the block or item when it is being used
Animation* other_animation; // secondary animation of item in case it is necessary
} Item;
How I initialize empty slots:
for (size_t x = 0; x < INVENTORY_MAX_SLOTS; x++) {
Item i = {0, INVENTORY_EMPTY_SLOT_ID, true, 1, 1, NULL, NULL};
this->items.push_back(i);
}
Adding items
/*********BUG HERE:******************/
void Inventory::AddItem(Item item) {
// find all indexes with the same item.id
std::vector<size_t> indexes_w_same_item;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == item.id) {
indexes_w_same_item.push_back(i);
}
}
// find the next empty slot
int next_empty_slot = -1;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == INVENTORY_EMPTY_SLOT_ID) {
next_empty_slot = i;
}
}
// go through all the indexes with the same item.id
// and see if at least one of them is empty.
// if one is empty and has sufficient capacity,
// add the item and return. if it isn't, keep moving forward
for (size_t x = 0; x < indexes_w_same_item.size(); x++) {
if (item.id == this->items[indexes_w_same_item[x]].id) {
if (this->items[indexes_w_same_item[x]].num + item.num <= this->items[indexes_w_same_item[x]].max_num) {
this->items[indexes_w_same_item[x]].num += item.num;
return;
}
}
}
// if there is an empty slot, make a new stack
if (next_empty_slot >= 0) {
this->items[next_empty_slot].id = item.id;
this->items[next_empty_slot].max_num = item.max_num;
// clamp item.num so it doesn't exceed item.max_num
if (item.max_num > item.num) {
this->items[next_empty_slot].num = item.num;
} else {
this->items[next_empty_slot].num = item.max_num;
}
}
}

I know you have found the error, but there are many issues in your code that lead to this error, and I wanted to help you understand how to write better code, so next time it will be easier for you to find it (and maybe even avoid it!).
You should divide the logic into as small pieces as possible - modularity is a key for more clear and clean code, which was helping you to understand the error much faster.
Instead of making a clear flow, you made two distinct flows on and off. The code is much clearer when you exhaust one possible flow, and only then start the other (look at the functions add_item_to_existing_stack_if_possible and add_item_to_new_stack_if_possible.
Your variables/functions/classes names must represent what they are standing for, it wasn't the case with the original code! Look at the Item struct now - it is much clearer what each member represents, without comments! (personally, I am not using comments at all)
C++ is not C with classes - things like typedef should not appear in your code, you should use operator<< to std::cout instead of printf and so on.
Make sure you add const specifiers as possible, it can help find many mistakes on compile time (and make your program run faster).
Performance related - you should pass objects as references as much as possible, it is much faster to pass an uint64 (memory location) than copy your entire Item object.
#include <vector>
#include <array>
#include <iostream>
struct Animation;
struct Item {
int type;
int id;
bool is_stackable;
int max_num_blocks_in_stack;
int curr_num_of_blocks_in_stack;
Animation* used_animation; // if it is non nullable, you should consider to use it without a pointer (possibly a reference)
Animation* secondary_animation; // nullable - can be a pointer or std::optional
};
class Inventory
{
public:
bool add_item(Item&& item);
private:
bool is_slot_empty(size_t idx) const { return items[idx].id == INVENTORY_EMPTY_SLOT_ID; }
std::vector<size_t> find_indexes_of(const Item& item) const;
size_t find_next_empty_slot() const;
bool add_item_to_existing_stack_if_possible(const Item& item);
bool add_item_to_new_stack_if_possible(Item&& item);
void print() const;
static constexpr size_t MAX_INV_SIZE = 40; // can transform into a class template!
std::array<Item, MAX_INV_SIZE> items;
static constexpr int INVENTORY_EMPTY_SLOT_ID = -1;
};
std::vector<size_t> Inventory::find_indexes_of(const Item& item) const
{
std::vector<size_t> indexes{};
for (size_t idx = 0; idx < MAX_INV_SIZE; ++idx)
{
if (items[idx].id == item.id)
{
indexes.push_back(idx);
}
}
return indexes;
}
size_t Inventory::find_next_empty_slot() const
{
for (size_t idx = 0; idx < MAX_INV_SIZE; ++idx)
{
if (is_slot_empty(idx))
{
return idx;
}
}
return MAX_INV_SIZE; // invalid value!
}
void Inventory::print() const
{
for (size_t i = 0; i < MAX_INV_SIZE; ++i)
{
if (this->items[i].id != INVENTORY_EMPTY_SLOT_ID)
{
std::cout << "Inventory slot: " << i << "\n"
<< "Item ID: " << items[i].id << "\n"
<< "Item Num: " << items[i].curr_num_of_blocks_in_stack << "\n"
<< "Item Max Num: " << items[i].max_num_blocks_in_stack << std::endl;
//<< "Item Texture: " << textures[items[i].id] << std::endl;
}
}
}
bool Inventory::add_item_to_existing_stack_if_possible(const Item& item)
{
auto indexes_with_same_item = find_indexes_of(item);
for (auto idx : indexes_with_same_item)
{
if (item.id == items[idx].id)
{
if (items[idx].curr_num_of_blocks_in_stack + item.curr_num_of_blocks_in_stack <=
items[idx].max_num_blocks_in_stack)
{
items[idx].curr_num_of_blocks_in_stack += item.curr_num_of_blocks_in_stack;
return true;
}
}
}
return false;
}
bool Inventory::add_item_to_new_stack_if_possible(Item&& item)
{
size_t next_empty_slot = find_next_empty_slot();
if (next_empty_slot >= 0)
{
this->items[next_empty_slot] = std::move(item);
return true;
}
return false;
}
bool Inventory::add_item(Item&& item)
{
bool was_possible_to_add_to_existing_stack = add_item_to_existing_stack_if_possible(item);
if (!was_possible_to_add_to_existing_stack)
{
return add_item_to_new_stack_if_possible(std::move(item));
}
return false;
}

Okay, I figured it out. There must be a break at the end of the second for loop, where it looks for the next empty slot, otherwise, it will detect the next empty slot as the last slot in the inventory, assuming that you are adding the first item in the inventory. Therefore, that item did not show up in the hopbar.
Here is the correct solution:
void Inventory::AddItem(Item item) {
// find all indexes with the same item.id
std::vector<size_t> indexes_w_same_item;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == item.id) {
indexes_w_same_item.push_back(i);
}
}
// find the next empty slot
int next_empty_slot = -1;
for (size_t i = 0; i < this->items.size(); i++) {
if (this->items[i].id == INVENTORY_EMPTY_SLOT_ID) {
next_empty_slot = i;
break;
}
}
// go through all the indexes with the same item.id
// and see if at least one of them is empty.
// if one is empty and has sufficient capacity,
// add the item and return. if it isn't, keep moving forward
for (size_t x = 0; x < indexes_w_same_item.size(); x++) {
if (item.id == this->items[indexes_w_same_item[x]].id) {
if (this->items[indexes_w_same_item[x]].num + item.num <= this->items[indexes_w_same_item[x]].max_num) {
this->items[indexes_w_same_item[x]].num += item.num;
return;
}
}
}
// if there is an empty slot, make a new stack
if (next_empty_slot >= 0) {
this->items[next_empty_slot] = item;
}
for (size_t i = 0; i < INVENTORY_MAX_SLOTS; i++) {
if (this->items[i].id != '.') {
printf("\nInventory slot: %d\n", i);
printf("Item ID: %c\n", this->items[i].id);
printf("Item Num: %d\n", this->items[i].num);
printf("Item Max Num: %d\n", this->items[i].max_num);
printf("Item Texture: %x\n", this->textures[this->items[i].id]);
}
}
return;
}

Related

Priority Queue using heap, values with same key don't follow FIFO (first in first out)

So I'm trying to create this priority queue to handle my "Order" objects, I'm running into a problem where an object containing the same key/priority will be placed at an early earlier position than others initialized first. I have provided the expected and received output alongside the 83 lines of code of how I constructed my heap with notes
#include <iostream>
#include <vector>
struct Order {
int value = -1;
int priority = -1;
bool operator <(Order const& RHS) { return priority < RHS.priority; }
};
class heap {
private:
std::vector<Order> orders{ Order{} };
int size{}; //initalizes it at 0
int p(int index) { return index >> 1; }
int l(int index) { return index << 1; }
int r(int index) { return (index << 1) + 1; }
public:
bool isEmpty() const { return size == 0; }
void shiftUp(int position);
void shiftDown(int position);
void add(Order new_entry);
Order removeTop();
Order& getTop() { return orders[1]; }
};
template <typename T>
void mySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
heap h;
h.add(Order{1,3}); h.add(Order{2,2});
h.add(Order{3,3}); h.add(Order{5,1});
h.add(Order{6,2}); h.add(Order{7,2});
h.add(Order{8,3}); h.add(Order{9,1});
h.add(Order{23,3});
std::cout << "value" << " key(priority)" << "\n";
for (int i = 0; i < 8; i++) {
Order temp = h.removeTop();
std::cout << temp.value << "\t " << temp.priority << "\n";
}
}
void heap::shiftUp(int position) {
if (position > size) return;
if (position == 1) return;
if (orders[p(position)] < orders[position]) {
mySwap(orders[position], orders[p(position)]);
shiftUp(p(position));
}
}
void heap::shiftDown(int position) {
if (position > size) return;
int greaterPosition = position;
if (l(position) <= size && orders[position] < orders[l(position)])
greaterPosition = l(position);
if (r(position) <= size && orders[greaterPosition] < orders[r(position)])
greaterPosition = r(position);
if (greaterPosition != position) {
mySwap(orders[position], orders[greaterPosition]);
shiftDown(greaterPosition);
}
}
void heap::add(Order new_entry) {
if (size + 1 >= orders.size()) orders.push_back(Order{});
orders[++size] = new_entry;
shiftUp(size);
}
Order heap::removeTop() {
Order temp = orders[1];
mySwap(orders[1],orders[orders.size() - 1]); size--;
orders.pop_back();
shiftDown(1);
return temp;
}
/*
Expected Output
Value key(priority)
1 3
3 3
8 3
23 3
2 2
6 2
7 2
5 1
9 1
Recieved/wrong Output
value key(priority)
1 3
23 3
3 3
8 3
2 2
6 2
7 2
5 1
*/
Fixed code from answered information above
#include <iostream>
#include <vector>
struct Order {
int value = -1;
int priority = -1;
int FIFO;
bool operator <(Order const& RHS) {
if (priority == RHS.priority)
return FIFO > RHS.FIFO;
else
return priority < RHS.priority;
} //compares keys for larger presidence
};
class heap {
private:
std::vector<Order> orders{ Order{} };
int size{}; //initalizes it at 0
int p(int index) { return index >> 1; }
int l(int index) { return index << 1; }
int r(int index) { return (index << 1) + 1; }
public:
bool isEmpty() const { return size == 0; }
void shiftUp(int position);
void shiftDown(int position);
void add(Order new_entry);
Order removeTop();
Order& getTop() { return orders[1]; }
};
template <typename T>
void mySwap(T& a, T& b) {
T temp = a;
a = b;
b = temp;
}
int main() {
heap h;
h.add(Order{1,3}); h.add(Order{2,2});
h.add(Order{3,3}); h.add(Order{5,1});
h.add(Order{6,2}); h.add(Order{7,2});
h.add(Order{8,3}); h.add(Order{9,1});
h.add(Order{23,3});
std::cout << "value" << " key(priority)" << "\n";
for (int i = 0; i < 8; i++) {
Order temp = h.removeTop();
std::cout << temp.value << "\t " << temp.priority << "\n";
}
}
void heap::shiftUp(int position) {
if (position > size) return;
if (position == 1) return;
if (orders[p(position)] < orders[position]) {
mySwap(orders[position], orders[p(position)]);
shiftUp(p(position));
}
}
void heap::shiftDown(int position) {
if (position > size) return;
int greaterPosition = position;
if (l(position) <= size && orders[position] < orders[l(position)])
greaterPosition = l(position);
if (r(position) <= size && orders[greaterPosition] < orders[r(position)])
greaterPosition = r(position);
if (greaterPosition != position) {
mySwap(orders[position], orders[greaterPosition]);
shiftDown(greaterPosition);
}
}
void heap::add(Order new_entry) {
if (size + 1 >= orders.size()) orders.push_back(Order{});
new_entry.FIFO = size + 1;
orders[++size] = new_entry;
shiftUp(size);
}
Order heap::removeTop() {
Order temp = orders[1];
mySwap(orders[1],orders[orders.size() - 1]); size--;
orders.pop_back();
shiftDown(1);
return temp;
}
In general, heap does not have FIFO property until you implement something that helps doing so. In your order class, you are only comparing using the priority value. In your Order class, you are comparing two Orders by only their priority value. You need a additional variable that serves as the purpose for recording the timing when that value was inserted, and compare according to that.
If you are using the variable value for that purpose, you need to specify in your overloaded < method, what do you want to do when two Order's priority values are equal. Currently, you are only using the priority variable to compare. You are not specifying what do you want to do when the priority of two Orders are equal. You have to specify what do you want to do when the priority value of two variables are equal. Maybe compare a timing variable.

Class Dynamic Array Bug

I am required to implement a dynamic array that adjusts, dynamically, in accordance with the number of value (temperatures) that are input into the code. I have written the majority of the code for this to be possible, however I have run into a bug and for the life of me, have been unable to locate the issue.
The program is supposed to output the values of temp_a, make temp_b = temp_a, output the value of temp_b, and then clear the value of temp_a, and finally output the values of temp_b once more.
However, when I compile the program, it outputs that the list is full and cannot add any more values, meaning there is a logic error somewhere in the code.
Please forgive me for the lengthy code, as soon as I can locate the error, the code shall be separated into multiple compilations.
#include <iostream>
using namespace std;
class TemperatureList {
private:
int* temp; // pointer to dynamic array
short current_size; // current number of elements
short max_size; // max number of elements allowed in this list
public:
// Overloading assignment operator
void operator =(const TemperatureList& another_list);
// === Constructors ===
// Default constructor
TemperatureList();
// Constructor that accepts an integer parameter that specifies the max length of the list
TemperatureList(int max);
// Copy constructor that accepts another List as parameter
TemperatureList(const TemperatureList& another_list);
// Destructor
~TemperatureList();
// === Modifier functions ===
// add new_value to end of list if there is still space
void add_temperature(int new_value);
// === Accessor functions ===
// return current current_size of the list
short get_current_size();
// === Other functions ===
// return the last element, or 0 if the list is empty, with a warning output
int get_last();
// return element at the position-th position, or 0 if the list is empty, with a warning output
int get_temp(short position);
// returns if current_size == 0
bool set_temp(short position, int value);
// returns if current_size == 0
bool empty();
// returns if current_size == max_size
bool full();
// Output list separated by commas
friend ostream& operator <<(ostream& outs, const TemperatureList& list);
};
int main() {
TemperatureList temp_a;
temp_a.add_temperature(23.5);
temp_a.add_temperature(24.6);
cout << temp_a;
TemperatureList temp_b = temp_a;
cout << temp_b;
temp_a = TemperatureList();
cout << "Now there's no temperatures in a.\n";
cout << temp_a;
cout << "How about temperatures in b?\n";
cout << temp_b;
return 0;
}
void TemperatureList::operator =(const TemperatureList& another_list) {
delete[] temp;
current_size = another_list.current_size;
max_size = another_list.max_size;
if (current_size > 0) {
temp = new int[max_size];
for (int i = 0; i < max_size; i++) {
temp[i] = another_list.temp[i];
}
}
else {
temp = NULL;
}
}
TemperatureList::TemperatureList() {
current_size = 0;
max_size = 0;
temp = NULL;
}
TemperatureList::TemperatureList(int max) : max_size(max) {
current_size = 0;
temp = new int[max];
}
TemperatureList::TemperatureList(const TemperatureList& another_list) {
current_size = another_list.current_size;
max_size = another_list.max_size;
if (current_size > 0) {
temp = new int[max_size];
for (int i = 0; i < max_size; i++) {
temp[i] = another_list.temp[i];
}
}
else {
temp = NULL;
}
}
TemperatureList::~TemperatureList() {
//cout << "== I am in destructor ==\n";
delete[] temp;
}
void TemperatureList::add_temperature(int new_value) {
if (current_size < max_size) {
temp[current_size] = new_value;
current_size++;
}
else {
cout << "Cannot add value to the list. It is full.\n";
}
}
int TemperatureList::get_last() {
if (empty()) {
cout << "The list is empty\n";
return 0;
}
else {
return temp[current_size - 1];
}
}
int TemperatureList::get_temp(short position) {
if (current_size >= position) {
return temp[position - 1];
}
else {
cout << "There is no temperature\n";
return 0;
}
}
bool TemperatureList::set_temp(short position, int value) {
if (current_size >= position) {
temp[position - 1] = value;
return true;
}
else {
return false;
}
}
short TemperatureList::get_current_size() {
return current_size;
}
bool TemperatureList::empty() {
return (current_size == 0);
}
bool TemperatureList::full() {
return (current_size == max_size);
}
ostream& operator <<(ostream& outs, const TemperatureList& list) {
int i;
for (i = 0; i < (list.current_size - 1); i++) {
outs << list.temp[i] << ",";
}
outs << list.temp[i];
return outs;
}
The logic error seems to stem from the fact that you initialize your current_size and max_size to zero. So, unless your run the overloaded constructor (wherein you’re set the max_size), every call to addTemperature() is going to fail the (current_size < max_size) check because they are both equal to zero.

How to define a function that returns a type class? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
So I'm making a program for class and I have a header file called "Item" and I have a class inside my main file called "Room" and I'm trying to make a method that returns type Item and Cygwin is giving me pages and pages of errors!
Here's my code so far:
Item Header File:
class Item
{
std::string description;
public: Item (std::string newDescription)
{
description = newDescription;
}
public: std::string getDescription()
{
return description;
}
};
Here's the main Class:
#include <iostream>
#include <string>
#include "Item.h"
class Room
{
std::string description;
int exits[2][4];
std::string items[10];
Room(std::string description)
{
this -> description = description;
}
void setExit (int direction, int neighbor) //Direction - 1=N, 2=E, 3=S, 4-W
{
for (int i = 0; i < 4; i++)
{
if (exits[0][i] == NULL)
{
exits[0][i] = neighbor;
exits[1][i] = direction;
break;
}
}
}
std::string getShortDescription()
{
return description;
}
std::string getLongDescription()
{
return "You are " + description + ".\n" + getExitString();
}
std::string getExitString()
{
std::string returnString = "Exits:";
for (int i = 0; i < 4; i++)
{
if (exits[1][i] != NULL)
{
std::string tempDirection;
switch(exits[1][i])
{
case 1: tempDirection = "North";
break;
case 2: tempDirection = "East";
break;
case 3: tempDirection = "South";
break;
case 4: tempDirection = "West";
break;
}
returnString += " " + tempDirection;
}
else
{
break;
}
}
returnString += "\nItems in the room:\n";
//returnString += getRoomItems();
return returnString;
}
/*Item getItem(std::string itemName)
{
int size = 0;
for (int i = 0; i < 10; i++)
{
if (items[i] == NULL)
{
break;
}
else
{
size++;
}
}
for (int i = 0; i < size; i++)
{
if (items[i] == itemName)
{
return items[i];
}
}
}*/
int getExit(int direction)
{
for (int i = 0; i < 4; i++)
{
if (exits[1][i] == direction)
{
return exits[0][i];
}
}
}
};
using namespace std;
int main()
{
}
Putting the error on here will take forever so I'm going to skip it sorry!
Any help would be super helpful!
There are several problems with your proposed implementation of this method:
Item getItem(std::string itemName)
{
int size = 0;
for (int i = 0; i < 10; i++)
{
// items[i] is of type std::string, which is a value type, not a pointer. It
// makes no sense to compare it to null, because it can't even be null.
if (items[i] == NULL)
{
break;
}
else
{
size++;
}
}
for (int i = 0; i < size; i++)
{
if (items[i] == itemName)
{
// Here you return an std::string, not an Item -- however, Item contains
// a one-argument constructor accepting std::string and is not marked
// "explicit", so this line is equivalent to "return Item(items[i]);".
// This may or may not be what you intended, but would not cause a
// compile-time error.
return items[i];
}
}
// You do not return anything if program flow makes it to this point. This
// causes an undefined value to be returned, and you don't want that. You need
// to return something here -- but it can't be null, because Item is a value
// type!
}
Consider instead using std::vector<std::string> as the type of items. A vector is a variable-length container that can grow automatically. (Think Java's List<>.) Or, perhaps you want to map item names to Item instances, in which case you might use std::map<std::string, Item>.

using vector::erase causes a malloc(): memory corruption (fast) c++

I have a Group class which has a vector v_group;
and ofc something to get the size of the vector and to remove a item:
Group class
void Group::drawGroup()
{
for(int i = 0; i < v_group.size(); i++)
{
v_group.at(i).draw();
}
}
void Group::add(Mesh object)
{
v_group.push_back(object);
}
Mesh &Group::get(int location)
{
return v_group.at(location);
}
void Group::clear()
{
v_group.clear();
}
void Group::remove(int location)
{
v_group.erase(v_group.begin()+(location));
}
bool Group::remove(Mesh object)
{
return true;
}
int Group::size()
{
return v_group.size();
}
In my other class I'm creating a Group object:
in header: `Group *m_group;`
Renderer::Renderer() : m_group(new Group())
{
}
void Renderer::drawGL()
{
m_group->drawGroup();
}
void Renderer::addObject(float width,float height,string texture_url)
{
UseableObject uobj(width,height,texture_url);
m_group->add(uobj);
}
void Renderer::RemoveObject(int index)
{
m_group->remove(index);
}
void Renderer::move(int objectIndex, float x, float y)
{
m_group->get(objectIndex).setPosX(x);
m_group->get(objectIndex).setPosY(y);
}
Group& Renderer::GetGroup()
{
return *m_group;
}
Somewhere else I'll want to erase a object from the initial Group vector using:
DropObject::DropObject(Renderer *renderer)
{
this->renderer = renderer;
//insert a i (count) into the vector to represent the already Available objects, and continue from there with the DropObjects
for(int i = 0;i < renderer->getGroupSize();i++)
{
yIndex.push_back(10); //Vector
xIndex.push_back(10); //Vector
}
}
DropObject::~DropObject()
{
}
void DropObject::Create(int &ENEMY_movePosition, const int &ENEMY_start_height)
{
renderer->addObject(20,20,"");
xIndex.push_back(ENEMY_movePosition);
yIndex.push_back(ENEMY_start_height);//just add index, nothing else cam into my mind right now ._.
cout << ENEMY_start_height << endl;
for(int i = 0; i < yIndex.size();i++)
{
cout << "y vec= " << yIndex[i] << endl;
}
}
void DropObject::Move(int index)
{
//current index set to isRemoved = false , because it's still there
isRemoved = false;
//x remains the same, y decrease by 1 (-> =-1)
try
{
yIndex[index] -= 2;
renderer->move(index,xIndex[index],yIndex[index]);
if(yIndex[index] < -250)
{
//renderer->RemoveObject(index);
renderer->GetGroup().remove(index);
yIndex.erase(yIndex.begin() + index);
xIndex.erase(yIndex.begin() + index);
isRemoved = true;
}
}catch(std::out_of_range ex)
{
cout << "DropObject move out of range:" << ex.what() << endl;
}
}
which works, but after xIndex.erase(yIndex.begin() + index); the programm crashes with a segmentation fault
or when I'm trying to call the vector from Group again. I get a malloc(): memory corruption (fast) error.
Maybe after erasing a element, the memory is still allocated for it, and therefore i'g such errors?
anyone can help?
yIndex.erase(yIndex.begin() + index);
xIndex.erase(yIndex.begin() + index);
at xIndex.erase() I used yIndex and not xIndex.
Terrible mistake.

Array of objects with vector as class member

I have an array of objects that have a vector as a class member (actually it is a struct). The struct is:
struct Cell {
vector<int> borderNodes;
vector<int> helperNodes;
int minNodePointer;
int maxNodePointer;
Cell() {
minNodePointer = -1;
maxNodePointer = -1;
}
Cell(int _minNodePointer, int _maxNodePointer) {
minNodePointer = _minNodePointer;
maxNodePointer = _maxNodePointer;
}
vector<int>& getHelperNodes() {
return helperNodes;
}
vector<int>& getBorderNodes() {
return borderNodes;
}
void setHelperNodesArray() {
sort(helperNodes.begin(), helperNodes.end());
}
void setBorderNodesArray() {
sort(borderNodes.begin(), borderNodes.end());
}
};
I have built an array of those objects as a global variable with :
Cell* cells = new Cell[maxNumberOfCells];
and I want to add some integers to the vectors inside the objects.
I tried this (inside a function):
cells[cellId].borderNodes.push_back(node_id);
or
cells[cellId].getBorderNodes().push_back(node_id);
and they compile fine, but nothing is added to the vector. How is the correct way to do this? Here is the function that reads from a db, and adds the integers. The query and reading from db is correct, so no mistakes there.
void loadBorderNodesPerCellBnOnly(bool shouldRearrangeNodes, int subtractor, int maxNumberOfCells, int** cellBorderNodes) {
cellBorderNodes = new int*[maxNumberOfCells];
try {
work W(Conn);
for (int rownum = 0; rownum < r.size(); ++rownum) {
const result::tuple row = r[rownum];
vector<string> s = split(row[1].as<string > (), ' ');
const int mySize = s.size();
int cellId = row[0].as<int> ();
cellBorderNodes[cellId] = new int[mySize];
for (int k = 0; k < mySize; k++) {
int node_id = atoi(s[k].c_str());
cellBorderNodes[cellId][k] = node_id;
(cells[cellId].getBorderNodes()).push_back(node_id);
try {
nodes[node_id - subtractor].cellId = cellId;
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
nodes[node_id - subtractor].isBorderNode = true;
}
s.clear();
}
} catch (const std::exception &e) {
std::cerr << e.what() << std::endl;
}
for (int k = 0; k < maxNumberOfCells; k++) {
cout << k << ": " << cells[k].borderNodes.size() << endl;
cells[k].setBorderNodesArray();
if (maxBorderNodesPerCell < cells[k].borderNodes.size()) {
maxBorderNodesPerCell = cells[k].borderNodes.size();
}
}
}
void loadBorderNodesPerCellBnOnly([...], int** cellBorderNodes) {
cellBorderNodes = new int*[maxNumberOfCells];
The function above takes an int** by value. The copy is called cellBorderNodes inside the function. In the next line you change the value of the copy and continue updating that. None of those changes will be visible outside of the function. (And you will leak the acquired memory)
If you want to pass an int** and modify it inside the function, consider passing it by reference as in int**&. But you might be better off using higher level constructs (pass a vector<vector<int>>&, create a type that represents the data and pass it by value...)