I am relatively new to programming and am trying to read an array of ints into a 2-D dynamic array. I'm relatively sure this is just a syntax issue.
The array is dynamic and therefore is of type int**. To try to populate the array, I've used a nested for loop to populate each element of the array with the next term from the ifstream. Input is assumed to be all ints separated by
whitespace.
//declare dynamic 2-D array
int** myArray = new int*[numRows]
for (int i = 0; i < numCols; i++)
{
myArray[i] = new int[numCols];
}
//populate array from ifstream
for (int i = 0; i < numRows; i++)
{
for (int j = 0; j < numCols; j++)
{
inFile >> myArray[i][j];
}
}
I expected to be able to store the ints from the ifstream (all between 0-100) directly into the array, but I seem to be storing addresses instead (very
large negative ints). What am I doing wrong?
Fixing the typo and a missing semicolon should fix it
// declare dynamic 2-D array
int** myArray = new int*[numRows]
// ^
// ;
for (int i = 0; i < numCols; i++) {
// ^^^^^^^
// numRows
myArray[i] = new int[numCols];
}
Related
This might be a dumb question but there is something I can't quite understand. When using a vector, whenever I want to 'push_back' an element to a certain position I can do that only if I initialize the vector in a certain way.
For example when I use this initialization:
std::vector<int> Myvec;
int size = 0;
int x = 0;
std::cin >> size;
for(int i = 0; i < size; i++)
{
std::cin >> x;
Myvec[i].push_back(x);
}
I receive the following error:
request for member 'push_back' in 'Myvec.std::vector<_Tp, _Alloc>::operator[] >(((std::vector::size_type)i))', which is of non-class type '__gnu_cxx::__alloc_traits >::value_type {aka int}'|
But when I use the following initialization it works:
int size = 0;
int x = 0;
std::cin >> size;
std::vector<int> Myvec[size];
for(int i = 0; i < size; i++)
{
std::cin >> x;
Myvec[i].push_back(x);
}
I don't have any problem using it and can implement it in all sorts of tasks, but it's bugging me because I'm not sure why it is actually working. Thank you for your help in advance.
In the first block you should use:
std::vector<int> Myvec;
int size = 0;
int x = 0;
std::cin >> size;
for(int i = 0; i < size; i++)
{
std::cin >> x;
Myvec.push_back(x);
}
Or you can use:
int size = 0;
int x = 0;
std::cin >> size;
std::vector<int> Myvec(size);
for(int i = 0; i < size; i++)
{
cin>>Myvec[i];
}
And print the vector using:
for(int i = 0; i < size; i++) {
std::cout<< Myvec[i]<<" ";
}
When you initialise it using vector Myvec[size], it becomes vector of vectors with size "size", means each Myvec[i] is a vector in which you can push elements.
Read more here: https://www.geeksforgeeks.org/2d-vector-in-cpp-with-user-defined-size/
You have a misunderstanding on how the std::vector::push_back function works. It basically appends a new object at the end of the vector. In particular, you don't need to index into the vector with std::vector::operator[]. Instead, change your snippet to
for(int i = 0; i < size; i++)
{
std::cin >> x;
Myvec.push_back(x);
}
The solution you came up with does something that you probably don't intend, i.e., using a raw array of vectors: when transferring user input into the objects, it creates size vectors with one element each.
You're not putting an element at position i in a vector.
You're putting an element at the back of the ith vector in an array of vectors! Worse, the array is empty, so the access is invalid.
If it weren't, though, you'd end up with i vectors each having one element. Not good!
Instead, you can make your vector be of a certain size:
MyVec.resize(SomeSize);
…then assign the elements as if the vector were an array (which it kind of is):
MyVec[i] = thing;
The key point here is that you don't have to push_back; you only do that when you want to push a new element to the back of the vector. You can access existing values with array-like [] syntax just fine.
Read more about vectors in your C++ book.
I try to define a 2D array with C++ with pointers and I don't know how can I define it true? I have some loops in the function and they are start with 1 to n and I want to allocate memory and at the end of function I want to delete allocated memory?
for define it like the following code. please help me to develop it.
int **W;
W = new int* [n];
for (int i=1; i <= n; i++)
W[i] = new int[n];
///////////////////////
for (int k=1;k<=n;k++)
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
do some thing!
///////////////////////
for ( int i = 1; i <= n; i++ )
delete [] W[i];
delete W;
For an array of size n, indices start from 0 - (n-1). Thus array[n] is out of bounds.
int **W;
int n = 3;
W = new int*[n];
for (int i = 0; i < n; i++)
W[i] = new int[n];
for (int i = 0; i < n; i++)
delete[] W[i];
delete W;
You have the general idea correct. But there are some errors in the details. C/C++ use 0-based indices to access arrays.
for (int i=1; i <= n; i++)
W[i] = new int[n];
needs to be
for (int i=0; i < n; i++)
W[i] = new int[n];
Similar changes need to be made in the other for statements.
Also, you need to delete W using the array delete operator. Instead of
delete W;
use
delete [] W;
Having said that, you should use std::vector instead of plain old dynamic arrays. With std::vector, you don't have to worry about deallocation of memory. The destructor of std::vector will take care of deallocating memory.
A 2D array of size n x n where each element is initialized to 0 can be defined simply as:
std::vector<std::vector<int>> array(n, std::vector<int>(n, 0));
CASE1:
int nrows=5;
int ncols=10;
int **rowptr;
rowptr=new int*;
for(int rows=0;rows<nrows;rows++) {
for(int cols=0;cols<ncols;cols++) {
*rowptr=new int;
}
}
CASE2:
int nrows=5;
int ncols=10;
int **rowptr;
for(int rows=0;rows<nrows;rows++) {
rowptr=new int*;
for(int cols=0;cols<ncols;cols++) {
*rowptr=new int;
}
}
I am able to insert and print values using both ways. What is the difference in initializations?
What is the difference?
#1 just allocates memory enough to hold a integer pointer and not an array of integer pointers.
#2 Causes a memory leak by just overwritting the memory allocation of the previous iteration.
I am able to insert and print values using both the ways
Memory leaks and Undefined behaviors may not produce immediate observale erroneous results in your program but they sure are good cases of the Murphy's Law.
The correct way to do this is:
int nrows = 5;
int ncols = 10;
//Allocate enough memory for an array of integer pointers
int **rowptr = new int*[nrows];
//loop through the array and create the second dimension
for (int i = 0;i < nrows;i++)
rowptr[i] = new int[ncols];
You have a memory leak in both cases.
The proper way to initialize such a "2d" array is
int** arr = new int*[nrows];
for (int i = 0; i < nrows; i++)
arr[i] = new int[ncols];
Note however, that it isn't a 2d array as defined by C/C++. It may not, and probably will not, be consecutive in memory. Also, the assembly code for accessing members is different.
In your case, the accessing by indexing is equivalent to *(*(arr+i)+j)
And in the case of a 2d array it's *(arr + N_COLS*i + j) when N_COLS is a compile time constant.
If you want a true 2d array you should do something like this:
int (*arr)[N_COLS] = (int(*)[N_COLS])(new int[N_ROWS * N_COLS])
You'd better use 1d array to manage 2d array
int **x = new int*[nrows];
x[0] = new int[nrows*ncols];
for (int i = 1; i < nrows; i++)
x[i] = x[i-1] + ncols;
for (int i = 0; i < nrows; i++)
for (int j = 0; j < ncols; j++)
x[i][j] = 0;
delete [] x[0];
delete [] x;
I have this function that reads a textfile and sends the strings to an array and then from that function I send that array and number of elements to my constructor. Now my constructor creates a dynamic 2d-array(I hope). I would like my 2d-arrays rows and columns to be assigned values from the array received.
heres my constructor.
Graph::Graph(string cities[], int n)
{
this->nrOfCities=n;
this->x=n;
this->y=n;
this->graph=new string *[x];
for (int i = 0; i < x; i++)
this->graph[i] =new string[y];
for(int i=0;i<this->x;i++)
for(int j=0;j<this->x;j++)
this->graph[j]=NULL;
for(int i=0;i<=this->x;i++)//I know this last part doesn't work.
for(int j=0;j<this->x;j++)
this->graph[0][j+1]=cities[j];
}
Any kind of help is appreciated.
In order to make a dynamic 2darray you must try s.th. like this:
type** arr2d;
arr2d = new type*[rows];
for(int i=0; i<rows; ++i)
arr2d[i] = new type[cols];
I am making a C++ program that checks if given aray is a latin square. I need to use a dynamic multi-dimensional array that stores given latin square. But I cant pass the array to a function that does the checking...
Currently I have such code for calling the function:
int squaretest(int **p, int n, int sum) {
//some code
};
And this code is for creating the array:
int main() {
//some code. n - length of one row, sum - sum of elements in one row.
int a;
int **lsquare;
lsquare = new int*[n];
for (int i=0;i<=n-1;i++) for (int j=0;j<=n-1;j++) {
cin >>a;
lsquare[i][j] = a;
}
blocktest(lsquare,n,sum);
//some code
};
The code compiles (i am using Geany IDE and G++ compiler) but when I run it in terminal, after the first imput, that has to be stored in block[0][0] I get Segmentation fault error. What's wrong with my code and what is the correct sollution?
To be able to do that.. You actually need to do this:
int **lsquare = new int*[n];
for (int i=0; i<n; ++i)
lquare[i] = new int[n];
for (int i=0; i<n; i++)
for (int j=0; j<n; j++)
cin >> lsquare[i][j];
blocktest(lsquare,n,sum);
The better system would be to do:
int *lsquare = new int[n*n];
for (int i=0; i<n; ++i)
for (int j=0; j<n; ++j)
cin >> lsquare[i + j*n];
blocktest(lsquare, n, sum);
You forgot to allocate memory for second dimension of the matrix.
int **lsquare;
lsquare = new int*[n];
for (int i=0; i<n; ++i){
lsquare[i] = new int[n];
....}
nobody writes
for (int i=0;i<=n-1;i++){...}
Do instead
for (int i=0; i<n; ++i){...}
You have an array of pointers in lsquare.
You might want to just do something like:
lsquare = new int[n * n];
That way you can then fill in this square, but the type is then:
int *lsquare
What you are actually creating an array of arrays. Not only do you need to allocate the array of arrays using new, but also you must allocate all n arrays. You'll want to have the outer loop of your nested for loop allocate each of the n sub-arrays.
lsquare = new int*[n];
for (int i=0;i<=n-1;i++)
{
lsquare[i] = new int[n];
for (int j = 0;j<=n-1;j++)
{
//...
You made yourself a pointer pointer that can be used as a matrix, allocated one row for it, then proceeded to act like you'd allocated an entire n*n matrix. You will indeed get a segfault if you run that.
You need to allocate enough space for n*n elements, not just n of them.
A less error-prone solution might be to use a std::vector of std::vectors.
You have to allocate space for the second dimension too, add this after you allocate lsquare:
for(int i = 0; i < n; ++i)
{
lsquare[i] = new int[n];
}