Dynamically adding an object? - c++

#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
static int c;
class DAI //DynamicArrayInput
{
public :
void getCountry()
{
cout << "Country : ";
cin >> Country;
}
void putCountry()
{
cout << Country << endl;
}
static int putCount()
{
return count;
}
private :
static int count;
char Country[30];
};
int main()
{
vector< DAI > A;
DAI B[3];
//DAI * B;
cout << "Enter name of countries\n";
for(int i=0; i < 3; i++)
{
//THIS DOESN'T WORK
/*
c++; //c is a static variable declared at top
B = new DAI[sizeof(DAI) * c/sizeof(DAI)];
GIVES WRONG OUTPUT :
Enter name of countries
Country : a
Country : b
Country : c
Printing name of countries
c
size of vector A is 3
vector after initialisation:
*/
A.push_back(B[i]);
B[i].getCountry();
}
cout << "Printing name of countries\n";
for(int i=0; i < 3; i++)
{
B[i].putCountry();
}
cout << "size of vector A is " << A.size() << "\
\nvector after initialisation:" << endl;
return 0;
}
**/*
CORRECT OUTPUT WITH LIMITED ARRAY SIZE = 3:
*Enter name of countries
Country : a
Country : b
Country : c
Printing name of countries
a
b
c
size of vector A is 3
vector after initialisation:*
*/**
I am just learning and this is not my homework,
I dont want to be limited to any array size such as above but when i try to use the staements in the first for loop as mentioned it does not work
i mean this does not works
c++; //c is a static variable declared at top
B = new DAI[sizeof(DAI) * c/sizeof(DAI)]; //B is a pointer of type class DAI
My aim is to use arrays of objects i like dynamically so that i can input any number of countries I don't want to use something like B[3] with something known array size but i am unable to do.
Please guide me, help me.

c++;   //c is a static variable declared at top
B = new DAI[sizeof(DAI) * c/sizeof(DAI)];
Here you are confusing new with malloc. To allocate c elements of type DAI, just do
B = new DAI[c];
However, your best bet is to stay with std::vector, which handles size and capacity itself.
for (int i = 0; i != 10; ++i)
A.push_back(DAI());
adds 10 DAIs to the vector A.
Edit
You can also create the vector with a number of DAIs from the start:
std::vector<DAI> A(10);
This also creates a vector with 10 elements, all at once. Unlike B[3], which always contains 3 elements, the vector can grow or shrink as needed without you having to handle the allocations.

