creating multiple objects for classes/structures? - c++

I have a question. Is it possible to create multiple objects during run time for classes or structures?
#include<iostream>
#include<conio.h>
using namespace std;
struct node
{
int no;
};
int main()
{
int i;
for(i=0;i<4;i++)
{
struct node s[i];
}
cout<<"Enter the values";
for(i=0;i<4;i++)
{
cin>>s[i].no;
}
cout<<"The values are:";
for(i=0;i<4;i++)
{
cout<<s[i].no<<endl;
}
getch();
return 0;
}
I tried the method above , but didn't succeed . Any help would be appreciated

replace
for(i=0;i<4;i++)
{
struct node s[i];
}
with
struct node s[4];
the way you wrote your program will not work. You defined the node array s inside a block so it will not be visible outside of that block.
If you want to dynamically allocate the memory you have to do something like:
struct node *s = new node[YourDesiredSize];
or if you like the c style (not recommended):
struct node *s;
s = (node*)malloc(YourDesiredSize * sizeof (node));
and don't forget to free the memory.

for(i=0;i<4;i++)
{
struct node s[i];
}
Here you create an array of nodes inside a for loop. This is local and only available in the for loop. In addition this will not compile as it is written because i is not a constant expression. Even however if you used the new operator to allocate the array as before it would only be available in the for loop.
Instead you should declare your array somewhere else :
node s[4];
This will create an array of size 4 by calling the default c'tor of node. Then your code should work.

If you want to create instances of structs or classes at runtime you need to use the new operator.
struct node* n = new n[4]; // creates an array of 4 node structs
for( int i=0; i<4; ++i )
{
n[i]->no = i;
}
Since this is dynamically allocated memory you are responsible for freeing it when the structs are no longer needed.
delete[] n; // free dynamically allocated memory - the brackets are needed because this an array

That can be done with a native array of instances (of structures or classes) if you know the count of them, or you can used collections such as list or vector if you don't.
#include<iostream>
#include<list>
using namespace std;
struct node
{
int no;
node() { }
node(int i) { no = i; }
};
int main()
{
struct node * arrayOf4Nodes = new node[4];
cout << "Enter four values: ";
int i;
for(i = 0; i < 4; i ++) {
cin >> arrayOf4Nodes[i].no;
}
cout << "The values are:" << endl;
for(i = 0; i < 4; i ++) {
cout << arrayOf4Nodes[i].no << endl;
}
delete [] arrayOf4Nodes;
// OR for unknown lengths
cout << "Enter values ending with -1000 to exit: ";
list<node> listOfNodes;
while (true) {
cin >> i;
if (cin.eof() || i == -1000)
break;
listOfNodes.push_back(node(i));
}
cout << "The values are:" << endl;
for (node n : listOfNodes) {
cout << n.no << endl;
}
return 0;
}

Related

C++: what if we don't allocate an object with new, but the class itself contains a new in constructor?

