Loop over objects with similar names - c++

I have a set of common objects in c++ named object1, object2, object3, ....
These objects are constructed from a class, that provides some functions, like Add() which "merges" two or more objects.
What I want to do is loop over the object and merge them all together. If I use
for (int i = 1 ; i <= 30 ; i++){
TString::Format("object%d",i)->Add();
}
obviously it cannot work, because I am trying to access an object using a wrong pointer to call it.
First of all, I would like to know if there is a way to loop over the objects and secondly if there is a specific name for this procedure.
EDIT I thought of using an array or a vector and access it from there, but in order to fill the array I have to give many push_back commands, which is not convenient if you have 100 objects.

This is not possible, because variable names are compile-time artifacts in C++. Apart from the debugger which gets additional information "on the side", a program cannot access a variable by its name.
If you need to associate an object with a name or an index, put the desired objects in a container. If you need access by name, use map<string,YourObjectType> or unordered_map<string,YourObjectType>. If you need access by index, use vector<YourObjectType>:
vector<YourObjectType*> objectPtrs;
objectPtrs.push_back(&object0);
objectPtrs.push_back(&object1);
objectPtrs.push_back(&object2);
...
objectPtrs.push_back(&object29);
for (int i = 1 ; i <= 30 ; i++){
TString::Format(*objectPtrs[i])->Add();
}
The example above makes a container of pointers so that the loop accesses the original objects, not their copies stored in a vector. You could eliminate the original object variables by storing them in a vector, and accessing them by index rather than by name.

If you have access to the code which creates the objects in the first place:
Build-up a key-value pair, during their creation/construction and enter them into a map.
The key is going to be "Object1", "Object2" etc. Value will be the pointer to the object allocated/created just now.
Push these pairs into a map.
When it is time to iterate over a set of objects, recreate that name ("ObjectN") and lookup in the map, to get back the pointer to the object.
[
["Object2", ptr-to-Object2]
["Object7", ptr-to-Object7]
...
]
This won't assume anything about the indices etc. You build a name-to-object association and look it up when you iterate.

Related

How to undo changes made by a function?

If I have array int a[n], and I have a function which has this array as its argument. This function takes the array, does some changes in the array, and then returns a boolean value. All I want to do is undo the changes done by the function if the returned value is false (return the array as it was). How can I achieve this?
You can do this however you want. There is no "one right way". It depends on the specifics of your situation. Here are a few possibilities:
Keep a copy of the array and revert to the copy if you need to "undo" the function.
Write a version of the function that goes in reverse and call that version if you want need to "undo" the function.
Have the function keep track of the previous values of any array entry it modifies so you can apply that tracking to revert the function.
Don't have the function actually modify the array but instead have it create a set of modifications. Only modify the array if you decide that's what you want to do.
I highly recommend option 4. You can have a "modified array" class that provides precisely the same API as the array that also includes a reference to the real array. It can have an apply member to change the real array. That way, you can just throw away the instance of the "modified array" class if you don't want to keep the changes.
Since the modified array class provides the array API, it can also modify another instance of the modified array class. This provides as many layers of nesting as you may need.
You have to backup the input array into a local array inside of the function (Before doing changes to input array). There after write the function logic. Finally check the value which is going to return by the function. If it is false then copy the backup array data in to input array.

Is there any way to give different names to the members of an array?

For example I am making a Pacman game and I am using a struct array to represent the ghosts.
But is there any way to change the ghost[0] expression to Inky ?
It seems you are looking for associative array. Associative array is an array that can be accessed with something like association. For example, if you want to access your fruits array and get the apple, you could do: fruits["apple"] and get the value, instead of wondering which index the apple was.
If this is what you are really looking for, then in C++ it is called a map. The map is the same as associative array. Take a look onto how to use it.
https://en.cppreference.com/w/cpp/container/map
You can define a reference to any item in your struct array.
Example:
Ghost &inky = ghosts[0];
Ghost &blinky = ghosts[1];
Ghost &pinky = ghosts[2];
Ghost &clyde = ghosts[3];
To respect C++ convention, I recommand that all these references are defined with a name that begin with a lower case.
You can then use all these references as normal variables using . to call member's functions or to read or assign member's variables.
Example:
inky.setBackColor(blue);
inky.remove();
clyde.size += 2;

How to store the addresses of different unordered map into another unordered map and then use them for by referencing?

I save integer values in 2 different unordered_map, say, map1 and map2. Now, I save the address of these maps into another master unordered map,say, arr_maps using some key already defined. Now, I want to access the corresponding map based on the value of the key. The value is the memory address of map1/map2. I pass these addresses to a function to access them because I don't to copy the whole map into another map, just wanna reference it. I am not able to do that. Getting no reference the map but the code is building
I have tried referencing but it doesn't work
**#header files here**
unordered_map<string, unordered_map<ui,ui>*> arr_map; //Global declaration
function test(unordered_map<ui,ui>& cmap)
{
ui deg_index;
unordered_map<ui, ui>::const_iterator get = cmap.find(0);
//"0" is present in cmap, but not able to reference the map
if(get_node_deg == curr_node_deg.end())
//do something
}
main()
{
unordered_map<ui, ui> map1,map2;
map1.emplace(0,0);
map1.emplace(1,1);
arr_map.emplace("01",&map1);
map2.emplace(0,1);
map2.emplace(1,2);
arr_map.emplace("12",&map2);
test(arr_map["01"]);//not able to reference it
// want to pass the reference of map 1 and use it, instead of copying the whole map
test(arr_map["12"]);//same here
}