Your array is static DAI[3] v (v is in the process' stack). To be able to add an element dynamically, you need to change it with DAI[INITIAL_SZ] v = new DAI[INITIAL_SZ] (now v is in the heap) so that now you can realloc it when adding/deleting elements.

Related

Problem using iterators with dynamically allocated array

I have a variable k of type int to set the length of a dynamically allocated int array:
int *Numbers = new int[k];
But because of this I cannot iterate over the array, I get an error:
"no matching begin function was found required for this range-based for statement"
I also cannot get the length of the array using size();
Here's the complete code:
#include <iostream>
using namespace std;
int main()
{
int b, k;
cin >> b >> k;
int *Numbers = new int[k];
for (int i : Numbers) {// (There is a error)
}
for (int i = 0; i < size(Numbers); i++) {
}
}
Prefer using a std::vector instead of a std::array. (Like #tadman mentioned.)
Here is your code using std::vector instead:
#include <iostream>
#include <vector>
int main()
{
int b, k;
std::cin >> b >> k;
std::vector<int> Numbers(b,k); // Fills the vector "Numbers" with nth number of elements with each element as a copy of val.
for (int i : Numbers)
std::cout << i << std::endl;
for (int i = 0; i < Numbers.size(); i++)
std::cout << Numbers[i] << std::endl;
return 0;
}
Say I want 10 elements with the number 5.
Output:
10
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
5
Also consider not using namespace std;.
The simple and recommended solution is to use std::vector, however if you really want a dynamically allocated array and to use iterator like features on it, you can use iterator_range from boost library, which allows you to create an iterator range for it thus making it usable in range based for loops and in functions like std::size.
Live demo
#include <iostream>
#include<boost/range.hpp>
int main()
{
int k = 5;
int *Numbers = new int[k]{1,4,5,7,8};
auto arr = boost::make_iterator_range(Numbers, Numbers + k);
for (int i : arr) { //range based loop
std::cout << i << " ";
}
std::cout << std::endl << "Size: " << arr.size(); //print size
//or std::size(arr);
}
Output:
1 4 5 7 8
Size: 5
Range-based for loops work with arrays, but not work with pointers. The Actual issue is that arrays is actually a pointer and not an array.try to use simple array.
Using pointers is problematic for many reasons. The simple solution to your problem is to use a vector
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int b, k;
cin >> b >> k;
vector<int> Numbers(k);
for (int i : Numbers) {
cout << i << endl;
}
for (int i = 0; i < Numbers.size(); i++) {
cout << Numbers[i] << endl;
}
}
C array does not have default iterator and thus there is no begin() and end() functions that are used to iterate over array when you use statment like this:
for (int i : Numbers)
You can check range-for reference:
range_expression - any expression that represents a suitable sequence (either an array or an object for which begin and end member functions or free functions are defined, see below) or a braced-init-list.
Okay, so since the dynamic array does not have a default iterator, do not use the for-each loop, instead consider using the regular for loop.
Also, mind the the size function will not work for an array (or dynamic array) and you need to remember the size, since it's not possible to get the size from the pointer only. Hence, this code would work:
#include <iostream>
using namespace std;
int main()
{
int b, k;
cin >> b >> k;
int *Numbers = new int[k];
const int SIZE = k;
for (int i = 0; i < SIZE; i++) {
cout << i << ' ';
}
}
You need to dereference *Numbers by using the * if you want to iterate over the array because *Numbers is a pointer to an integer which points to the first element of your array.For Example :
#include <iostream>
using namespace std;
int main()
{
int k = 10;
int *numbers = new int[k];
//filling the array
for(int i = 0 ; i < k ; ++i) {
*(numbers + i) = i ;
}
//output array element
for(int i = 0 ; i < k ; ++i) {
cout << numbers + i << " is the address of "<<*(numbers + i) << endl;
}
return 0;
}
The output is :
0x6f1750 is the address of 0
0x6f1754 is the address of 1
0x6f1758 is the address of 2
0x6f175c is the address of 3
0x6f1760 is the address of 4
0x6f1764 is the address of 5
0x6f1768 is the address of 6
0x6f176c is the address of 7
0x6f1770 is the address of 8
0x6f1774 is the address of 9
Unfortunatly, you can't get the size of your array with *Numbers because it's not an array but a pointer.

why range base loop doesn't work for arrays in heap, but works for the arrays in stack

Here I'm trying to user c++11 range base loop for tow integer arrays. one declared using new keyword and other not.
#include <iostream>
#include <stdlib.h>
#define ARRAY_LENGTH 100
int main()
{
int* heap_array = new int[ARRAY_LENGTH];
int stack_aray[ARRAY_LENGTH];
for(int i=0; i < ARRAY_LENGTH; i++)
{
int val = (rand() % ARRAY_LENGTH) + 1;
heap_array[i] = val;
stack_array[i] = val;
}
for(int& i : stack_array){ std::cout << i << std::endl;}
for(int& i : *heap_array){ std::cout << i << std::endl;} // compile error
delete[] heap_array;
return 0;
}
Why range base loop doesn't work for the array declared with new keyword? my view is it doesn't matter heap or stack both are heap_array & stack_array are pointers to the first element.
Your heap_array isn't really an array but a raw pointer to an int. A raw pointer does not know anything about the number of elements allocated.

Creating a vector of objects

vector <Population> obj;
int num_of_cities = 0;
cout<<"Enter the number of cities"<<endl;
cin>>num_of_cities;
for( int x = 0; x < num_of_cities ; x++)
{
cout<<"Enter population for city #"<< x + 1 <<endl;
cin>>populate;
obj[x].setPopulation(populate);
.....
Im trying to make a vector of objects. Basically the user will input the amount of cities and the program should create an object for each city. That way information on each city can be entered. I believe there is a problem with the syntax because once I put a value for populate, the program crashes. Any one can help ?
The following line is the problem:
obj[x].setPopulation(populate);
You are trying to access the object at index x but your vector is actually empty.
To solve this, there is 2 solutions:
You should create a Population object and push_back to your vector at each loop iteration
Example:
//...
for( int x = 0; x < num_of_cities ; x++)
{
cout<<"Enter population for city #"<< x + 1 <<endl;
cin>>populate;
Population pop;
pop.setPopulation(populate)
obj.push_back(pop);
}
//...
Or you initialize your vector with a size only when you know the number of cities: vector <Population> obj (num_of_cities);
Example:
//...
cin>>num_of_cities;
vector <Population> obj (num_of_cities); // move your vector declaration here
for( int x = 0; x < num_of_cities ; x++)
//...
obj[x].setPopulation(populate);
here you are trying to access an element which is out-of-bound, since the vector obj has no content yet.
A way to make this work would be to call
obj.resize(num_of_cities)
before the for loop.
A more general approach (which would work if you do not know beforehand how many elements you will have, but which is slower in this case), would be creating a Population object, and then pushing it to the vector:
Population p;
p.setPopulation(populate);
obj.push_back(p);
While currently available answers correctly identify the source of the problem at hand - access to empty vector - they fail to set the right example of using the vector in a given scenario. They either suggest a push_back of pre-constructed object - thus calling a copy-construcor unnecessarily - or demand a presence of default constructor, with a side effect of exra assignment.
The most elegant solution would be following:
Make sure your Population has a constructor which accepts population size and sets internal member accordingly (likely to be const int):
Population::Population(int habitants) : habitants(habitants) { }
Than, use emplace_back to insert an object without calling any other constructors:
obj.emplace_back(populate);
The following code will let you make a vector of city objects that you can then populate with meaningful data. First, you need to define a City class that can set and get the various data items. The code will compile and run but it is a limited version of what you might want to accomplish.
#include<iostream>
#include<vector>
#include<string>
using namespace std;
class City {
public:
City() {}
~City() {}
void setPopulation(int& pop) { m_pop = pop; }
int getPopulation() const { return m_pop; }
void setName(const string& name) { m_name = name; }
string getName() const { return m_name; }
private:
string m_name{ "" };
int m_pop{ 0 };
};
vector<City> cities(0);
int num_of_cities = 0;
int main() {
do {
cout << "Enter number of cities: ";
cin >> num_of_cities;
} while (num_of_cities < 1);
cities.resize(num_of_cities);
int val{ 0 };
string nam{ "" };
for (int i = 0; i < cities.size(); i++) {
cout << "Enter name of city: ";
cin >> nam;
cities[i].setName(nam);
cout << "Enter population for city: ";
cin >> val;
cities[i].setPopulation(val);
}
system("pause");
return 0;
}

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.

Do jagged arrays exist in C/C++?

Is there such a thing as a jagged array in C or C++?
When I compile this:
int jagged[][] = { {0,1}, {1,2,3} };
I get this error:
error: declaration of `jagged' as multidimensional array must have bounds for all dimensions except the first
In C I would use an array of pointers.
For instance:
int *jagged[5];
jagged[0] = malloc(sizeof(int) * 10);
jagged[1] = malloc(sizeof(int) * 3);
etc etc.
There's a bunch of ways to do it. Here's another way:
int jagged_row0[] = {0,1};
int jagged_row1[] = {1,2,3};
int *jagged[] = { jagged_row0, jagged_row1 };
If you just want to initialise it, you can say:
int jagged[][3] = { {0,1}, {1,2,3} };
but the array will still have the shape [2][3]. If you want a true jagged array, you will have to create it dynamically. And if you do that, and are using C++, you should use a std::vector, as friol suggests.
In C++ (not compiled, and probably there's a more compact syntax):
std::vector<std::vector<int> > myArray;
myArray.push_back(std::vector<int>());
myArray.push_back(std::vector<int>());
myArray[0].push_back(0);
myArray[0].push_back(1);
myArray[1].push_back(1);
myArray[1].push_back(2);
myArray[1].push_back(3);
So now you can access the elements with, for example, myArray[0][0], etc.
In C99 you can do the following:
int jagged_row0[] = {0,1};
int jagged_row1[] = {1,2,3};
int (*jagged[])[] = { &jagged_row0, &jagged_row1 }; // note the ampersand
// also since compound literals are lvalues ...
int (*jagged2[])[] = { &(int[]){0,1}, &(int[]){1,2,3} };
The only difference here (as compared to rampion's answer) is that the arrays don't decay to pointers and one has to access the individual arrays via another level of indirection - (e.g. *jagged[0] - and the size of each row has to be recorded - i.e. sizeof(*jagged[0]) will not compile) - but they're jagged-appearing to the bone ;)
The reason you got the error is that you must specify the bounds for at least the outer dimension; i.e.
int jagged[][3] = {{0,1},{1,2,3}};
You cannot have jagged[0] be a 2-element array of int and jagged[1] be a 3-element array of int; an N-element array is a different type from an M-element array (where N != M), and all elements of an array must be the same type.
What you can do is what the others have suggested above and create jagged as an array of pointers to int; that way each element can point to integer arrays of different sizes:
int row0[] = {0,1};
int row1[] = {1,2,3};
int *jagged[] = {row0, row1};
Even though row0 and row1 are different types (2-element vs. 3-element arrays of int), in the context of the initializer they are both implicitly converted to the same type (int *).
With C++11 initializer lists this can be written more compactly:
#include <vector>
#include <iostream>
int main() {
// declare and initialize array
std::vector<std::vector<int>> arr = {{1,2,3}, {4,5}};
// print content of array
for (auto row : arr) {
for (auto col : row)
std::cout << col << " ";
std::cout << "\n";
}
}
The output is:
$ g++ test.cc -std=c++11 && ./a.out
1 2 3
4 5
For reference:
http://en.cppreference.com/w/cpp/utility/initializer_list
You can also use the compound literals in c to initialize a truly jagged array which is contiguous in memory as follows:
int (*arr[]) = { (int []) {0, 1}, (int []){ 2, 3, 4}, (int []){5, 6, 7, 8} }
This will be laid out contiguously in memory.
By using dynamic allocation in cpp we can create jagged arrays.
For example:
#include<iostream>
using namespace std;
int main(){
int n;
cout<<"Enter n:";
cin>>n;
cout<<"Enter elements:";
int **p = new int *[n];
for(int i=0;i<n;i++){
p[i] = new int[i+1];
for(int j=0;j<(i+1);j++){
cin>>p[i][j];
}
}
cout<<"Jagged Array:"<<endl;
for(int i=0;i<n;i++){
for(int j=0;j<(i+1);j++){
cout<<p[i][j]<<" ";
}
cout<<endl;
}
for(int i=0;i<n;i++){
delete []p[i];
}
delete []p;
}
For n=3, we have created a jagged array in the following look:
Enter n: 3
Enter elements:
1
1 2
1 2 3
Jagged Array:
1
1 2
1 2 3
//
//jaggedArrays.cpp
//
//program to implement jagged arrays in c++
//
#include<iostream>
#include<iomanip>
using namespace std;
int main()
{
int rows, i, j;
cout << endl << "Enter no of rows : ";
cin >> rows;
int columnsSizeOfEachRow[rows];
cout << endl;
for( i = 0 ; i < rows ; i++ )
{
cout << "Enter column size for row no " << i + 1 << " : ";
cin >> columnsSizeOfEachRow[i];
}
int *jaggedArray[rows];
for (i = 0 ; i < rows ; i++)
jaggedArray[i] = new int[columnsSizeOfEachRow[i]];
cout << endl;
for(i = 0 ; i < rows ; i++)
{
for ( j = 0 ; j < columnsSizeOfEachRow[i] ;j++)
{
cout << "Array[" << i + 1 << "][" << j + 1 << "] << ";
cin >> jaggedArray[i][j];
}
cout << endl;
}
cout << endl << endl << "Jagged array is as follows : " << endl;
for( i = 0 ; i < rows ; i++)
{
for ( j = 0 ; j < columnsSizeOfEachRow[i] ;j++)
cout << setw(3) <<jaggedArray[i][j] << " ";
cout << endl;
}
return 0;
}
The jagged arrays do exist in c++/c but the syntax is quite complex and you have to handle many things.
There are two types of jagged arrays in c++.
1) STATIC JAGGED ARRAY(A 2d array in which the size will be a constant number and there will be different number of columns in each row).
2) DYNAMIC JAGGED ARRAY(A 2d array in which the size will be any number taken from user and there will be different number of columns in each row)
1)STEPS OF IMPLEMENTING STATIC JAGGED ARRAY
Using array and a pointer
1) Declare 1-D arrays with the number of rows you will need
2) The size of each array(array for the elements in the row) will be the number of columns (or elements) in the row
3) Declare a 1-D array of pointers that will hold the addresses of the arrows
4) The size of the 1-D array is the number of rows you want in the jagged array
#include<iostream>
#include<string>
using namespace std;
int main()
{
int row0[4] = { 1,2,3,4 };
int row1[2] = { 5,6 };
int* jagged[2] = { row0,row1 };
int Size[2] = { 4,2 }, k = 0;
for (int i = 0; i < 2; i++)
{
int* ptr = jagged[i];
for (int j = 0; j < Size[k]; j++)
{
cout << *ptr << "";
ptr++;
}
cout << endl;
k++;
jagged[i]++;
}
return 0;
}
The output is as follows
123456
1)STEPS OF IMPLEMENTING DYNAMIC JAGGED ARRAY
Using an array of pointer
1) Declare an array of pointers(jagged array)
2) The size of this array will be the number of rows required in the jagged array
3) For each pointer in the array allocate memory for the number of elements you want in this row.
#include<iostream>
#include<string>
using namespace std;
int main()
{
//2 rows
int* jagged[2];
//Allocate memeory for the elements in the row 0
jagged[0] = new int[1];
//Allocate memory for the elements in row 1
jagged[1] = new int[5];
//Array to hold the size of each row
int Size[2] = { 1,5 },k = 0, number = 100;
//User enters the numbers
for (int i = 0; i < 2; i++)
{
int* p = jagged[i];
for (int j = 0; j < Size[k]; j++)
{
*p = number++;
//move the pointer
p++;
}
k++;
}
k = 0;
//Display elements in Jagged array
for (int i = 0; i < 2; i++)
{
int* q = jagged[i];
for (int j = 0; j < Size[k]; j++)
{
cout << *q << "";
//move the pointer to the next element
q++;
}
cout << endl;
k++;
//move the pointer to the next row
jagged[i]++;
}
delete[] jagged[0];
delete[] jagged[1];
return 0;
}
The output is as follows
100
101102103104105
No, there are no jagged multidimensional arrays in C nor C++. You can create various constructs that perform similar function at some memory cost (like array of pointers to arrays), but not an actual C-style multidimensional array.
The reason is that C-style arrays, no matter how many dimensions, occupy contiguous memory area with no metadata. So, memory-wise, they're all single-dimensional. It's only the cleverness of pointer arithmetic (striding the pointer by the size of a row) that gives you the functionality of extra dimensions. A jagged array laid out serially has different row sizes, so it cannot be strode by a constant value, so it requires additional storage depending on data size, thus is impossible to express in C type system.
It becomes clearer when you consider to what pointer multidimensional array decay to: Array to pointer decay and passing multidimensional arrays to functions
And that's why you see the error message must have bounds for all dimensions except the first, because all dimensions except the first are necessary to stride the array.