Hope my question isn't confusing. I'll explain that with code.
I'm learning constructor/desctructor and new/delete in C++. While comparing two piece of code, I'm thinking about where the object and it's members are allocated.
I got a little bit confused when I see the new in constructor and main, and delete in destructor and main:
In the first example, I think local object c is allocated in stack. And that means, members list pointer, two int values (size and capacity) are all in stack. The object also contains an array in size 10, however the array itself is allocated in heap since new is used. When the program ends, the local object c (including the pointer) will be freed automatically. And the array pointed by pointer list will be freed as well, by destructor. Is that correct?
#include <iostream>
#include <string>
using namespace std;
class Collector {
int * list;
int size;
int capacity;
public:
// Default constructor
Collector(){
// We must define the default values for the data members
list = nullptr;
size = 0;
capacity = 0;
}
// Parameterized constructor
Collector(int cap){
// The arguments are used as values
capacity = cap;
size = 0;
list = new int[capacity];
}
bool append(int v){
if (size < capacity) {
list [ size++ ] = v;
return true;
}
return false;
}
// A simple print function
void dump(){
for(int i = 0 ; i < size ; i++) {
cout << list[i] << " ";
}
cout << endl;
}
~Collector(){
cout << "Deleting the object " << endl;
if (size > 0)
delete[] list;
}
};
int main(){
Collector c(10);
for (int i = 0 ; i < 15 ; i++){
cout << c.append(i) << endl;
}
}
Now compared with the second example, object is created with new. So all members including pointer and two int values are all allocated from heap. The array itself is also in heap for the same reason as the first example. Before the program ends, there is a delete so the pointer and two int values are all freed. The array is also freed since the desctructor is called when delete command is issued. Is my understanding correct?
#include <iostream>
#include <string>
using namespace std;
class Collector {
int * list;
int size;
int capacity;
public:
// Default constructor
Collector(){
// We must define the default values for the data members
list = nullptr;
size = 0;
capacity = 0;
}
// Parameterized constructor
Collector(int cap){
// The arguments are used as values
capacity = cap;
size = 0;
list = new int[capacity];
}
bool append(int v){
if (size < capacity) {
list [ size++ ] = v;
return true;
}
return false;
}
// A simple print function
void dump(){
for(int i = 0 ; i < size ; i++) {
cout << list[i] << " ";
}
cout << endl;
}
~Collector(){
cout << "Deleting the object " << endl;
if (size > 0)
delete[] list;
}
};
int main(){
Collector *c;
c = new Collector(10);
for (int i = 0 ; i < 15 ; i++){
cout << c->append(i) << endl;
}
delete c;
cout << "Exiting program" << endl;
}

C++ Dynamic data – how to obtain it and how to get rid of it

The code below – it's a skeleton of a program operating on the dynamic collection of data. The idea is to use a structure containing two fields: the first stores the number of elements in collections, and the second is the actual collection (a dynamically allocated vector of ints). As you can see, the collection is filled with the required amount of pseudo-random data.
Unfortunately, the program requires completion, as the most important function.
Here's what i expect from the function:
if the collection is empty, it should allocate a one-element vector and store a new value in it.
if the collection is not empty, it should allocate a new vector with a length greater by one than the current vector, then copy all elements from the old vector to the new one, append a new value to the new vector and finally free up the old vector.
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
struct Collection {
int elno;
int *elements;
};
void AddToCollection(Collection &col, int element) {
//the first part of the funtion
if (col.elno==0){
col.elements= new int[1];
col.elements[0]= element;
}
//this is the second part but i do not know how to do it.
//Please help me to complete***************
else {
int *temp;
temp = new[];
}
}
void PrintCollection(Collection col) {
cout << "[ ";
for(int i = 0; i < col.elno; i++)
cout << col.elements[i] << " ";
cout << "]" << endl;
}
int main(void) {
Collection collection = { 0, NULL };
int elems;
cout << "How many elements? ";
cin >> elems;
srand(time(NULL));
for(int i = 0; i < elems; i++)
AddToCollection(collection, rand() % 100 + 1);
PrintCollection(collection);
delete[] collection.elements;
return 0;
}
vector container is originally dynamic container. so u can use vector.
Just declare vector variable in structure and use it in AddToCollection function.
struct Collection {
int elno;
std::vector<int> elements;
};
void AddToCollection(Collection &col, int element) {
col.elements.push_back(element);
col.elno++;
}
like this.
Here is what you are looking for:
void AddToCollection(Collection &col, int element)
{
if(col.elements == NULL)
{
col.elements = new int[1];
col.elements[0] = element;
col.elno = 1;
}
else
{
int *newArr = new int[col.elno+1];
for(int i = 0; i < col.elno; i++)
{
newArr[i] = col.elements[i];
}
newArr[col.elno] = element;
delete[] col.elements;
col.elements = new int[col.elno+1];
for(int i = 0; i < col.elno+1; i++)
{
col.elements[i] = newArr[i];
}
delete[] newArr;
newArr = NULL; // avoid dangling pointer
col.elno++;
}
}
For sure using vector container is a great ideea but the exercise require no modification to the main function. The objective of this exercise is to help the student to understand dynamically allocated memory.

