A pointer to a multidimensional array [duplicate] - c++

This question already has answers here:
May I treat a 2D array as a contiguous 1D array?
(6 answers)
Closed 8 years ago.
I'm having an issue creating a pointer to a multidimensional list. In the case of the single array - no problems output is as it should be. In the case of the multidimensional array - an error message is generated.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
const int ROWS = 3, COLS = 4;
int list[ROWS][COLS] = { {4, -3, 5, 6}, {5, 1, 7, 2},{-4,6,10,-8}};
int list2[] = {3, 6, 9, 2};
int *plist = list;
int *plist2 = list2;
for (int row = 0; row < ROWS; row++)
{
for (int col = 0; col < COLS; col++)
cout << setw(4) << list[row][col] << " ";
cout << endl;
}
cout << *plist << endl;
cout << *plist2 << endl;
return 0;
}
main.cpp:11:14: error: cannot convert "int ()[4]" to "int" in initialization
int *plist = list;

It really depends on what you are trying to do, but a 2D array cannot decay to a single pointer. As an example, pointer to array would work, letting the first dimension decay to pointer:
int (*plist)[COLS] = list;
You can then access the elements as plist[i][j].
Also beware of using names such as list, especially if you do something adventurous such as saying using namespace std;.

Related

The numbers in my bubble sort array output incorrectly after being sorted [duplicate]

This question already has an answer here:
Array not playing back properly inside function - bubble sort
(1 answer)
Closed 2 years ago.
I am learning bubble sort. In my output array, the numbers in my presort array output correctly, but the second time it outputs with the sorted numbers it omits the 0 in the 10. I get an output of: Before sort: Array = {10, 2, 3, 1} After sort: Array = {1, 2, 3, 1} Any ideas?
#include <iostream>
using namespace std;
void showArray(int sortMe[], int size);
int main()
{
int sortMe[4] = {10, 2, 3, 1}; // Original Array
int numElements = 4;
int temp; // For swapping
cout << "Before sort: ";
showArray(sortMe, numElements);
for (int i=numElements-1; i>0; i--) { // For loop1
for(int j=0; j<i; j++) {
// Checks if the value on left is bigger than the right
if(sortMe[j] > sortMe[j+1]) {
// If bigger swap values
temp = sortMe[j];
sortMe[j] = sortMe[j+1];
sortMe[j+1] = temp;
}
}
}
cout << "After sort: ";
showArray(sortMe, numElements);
}
void showArray(int sortMe[], int size) {
// Outputs array in format array = {num1, num2, etc.}
int i = 0;
cout << "Array = {";
for (int i = 0; i < size - 1; i++) {
cout << sortMe[i] << ", ";
}
cout << sortMe[i] << "}" << endl;
}
Your problem is not the sorting, but printing. You define i two times.
If you rewrite your for loop inside the print like this your problem is solved for (; i < size - 1; i++).
The way you've written it the last element is always the element at index 0 because of int i = 0; outside of the loop.

pushing back an array of objects into a vector c++

