Reputation: 21
I am trying to dynamically allocate memory for a nested struct that happens to be a pointer. I have written some made-up code below to try and illustrate my problem.
These two structs are found in two separate header files, also the code is under one namespace.
Tiles.h
struct Tiles
{
int* m_noOfSections;
int* m_noOfTilesInSecs;
char* m_TileName;
};
// functions omitted
Flooring.h
struct Flooring
{
Tiles* m_Tiles;
int m_noOfTiles;
char* m_FlooringName;
};
void read(Tiles&);
I am working on a function definition for Flooring.h where I have to dynamically allocate an array of Tiles
, the size of the array is determined earlier on in this function from user input.
I've tried using the following code but ran into issues:
Flooring.cpp
void read(Flooring&Flr)
{
Tiles* tiles;
tiles = new Tiles[Flr.m_noOfTiles];
for (int i = 0; i < Flr.m_noOfTiles; i++) {
cout << i + 1 << ": ";
read(tiles[i]);
}
}
Note: The read(tiles[i]);
[declaration: void read(Tiles&)
] function assigns values to the data members of Tiles
. I have tested the functions in the Tiles
files and they are working as intended. So I have not included the code for those. I believe the issue lies in my Flooring.cpp implementation file.
My expectation is that that the above read function would assign values to:
tiles[i].m_noOfSections
, tiles[i].m_noOfTilesinSecs
, tiles[i].m_tileName
One of the issues is that I do not have a chance to input tileName
, when running the code it skips the part where I would normally input a tileName
.
The output would be as follows:
Enter the number of sets of tiles: Enter number of sections: [user is able
to input value here, but not before when asked to enter the number of the set of tiles]
Tiles.cpp
void read(char* tileName)
{
cout << "Enter tile name: ";
read(tileName, 15, "error message") ;
}
The function definition for the read
function with three parameters can be found below. This function was pre-defined in this assignment. I have also reviewed the function and I don't see any problems with it, but I will post it regardless if it helps.
void read(char* str, int len, const char* errorMessage)
{
bool ok;
do
{
ok = true;
cin.getline(str, len+1, '\n');
if (cin.fail()) {
cin.clear();
cin.ignore(1000, '\n');
ok = false;
}
}while(!ok && cout << errorMessage);
}
I hope that is enough information, apologies if my formatting isn't adequate, or if my terminology isn't appropriate, I am still quite new to all sorts of programming. Please do let me know if I have forgotten to include some information.
Upvotes: 2
Views: 502
Reputation: 32722
I would suggest using std::vector
and std::string
, by which the storage of the elements will be managed automatically and thereby manual memory allocations can be avoided and you can concentrate on the implementations.
That means, have a good start with the followings:
#include <iostream>
#include <vector> // std::vector
#include <string> // std::string
struct Tiles
{
std::vector<int> m_noOfSections;
std::vector<int> m_noOfTilesInSecs;
std::string m_TileName;
};
struct Flooring
{
std::vector<Tiles> m_Tiles;
// int m_noOfTiles; // --> obsolete, as you can get the size by calling `m_Tiles.size()`
std::string m_FlooringName;
};
As a side note, in Flooring
(maybe also in Tiles
) it does look like, you want to map the Tiles
's name to a group of Tiles
. As per requirements have a look at other data structure like std::pair
, std::map
, std::multimap
, std::unordered_map
, std::unordered_multimap
what standard library provides for this scenario.
Upvotes: 2
Reputation: 14589
new expression doesn't assign anything, it only value-initializes, if you offer those values, or calls constructor and passes arguments to it.
tiles = new Tiles[Flr.m_noOfTiles];
creates an array of Flr.m_noOfTiles
class Tiles
with garbage non-nullptr pointers and values. Memory for underlings are not initialized. It could be done, by offering initializer list.
tiles = new Tiles[Flr.m_noOfTiles] { value1, value2, value3 };
You have to allocate memory for every pointer. And when it's not needed, deallocate it, in proper order, from most nested to less nested structure.
This might be not a trivial task depending on operations you need and cause quite a hassle in code. It's the reason why C++ have constructors and destructors. So:
Upvotes: 2