C++ beginner declaring a function involving array of structures

There is a few lines of my code that I would like to define as a function because I plan to use it multiple times. portion of code is as follows:
// loop within loop used to reorder with highest price at the top
for(i=0;i<x;i++){
for(t=i;t<x;t++){
if(f[i].price < f[t].price) {
temp = f[i].price;
f[i].price = f[t].price;
f[t].price = temp;
}
}
}
I hope to be able to enter new values for x and f each time I call the function. I have included all of my code below. If I'm unclear about my objective in anyway please feel free to ask. I apologize in advance for the improper terminology I am new to this. Thank you
#include <iostream>
using namespace std;
struct List
{
char name[10];
int price;
};
int main()
{
//x represents number of structures within array!
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
//array of structures fruit
struct List f[x];
int i;
//input values into structure
for (i = 0; i < x; i++) {
cout << "\nEnter fruit name, and price.\n";
cin >> f[i].name;
cin >> f[i].price;
};
//variables for reordering
int temp;
int t;
// loop within loop used to reorder with highest price at the top
for(i=0;i<x;i++){
for(t=i;t<x;t++){
if(f[i].price < f[t].price) {
temp = f[i].price;
f[i].price = f[t].price;
f[t].price = temp;
}
}
}
//Output of menus
//fruit Menu
cout << "\n\nFruit Menu";
for (i = 0; i < x; i++) {
cout << "\n" << f[i].name << " $" << f[i]. price;
};
return 0;
}
I suppose it is an assignment that says "implement your own sort function for sorting an array of fruits", so I take the data structure "array of fruits" as given. You can, of course, change this to vector<struct Fruit> as well, but that's a different topic.
Maybe the following fragments help you finishing your code. It contains functions for entering, sorting, and printing the array with some samples how to deal with the parameters and the calls. You'll have to finalise the code.
Have fun!
#include <iostream>
using namespace std;
struct Fruit
{
char name[10];
int price;
};
// enter up to nrOfFruis; return number of fruits actually entered
int enterFruits(struct Fruit *fruits, int maxNrOfFruits) {
int entered = 0;
while (entered < maxNrOfFruits) {
cin >> fruits[entered].name;
entered++;
}
return entered;
}
void sortFruits(struct Fruit* fruits, int nrOfFruits) {
// your sort code goes here
// example for swaping two elements:
Fruit temp = fruits[0];
fruits[0] = fruits[1];
fruits[1] = temp;
}
void printFruits(struct Fruit *fruits, int nrOfFruits) {
cout << "\n\nFruit Menu";
for (int i = 0; i < nrOfFruits; i++) {
cout << "\n" << fruits[i].name << " $" << fruits[i]. price;
};
}
int main()
{
// Your task: put a proper loop and exit condition arround the following lines...
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
struct Fruit fruits[x];
int entered = enterFruits(fruits, x);
sortFruits(fruits, entered);
printFruits(fruits, entered);
return 0;
}
You cannot allocate an array on the stack if you do not know it's size at compile time. Therefore, you need to dynamically allocate memory for it(you also need to remember to delete it):
//x represents number of structures within array!
int x;
cout << "How many items would you like to list under the fruit menu?\n";
cin >> x;
//array of structures fruit
struct List * f = new List[x];
//...
delete [] f;
Alternatively, you could do it the C++ way, using vector, having the vector elements on the stack:
int x;
std::cin>>x;
std::vector<A> v(x);
for( size_t i = 0; i < x; i++)
{
std::cin >> v[i].x;
}
If you just want to pass an array to a function you can do so like this:
void sortArray(struct List list[]);
void sortArray(struct List* list, int n); // n = size of array
may be better to just use std::vector or some other list container instead. :)
Sounds like you want a function that receives an array t and index x, and you want to mutate the array in the function?
C++ is "pass by value", so to mutate the array you have to have your function take a reference (or pointer) to the array so that you're mutating the original array and not a copy of it, so just have your function signature like this: func(T& t, int x) (assuming T is the type of array t).