Problems with updating a vector of pointers in a constructor

stackoverflow!
For my latest assignment, I came across a problem I can't really wrap my head around.
The idea behind it is really easy, you have a basic class called Dir_or_File, which represents (as the name suggests) a directory or a file. Every one of these has two variables within itself, it has a name which corresponds to its path and entries, which consists of a vector, which keeps track of all the directories or files, which are contained in my directory.
To aid in this, I have made a method called split_after_slash, which converts any string into a vector of strings, which are split after each slash, "o1/o2/o3/" becomes a vector with the entries "o1/", "o2" and "o3". This method has been tested and it works as intended. Just for clarification, as I will be using it later on.
With this in mind, the constructor is causing problems, the idea is, that I give a path (as a string) to my constructor and it will initiate a directory.
For example:
Dir_or_File dir("/home/music/song.mp3");
Should create the Dir_or_File object "dir", which consists of its name, which is "/home/music/song.mp3" and a vector named entries, which would itself contain a Dir_or_File with the name"home/music/song.mp3" and entrieswith a Dir_or_File with the name "music/song.mp3" in it and so on. At the end, you would have your last entry, named "song.mp3", which has an empty list of entries.
My idea is to solve said problem via recursion, which I tried the following way:
Dir_or_File::Dir_or_File(std::string name)
{
this->name = name;
std::vector<std::string> full_path = split_after_slash(name);
if (full_path.size() > 1)
{
std::string new_param;
for (unsigned int i = 1; i < full_path.size(); i++)
{
new_param.append(full_path[i]);
}
Dir_or_File new_entry(new_param);
entries.push_back(&new_entry);
}
}
Setting the nameis self-explainatory, splitting the string should be too. After that, I only need to know if there is more than one string remaining in the path, which means I would be in a folder, which still has a sub-folder, if there is a sub-folder, I will call the constructor with everything but the folder I'm currently in, if there is no sub-folder, I don't need to add any entries to, well entries.
But if I test my code now, I can create a Dir_or_File, which has one entry in entries, but thats it, the entry has no name, but some gibberish and an empty entries vector, what am I doing wrong here?
Is this something that is fundamentally wrong with my approach or something that can be fixed?
Yes. Yes.
The lines
Dir_or_File new_entry(new_param);
entries.push_back(&new_entry);
are the source of your problems. new_entry is a local variable in the function. Storing its address in entries is not good. When the function returns, entries will contain a list of dangling pointers.
You can fix the problem using couple of approaches.
Make entries a vector of objects instead of vector of pointers. Then, you can use
entries.push_back(new_entry);
Allocate dynamic memory using new and store the pointer in entries.
Dir_or_File* new_entry = new Dir_of_File(new_param);
entries.push_back(new_entry);
Note that, if you use the second approach, you'll have to write a bunch of booking code to manage pointers. It will be easier to user the first approach, which will also result in less buggy code.
You can store smart pointers in stead of raw pointers in entries but even that requires you to understand how to smart pointers. The first approach is still better, IMO.

Accessing the values of map from its key using pointer to map

I want to dynamically allocate an array of pointers to an unordered_map in C++. The std::unordered map has been typedef as 'dictionary'.
dict_array= ( dictionary **) calloc(input_size, sizeof(dictionary*));
Now I want to access the individual hashmaps, and for each individual hashmap (mydict), I want to access the values using some key. like below:
for (int i=0; i< input_size, i++){
dictionary *mydict= dict_array[i];
mydict[some_key]++; /*access the value against 'some_key' and increment it*/
}
But this above line to access the value against the key generates a compilation error. What would be the correct way to access it?
In your example, you haven't actually allocated any dictionary or (std::unordered_map) objects yet.
The dict_array[i] is simply a null pointer. Thus the assignment to mydict also results in a null pointer. You would need to construct a dictionary first by invoking dict_array[i] = new dictionary();.
The expression mydict[some_key]++ doesn't mean what you think it does because mydict is a dictionary * and not a dictionary. Thus you would need to actually dereference it first before having access to a valid dictionary object:
(*my_dict)[some_key]++
But again, before this would work, you need to initialize the underlying pointers.
Also, it's generally a bad idea (which often leads to undefined behavior) to mix C allocation with C++ standard objects.
Why on earth are you messing around with pointers like this?
If you really want an array of pointers, then you'll have to dereference to access the map itself:
(*my_dict)[some_key]++;
assuming you've correctly set up each pointer to point to a valid dictionary.
Or use a less insane data structure
std::vector<dictionary> dict_array(input_size);
dict_array[i][some_key]++;
use operator[]():
mydict->operator[](some_key)++;