Using an int array of varying sizes in an object - c++

I am pretty new to this but I am trying to create a class that declares an int array as an attribute.
DataHousing.h
class DataHousing {
private:
// ATTRIBUTES
int fileContents[count];
int count;
DataHousing.cpp
// CLASS METHOD IMPLEMENTATIONS
#include "DataHousing.h"
// CONSTRUCTORS
DataHousing::DataHousing() {
this->fileContents = NULL;
this->count = 0;
}
The array will vary in size depending on the amount of numbers that are contained in a separate file. So, one file will be read in and stored in an array using dynamic memory which may have 500 different numbers. But, another file may be read in that has 100,000 different numbers.
I have a method in the class that will count the numbers in each file and then populate the count variable.
How do I initialize the array if I do not know what the size will be?

Related

Dynamic array seems bigger than the dynamic size variable for it

I have class A, in it I have a dynamic array arr and a dynamic variable s which determines the size of the array. At the start of my main I use the constructor for class A which sets s to 2 and fills the arr with dummy objects. Now when I add objects to the array and sort it, objects seem to disappear.
The size of my array (so variable s) gets doubled when there is not enough space in the array, so no free slot available.
The way I display the array is by using a for loop with the limit i < s. So it should display all objects in the array.
Now when I add more objects and the array gets bigger, the previously "lost" objects start to appear again. So it seems like my array is bigger than the variable s, which dynamically determines the size.
How is that possible?
class A
private:
int *s = new int;
obj *arr = new obj[*s];
//triggers when trying to add an object to the array, but every place from
//arr[0] to arr[s-1] is taken by non dummy object
void A::resize {
*s *= 2;
//for loop that fills code with dummy objects
}
void A::display {
for (int i = 0; i < *s; i++) {
displayobject(i);
}
}
I had a very similar code last year in university and everything worked fine, can't find my mistake.
I would just use a vector, where i can easily use a for loop to go through the real size, but our prof wants us to use a dynamically alocated array.

c++ Declaring a 2D array as a global variable

I am struggling to figure out how to declare a 2D Array as a global variable so i can use it in all of my methods. So far it is only declared in a single method hence why it cannot be used in other methods.I have figured out how to declare a normal string array by just typing string* array = new string[1] at the start of my code before the methods (i then alter the size of this array later on based of a variable) but i am unsure how to do it with a 2D array:
void WordSearch::ReadSimplePuzzle()
int columns = 9;
int rows = 9;
string **simple2DArray = new string*[columns];
for (int i = 0; i < columns; i++)
simple2DArray[i] = new string[rows];
//code that populates the array too long to post but not relevant.
I then have a method later on where i need to access the simple2DArray but i cannot figure out how to define it at the start of the code any help would be appreciated.
If you columns and rows variables never change, you can do this:
const int columns = 9;
const int rows = 9;
string simple2DArray[columns][rows];
By statically allocating the memory, you now don't have to worry about freeing it.
Since you clarified that the size is not known until run-time, you will not be able to allocate the memory statically. A very simple solution would be:
std::vector<std::vector<std::string>> simple2DArray; // This will have size 0 at start
Then, in your initialization step, just do this:
simple2DArray.resize(rows);
for (auto& row : simple2DArray)
{
row.resize(columns);
}
There are other ways to do this, of course, such as allocating all the memory in one block of size rows*columns and then exposing it as if it were a 2-d matrix but that might be overkill for your purposes.
My suggestion is hide the array behind a functional interface.
std::string const& getElement(size_t m, size_t n);
void setElement(size_t m, size_t n, std::string const& val);
The calling functions have the abstractions of a 2D array but they don't need to know how the it is represented in code.
In the implementation, you have various options:
Use a 1D array. Map the 2D indices to the right index in the 1D array.
Use a std::vector. Still need to map the indices.
Use a 2D array. No mapping of indices needed.
Use a std::vector<std::vector<std::string>>. No mapping of indices needed.
I am struggling to figure out how to declare a 2D Array as a global
variable so i can use it in all of my methods.
As with any global var, you need to declare your pointer in global space:
string **simple2DArray;
and then you can assign to it from inside your method
simple2DArray = new string*[columns];
If you are asking this for making it easier to solve competitive programming problems, then look at the constraints given in the question. For example if the matrix can be an N*N with 1 <= N <= 1000 Then you can globally declare int arr[1000][1000];
Here's some code for a better idea.
//global declarations
int N;
int arr[1000][1000];
int functionA()
{
// some code
}
int functionB()
{
// some code
}
int main()
{
// Get the input of both N and your array arr
// Now you can use them in any where in your code
}

How to initialize a constant int to use for array size?

I have a static integer variable Game::numPlayers, which is read in as an input from user. I then have the following class defined as such:
class GridNode
{
private:
/* Members */
static const int nPlayers = Game::numPlayers;
std::vector<Unit> units[nPlayers];
//...
};
This won't compile ("in-class initializer for static data member is not a constant expression").
I obviously cant just assign the array size of Game::numPlayers, and I also tried not initializing it and letting a constructor do the work, but that didn't work either.
I don't understand what I'm doing wrong here and what else I could possibly do to get this to work as intended.
I'm just copying a value, how is that any different from static const int nPlayers = 8 which copies the value 8 into nPlayers and works?
Edit:
To clarify, I choose to have an array of vectors because I want each node to have a quick-access container of units, but one container for each user/player so as to distinguish which units belong to which player within each node (e.g. index 0 of the array = player 1, index 1 = player 2, index 2 = player 3, and so on), otherwise I would just have one vector or a vector of vectors. I thought a map might work, but I thought an array of vectors would be faster to access and push into.
Also, Game::numPlayers is read in as a user input, but only read and assigned once within one game loop, but if I close/restart/play a new game, it needs to read in the user input again and assign it once.
I don't see why you need to use an array of std::vector if the number of elements will be obtained at runtime.
Instead, create a std::vector<std::vector<Units>> and size it appropriately on construction. if you need to reset the size, have a member function resize the vector.
Example:
class GridNode
{
private:
/* Members */
std::vector<std::vector<Unit>> units;
public:
GridNode(int nPlayers=10) : units(nPlayers) {}
std::vector<Unit>& get_units(size_t player)
{ return units[player]; } // gets the units for player n
void set_num_players(int nPlayers)
{ units.resize(nPlayers); } // set the number of players
int get_num_players() const { return units.size(); }
};
int main()
{
int numPlayers;
cin >> numPlayers;
//...
GridNode myGrid(numPlayers); // creates a GridNode with
// numPlayers vectors.
//...
Unit myUnit;
myGrid.get_units(0).push_back(myUnit); // places a Unit in the
// first player
}
Also, it isn't a good idea to have extraneous variables tell you the vector's size. The vector knows its own size already by calling the vector::size() function. Carrying around unnecessary variables that supposedly gives you this information opens yourself up for bugs.
Only integral constant expressions are allowed as array sizes in array declarations in C++. A const int object initailized with something that is not an integral constant expression (your Game::numPlayers is not, since it is read from the user), does not itself qualify as integral constant expression.
The bottom line here is that regardless of how you slice it, it is not possible to sneak in a run-time value into an array declaration in C++. C++11 does support some semblance of C99-style Variable Length Arrays, but your case (a member array) is not covered by it anyway.
If the array size is a run-tuime value, use std::vector. In your case that would become std::vector of std::vectors.

Nested Struct and Array C++

Hello I am dealing with nested structs and arrays in C++, here is some background info:
struct Cells // a collection of data cells lines
cells :: [Cell] // the cells: a location and a value
nCells :: Integer // number of cells in the array
capacity :: Integer // maximum size of the array end
struct Cell
location :: int // a location of data cells lines
value :: int // the value end Cells
The code I have which won't compile (3 files, header, ADT implementation, main)
How am I declaring the nested struct in struct array wrong?
// Defines the cell.h ADT interface
struct Cell;
struct Cells;
struct Cells {
Cell cells[];
int nCells;
int capacity;
};
struct Cell {
int location;
int value;
};
//fill cells with random numbers
void initialize(Cells *rcells);
ADT Implementation
using namespace std;
#include <iostream>
#include <cstdlib>
#include "cell.h"
void initialize(Cells *rcells){
for(int i = 0 ; i < rcells->nCells; i++)
{
rcells->cells[i].location = rand() % 100;
rcells->cells[i].value = rand() % 1000;
}
}
main
using namespace std;
#include <iostream>
#include <cstdlib>
#include "cell.h"
int main(){
Cells *c;
c->cells[0].location=0;
c->cells[0].value=0;
c->cells[1].location=0;
c->cells[1].value=0;
c->nCells = 2;
c->capacity = 2;
initialize(c);
}
Your original declaration fails because in
struct Cells {
Cell cells[];
int nCells;
int capacity;
};
"cells" defined in this way is an array, which should have fixed size (unless it is the last member and you're using C99 standard). You may think it is the same as
Cell* cells
but it won't be converted to pointer type automatically in struct definition.
The C++ way to do such things is
typedef std::vector<Cell> Cells;
Your initialize function could be
void initialize(int ncell, Cells& cells) {
cells.resize(ncell);
for (Cell& cell : cells)
{
cell.location = rand() % 100;
cell.value = rand() % 1000;
}
}
Your main program should change a little bit
int main(){
Cells c;
initialize(2, c);
c[0].location=0;
c[0].value=0;
c[1].location=0;
c[1].value=0;
}
If you want cell count information, you can call
c.size()
There is no need for capacity variable because there is no upper limit on total number of cells.
By the way, this is not the nested struct people usually talk about. When one say nested struct, he often means nested struct definition. There is nothing special about an object containing other objects.
Unlike some other programming languages, when you declare an array in C or C++, it is created where you declare it. For example if you declare one as a function local variable, it will be created on the stack.
In you case Cell cells[]; declares an array that must be created within your class. Thus if you class have an array of four elements, the compiler needs to allocate to each instance 4*sizeof(Cell) bytes for the field so it can fit the array in the instance. If your array have 524 elements, it needs 524*sizeof(Cell) bytes.
You see the problem here : the compiler cannot guess what is the size of your object. Which is problematic to obtain the location of each field in an instance, especially if you declare two array without size. Note that this issue is not restricted to object fields : you cannot declare an array as a local variable in a function without giving a size either, for example. This because array have a fixed size determined upon creation. Thus wherever you create the array, you must provide its size.
When you write Cell array[] as a function argument, you are not creating an array, but only obtaining a pointer to it, so not giving its size is okay.
To solve your issue you must somehow make classes with a constant size. For example you can allocate you array dynamically with new[some_variable] and use pointer Cell *cells; in your class. A pointer has a fixed size, and you array is to be declared on the heap (don't forget to delete[] it).
Remark: instead of a size, giving an array initializer only is valid :
int x[] = {1, 2, 4}; //creates an array of three elements

pointer to string that can be used to dynamically allocate array of strings

Im writing a project and its for a car lot and im creating classes. I need to fullfill certain requirements. For accessory descriptions I need to use a pointer to a string that can be used to dynamically allocate an array of strings with the exact number of accessories. Each element will hold the name of the accessory.
If the number of accessories is 0, there is no need to allocate space, set the pointer to null.
And also pointer to a double that can eb used to dynamically allocate an array of doubles with the same number of elements as accessories. Each element will hold the cost of the associated accessory, that is, the cost in element 0 is the cost of the accessory in element 0.
If the number of accessories is zero, set the pointer to null since there is no need to allocate space.
Heres what my class is so far without those last two requirements. Im stumped.
#ifndef VEHICLE_H
#define VEHICLE_H
class Vehicle
{
public:
Vehicle();
protected:
int vin_number;
string manufacturer;
string model;
string color;
double basecost;
int accessories;
string accessory_list;
private:
};
#endif // VEHICLE_H
Please help it's an online course and ive been googling and reading for hours.
You should not dynamically allocate an array of string.
If you decide to use C++, you should be using STL and collections. Like this:
std::list<std::string> accessory_list;
If you decide to use C, a dynamically allocated string list could look like this:
//init
int accessory_count = 0;
int accessory_cap = 20;
char** accessory_list = calloc (sizeof(char*), accessorry_cap);
//add:
if (accessory_count==accessory_cap) {
accessory_cap += 20;
accessory_list = realloc (accessory_list, sizeof(char*)* accessorry_cap);
}
accessory_list[accessory_count++] = new_accessory.
If you really need a dynamic array of strings, you can do:
int accessory_arr_cap = 20;
string* accessory_arr = new string[accessory_arr_cap];
But since there is no realloc possible in this case, you will have to copy the entire array into new one if you need to enlarge it.
If the cost and name of the option are related, put them in a struct:
struct Option
{
char* Name;
double price;
}
Than what you are looking for is a collection, perhaps a std::vector<Option>. I'll leave it up to you to google the std::vector, it's a good learning exercise.
On a side note, do you have to use C++? You might find another language like C#, or Java a little easier to learn to program with.
If you can't use vectors, make your own collection. I won't post the code because I sense this is an assignment but here's how they normally work:
instantiate with a default size array of say 10.
keep a variable with this max in it
keep a variable with the current number of items in it (starts at 0, maybe call it count or something)
when you add a pointer, put it in element 'count' and increment the counter
if count = capacity then allocate a new array 2*capacity, copy all elements into it, delete the old one and assign the new array to the variable that was the old array.