Incorrect Variable output with Vector Class C++

My output for the call to the temporary array size wont correctly output. It resizes as according, but I can't get the MAX to display the new value of the new array. My error is within the Resize function within the class.
#include <iostream>
#include <vector>
#include <string>
#include <math.h>
#include <ctime>
using namespace std;
class VectorClass {
private:
int * Vector;//This will be our resizeable array
int Size; //Keep track of vector current size
int MAX=10;
int growth = 5;
int num;
int Resize(int growth, int MAX);
public:
VectorClass(int growth, int Size);
~VectorClass();
int AddItem(int num);
void RemoveItem();
void Print(void);
};
VectorClass::VectorClass(int growth, int Size)
{
Size = 10;
growth = 5;
Vector = new int[Size];
}
VectorClass::~VectorClass()
{
cout << "Destructor was called." << endl;
}
//Will insert num into the vector at the current open position
int VectorClass::AddItem(int num)
{
Vector[Size] = num;
Size++; //Indicate that there isnt as much free space
if (Size == MAX)
{
Resize(Size, MAX);
}
Print();
return num;
}
//Get rid of the most recently added item
void VectorClass::RemoveItem()
{
Size--; //Tricks the vector into one fewer elements in it it currently does
Print();
}
int VectorClass::Resize(int growth, int MAX)
{
cout << "Array is full! Resizing the Array!" << endl;
//Step 1: make a copy
int * temp = new int[MAX]; //Make a new array, same size as exiting array
//loop that copies the original into the copy
for (int i = 0; i<MAX; i++)
{
temp[i] = Vector[i];
}
//Step 2: Delete the original
delete[] Vector; //Deletes all elements in the array Vector from the Heap
//Step 3: Make a bigger vector
Vector = new int[MAX + growth];
//Step 4: Reverse the copy and record the size change
for (int i = 0; i<MAX; i++)
{
Vector[i] = temp[i];
}
MAX = MAX + growth;
//Step 5: Delete the copy
delete[] temp;
cout << "Resize was called.\n" << endl;
return MAX;
}
void VectorClass::Print()
{
cout << "*******************************************************" << endl;
for (int i = 0; i< Size; i++)
{
cout << Vector[i] << endl;
}
cout << "Size = " << Size << "\tMAX = " << MAX << "\t Growth = " << growth << endl << endl;
cout << "*******************************************************" << endl;
}
int main(void)
{
VectorClass V(5,10);
for (int i = 0; i <= 4; i++)
{
int x = rand();
V.AddItem(x);
}
//Print the Vector #1
V.Print();
//Delete 2 Items
V.RemoveItem();
V.RemoveItem();
//Add 9 random Numbers
for (int i = 0; i <= 8; i++)
{
int x = rand();
V.AddItem(x);
}
//Print the Vector
V.Print();
system("pause");
return 0;
}
Several things are wrong with you code. The first one, probably not the one you care about most, is that you never free the memory. You should do it in your destructor, or even better use a std::unique_ptr to handle your memory.
Now, i believe you are yourself confused about your own variables. I see that you possess a variable member named num that you never use. Even worse, you have a parameter in AddItem with the same name. Are you sure it does what you want? The same is true for growth. I would advise you to name your member variable differently, so that you know what they are quickly. I prefixe them with "m_" for example, but you can do as you wish.
You do not need to declare your function parameters inside your class. Only in the function prototype.
Then, in your AddItem function, you use your variable Size to determine where to add the new element, but you initialize your array with it too, which means that not only you do not add your elements at the beginning of your array, you try to write them in memory you do not own!
I could continue for a long time. I am sorry but it only appears to me that you do not know C++ at all. You should go learn the basics again, and maybe start with an easier project to begin your C++ learning.
Good luck :-)