I have a class which takes an array and repopulates the array with the same numbers in random positions.
I now need generate a list that that generates 10 lists of the randomised array, which i believe i have done.
I done this by creating an array of my class object as seen in my code.
class numbers{
private:
int indexCount;
public:
void swap (int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void printArray (int arr[], int n)
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << "random calls: " << indexCount <<endl;
}
void randomize (int arr[], int n)
{
indexCount=0;
for (int i = n - 1; i > 0; i--)
{
int j = rand() % (i + 1);
indexCount++;
swap(&arr[i], &arr[j]);
}
}
};
int main()
{
srand (time(NULL));
vector <int> list;
int i;
int arr[] = {1, 2, 3, 4, 5, 6, 0, 0, 0};
int n = sizeof(arr) / sizeof(arr[0]);
numbers a[10];
for (i=0; i <10;i++)
{
a[i].randomize(arr,n);
a[i].printArray(arr,n);
// list.push_back(a[i]);
}
return 0;
}
What i am trying to do is is push back the array of object a that contains each list into the list vector such that list[1] would contain {1,0,2,3,0,0,6,5,4} and list[2] would contain another set of numbers.
My question:
how could i push back the array of objects that contain the list of numbers into my vector.
for example:
input:
{1,2,3,4,5,6,0,0,0}
output after printing off the vector
list[0] contains {1,0,2,3,0,0,6,5,4}
list[1] contains {0,0,1,6,0,4,3,5,2}
...
list[9] contains {1,0,2,0,3,4,6,5,0}
A vector cannot be templated with a standard array (such as int a[10]). It can be templated with a pointer (such as int *) and it can be templated with another std::vector.
If you have an array, and you want to store the values of that array in a single index of a vector, you need to copy the elements of the array into the container in the vector. For a std::vector<int*> this looks like this:
std::vector<int*> array_vec;
int numbers[] = {1, 2, 3, 4, 5, 6, 0, 0, 20};
for (std::size_t i = 0; i < 10; i++)
{
int* temp = new int[sizeof(numbers)/sizeof(numbers[0])];
std::copy(&numbers[0], &numbers[9], temp);
array_vec.push_back(temp);
// change numbers so that it's different and we can see that reflected in the output
numbers[8] = i;
}
// print the elements from the vector
for (auto a : array_vec)
{
std::cout << "{ ";
for (std::size_t i = 0; i < 9; i++)
{
std::cout << a[i] << " ";
}
std::cout << "}\n";
}
// we need to delete the memory we allocated
for (auto a : array_vec)
delete[] a;
Note: I do not recommend this method, since it requires the use of new[] and delete[]. There is no reason in modern C++ that you should be manually managing memory like this, especially as a beginner.
The better solution is to use a std::vector<std::vector<int>>. No manual memory management. You take advantage of the std::vector<int> constructor that takes two iterators for int, a start and an end iterator, and emplace_back (instead of push_back):
std::vector<std::vector<int>> vector_vec;
int numbers[] = {1, 2, 3, 4, 5, 6, 0, 0, 20};
for (std::size_t i = 0; i < 10; i++)
{
// create a new std::vector<int> in vector_vec by calling its iterator constructor
vector_vec.emplace_back(numbers, numbers + 9);
numbers[8] = i;
}
// print the elements from the vector
for (auto& v : vector_vec)
{
std::cout << "{ ";
for (auto i : v)
{
std::cout << i << " ";
}
std::cout << "}\n";
}
Note: There is no need now to manually delete[] the memory, since the std::vector manages memory for us.
This answer does not address the issues with the class in your question. That will have to be answered in a different question, if you have one.
If you have questions about the std::vector class, its constructors, or its member functions, please see std::vector.

Make a combination of two arrays to form a pair of each item [duplicate]