Creation of Dynamic Array of Dynamic Objects in C++

I know how to create a array of dynamic objects.
For example, the class name is Stock.
Stock *stockArray[4];
for(int i = 0 ; i < 4;i++)
{
stockArray[i] = new Stock();
}
How do you change this to dynamic array of dynamic objects?
What I tried:
Stock stockArrayPointer = new Stock stock[4];
It doesn't work and the error is "The value of Stock** cannot be used to initalize an entity of type Stock.
Second question is after the creation of dynamic array of dynamic objects, what is the syntax to access the pointers in the array.
Now, I use stockArray[i] = new Stock(); How will this change?
Need some guidance on this...
If you are using c++ then you shouldn't reinvent the wheel, just use vectors:
#include <vector>
std::vector< std::vector< Stock > > StockVector;
// do this as many times as you wish
StockVector.push_back( std::vector< Stock >() );
// Now you are adding a stock to the i-th stockarray
StockVector[i].push_back( Stock() );
Edit:
I didn't understand your question, if you just want to have and array of arrays allocated on the heap just use:
Stock** StockArrayArray = new Stock*[n]; // where n is number of arrays to create
for( int i = 0; i < n; ++i )
{
StockArrayArray[i] = new Stock[25];
}
// for freeing
for( int i = 0; i < n; ++i )
{
delete[] StockArrayArray[i];
}
delete[] StockArrayArray;
The type of a variable to a dynamic array is a pointer to the first object of the array. You want an array of dynamically allocated Stock objects, so an array of pointers to Stock, so your variable is a pointer to a pointer to Stock:
int n = 4; // dynamic size of the array;
Stock** stockArray = new Stock*[n];
for (int i = 0; i != n; ++i)
{
stockArray[i] = new Stock();
}
and freeing it:
for (int i = 0; i != n; ++i)
{
delete stockArray[i];
}
delete[] stockArray;
Stock* stockArrayPointer = new Stock [4];
works only if the Stock class has a zero argument constructor
if it does not have any zero argument constructor you cannot create an array of dynamic objects dynamically
you can as said create a array of dynamic object with a static array like
Stock stockArrayPointer[4]={Stock(args),Stock (args)};
but the syntax
Stock* stockArrayPointer=new Stock[4]{Stock(args),Stock (args)}; does not hold
or as said
use vectors...
vectors are memory allocated on heap
so the vector is a dynamic allocation
vector<Stock> V;
V.push_back(Stock(args));
or
V.push_back(new Stock(args));
The reason why
Stock* stockArrayPointer=new Stock[4]{Stock(args),Stock (args)};
does not hold
is because
this means
you are using the new operator incorrectly
I did something which worked perfectly:
#include <iostream>
#include <cstring>
#include <cstdlib>
using namespace std;
class student {
string name;
int age;
int roll;
public:
student() {
name="";
age=0;
roll=0;
}
student (string n, int a, int r) {
name=n;
age=a;
roll=r;
}
void show_details ();
};
void student::show_details() {
cout << "Name: " << name << "\n";
cout << "Age: " << age << "\n";
cout << "Roll No: " << roll << "\n";
}
int main() {
string a; int b, c, n;
cin >> n;
student **obj;
obj=(student**)malloc(n*sizeof(student*));
for (int i=0; i<n; i++) {
cin >> a;
cin >> b;
cin >> c;
obj[i]=new student(a,b,c);
}
for (int i=0; i<n; i++) {
obj[i]->show_details();
}
for (int i=0; i<n; i++) free (obj[i]);
free (obj);
}
Yes... I used pointer to pointer for the array part, and it worked perfectly for variable sized arrays.