This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
How do sizeof(arr) / sizeof(arr[0]) work?
(8 answers)
Closed 3 years ago.
I have two arrays array1 of size 3 and array2 of size 2. I wish to form a pair of each item from both arrays. That is;
int array1[] = {1, 2, 3};
int array2[] = {9, 4};
Results I'm hoping to achieve:
1 , 9
1 , 4
2 , 9
2 , 4
3 , 9
3 , 4
This is what I have tried:
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
int array1[] = {1, 2, 3};
int array2[] = {9, 4};
int arrayOneSize = sizeof(array1);
int arrayTwoSize = sizeof(array2);
for (size_t i = 0; i < arrayOneSize; i++)
{
for (size_t j = 0; j < arrayTwoSize; j++)
{
cout << array1[i] << " , " << array2[j] << endl;
}
}
return 0;
}
But for some reason I am getting a whole bunch of weird combinations like:
1,9
1,4
1,1
1,2
1,3
1,1029505037
1,-531587312
... (It's really long, just want to shorten the results a little)
0,-411331072
1,9
1,4
1,1
1,2
1,3
1,1029505037
1,-531587312
1,-411331072
Sorry for the noob question. I am still new to C++ so, I will gladly appreciate any help. And also why am I getting numbers which are not part of the array?
Thanks in advance.
To get the number of elements in an array, you have to divide its size by the size of an element in it:
int arrayOneSize = sizeof(array1) / sizeof(array1[0]);
int arrayTwoSize = sizeof(array2) / sizeof(array2[0]);
As Jarod42 points out, you can use the range-based for loop for the arrays and bypass finding the size manually all-together.
Alternatively, consider using std::array, or better yet, std::vector. Here's an implementation with modern C++:
#include <iostream>
#include <vector>
int main() {
std::vector vec1{ 1, 2, 3 }; // no need for <int> with C++17
std::vector vec2{ 9, 4 };
for (auto&& e1 : vec1) {
for (auto&& e2 : vec2) {
std::cout << e1 << " , " << e2
<< '\n'; // no need to flush the buffer all the time
}
}
}
The size ( no. of elements in each array) computation of arrays is having the issue.
int arrayOneSize = sizeof(array1);
int arrayTwoSize = sizeof(array2);
This will be number of elements * sizeof(int) which gives the total size. Since you are interested only in number of elements, you should rather do
int arrayOneSize = sizeof(array1)/sizeof(int);
int arrayTwoSize = sizeof(array2)/sizeof(int);
This should give the expected output

how to find 2d array size in c++

How do I find the size of a 2D array in C++? Is there any predefined function like sizeof to determine the size of the array?
Also, can anyone tell me how to detect an error in the getvalue method for arrays while trying to get a value which is not set?
Suppose you were only allowed to use an array, then you could find the size of a 2-D array in the following way.
int ary[][5] = { {1, 2, 3, 4, 5},
{6, 7, 8, 9, 0}
};
int rows = sizeof ary / sizeof ary[0]; // 2 rows
int cols = sizeof ary[0] / sizeof(int); // 5 cols
#include <bits/stdc++.h>
using namespace std;
int main(int argc, char const *argv[])
{
int arr[6][5] = {
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5}
};
int rows = sizeof(arr)/sizeof(arr[0]);
int cols = sizeof(arr[0])/sizeof(arr[0][0]);
cout<<rows<<" "<<cols<<endl;
return 0;
}
Output: 6 5
Use an std::vector.
std::vector< std::vector<int> > my_array; /* 2D Array */
my_array.size(); /* size of y */
my_array[0].size(); /* size of x */
Or, if you can only use a good ol' array, you can use sizeof.
sizeof( my_array ); /* y size */
sizeof( my_array[0] ); /* x size */
sizeof(yourObj)/sizeOf(yourObj[0])
should do the trick
int rows = sizeof(arr)/sizeof(arr[0]);
int cols = sizeof(arr[0])/sizeof(arr[0][0]);
Along with the _countof() macro you can refer to the array size using pointer notation, where the array name by itself refers to the row, the indirection operator appended by the array name refers to the column.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int beans[3][4]{
{ 1, 2, 3, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
cout << "Row size = " << _countof(beans) // Output row size
<< "\nColumn size = " << _countof(*beans); // Output column size
cout << endl;
// Used in a for loop with a pointer.
int(*pbeans)[4]{ beans };
for (int i{}; i < _countof(beans); ++i) {
cout << endl;
for (int j{}; j < _countof(*beans); ++j) {
cout << setw(4) << pbeans[i][j];
}
};
cout << endl;
}
#include<iostream>
using namespace std ;
int main()
{
int A[3][4] = { {1,2,3,4} , {4,5,7,8} , {9,10,11,12} } ;
for(int rows=0 ; rows<sizeof(A)/sizeof(*A) ; rows++)
{
for(int columns=0 ; columns< sizeof(*A) / sizeof(*A[0]) ; columns++)
{
cout<<A[rows][columns] <<"\t" ;
}
cout<<endl ;
}
}
Here is one possible solution of first part
#include<iostream>
using namespace std;
int main()
{
int marks[][4] = {
10, 20, 30, 50,
40, 50, 60, 60,
10, 20, 10, 70
};
int rows = sizeof(marks)/sizeof(marks[0]);
int cols = sizeof(marks)/(sizeof(int)*rows);
for(int i=0; i<rows; i++)
{
for(int j=0; j<cols; j++)
{
cout<<marks[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
The other answers above have answered your first question.
As for your second question, how to detect an error of getting a value that is not set, I am not sure which of the following situation you mean:
Accessing an array element using an invalid index:
If you use
std::vector, you can use vector::at function instead of [] operator
to get the value, if the index is invalid, an out_of_range exception
will be thrown.
Accessing a valid index, but the element has not been set yet:
As far as I know, there is no direct way of it. However, the following
common practices can probably solve you problem: (1) Initializes all elements to a value that you are certain that is impossible to have. For example, if you are dealing with positive integers, set all elements to -1, so you know the value is not set yet when you
find it being -1. (2). Simply use a bool array of the same size to
indicate whether the element of the same index is set or not, this
applies when all values are "possible".
int arr[5][4];
For the row subscript(4 raise to 2, include cmath to use pow):
sizeof(arr1)/pow(4,2)
Column subscript:
sizeof(*arr1)/4
4 means 4 bytes, size of int.
This can also be tried to get the row and column size of a 2-D array
matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
int rows = matrix.size();
int cols = matrix[0].size();
cout<<rows<< " "<<cols;
Ouput:
3 4
There is a standard template to determine sizes of the dimensions of arrays: std::extent_v
#include <type_traits>
#include <iostream>
int main()
{
int a[3][4];
std::cout << "rows:" << std::extent_v<decltype(a), 0> << '\n';
std::cout << "cols:" << std::extent_v<decltype(a), 1> << '\n';
std::cout << "size in bytes:" << sizeof(a) << '\n';
}
Output:
rows:3
cols:4
size in bytes:48

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.