I have a dynamically allocated 2d array and would like to loop through it with pointer arithmetic because I won't know the number of rows and number of cols before runtime.
I know how to do this with a 1d array:
int *arr = new int[size];
and to loop through it:
for (int *i = arr; i < arr + arr.size(); i++){
*i = 20; //sets all elements to 20
}
However, it's at the 2d level that I get stuck.
Here's what I have so far:
int **arr = new int *[row];
for(int i = 0; i<row; i++)
arr[i] = new int[col];
To loop through all values:
for(int **i=arr; i < arr + row; i++){
for(int *j=*i; j < j + col; j++){
*j = 20; // set all values to 20
}
}
The second loop is obviously incorrect, I just don't know what else to try.
You should do the same thing to j as you did to i.
for(int **i=arr; i < arr + row; i++){
for(int *j=*i; j < *i + col; j++){
*j = 20; // set all values to 20
}
}
Related
What is the fastest way to convert a 2D memory allocation to a 1D vector? Right now, I am using nested loops to do it by referring each value at a time. Would it be possible use memcpy or copy to gain speed? I have the following:
Ipp32f* datamem = ippiMalloc_32f_C1(size0, size1, &(steps));
Ipp32f* datamem2 = ippiMalloc_32f_C1(size0, size1, &(steps)); s
std::vector<double> result(2*size0*size1);
int count = 0;
for (int i = 0; i < 1; i++){
for (int j = 0; j < size0; j++){
for(int k = 0; k < size1; k++){
Ipp32f* pointer = (Ipp32f)((Ipp8u*)datamem + steps * k + sizeof(Ipp32f) * j);
result[count] = *pointer;
count++;
}
}
}
for (int i = 1; i < 2; i++){
for(int j = 0; j < size0; j++){
for(int k = 0; k < size1; k++){
Ipp32f* pointer = (Ipp32f)((Ipp8u*)datamem2 + step * k + sizeof(Ipp32f) * j);
result[count] = *pointer;
count++;
}
}
}
This code creates a vector where each index are referenced by a number store in datamem and datamem2. Is there a better way to this?
So i keep trying to transfer the elements but it keeps giving me repeated elements, it fails to properly copy the 2D array onto a 1D vector
// This was one of my attempts
vector<int> rando(int rowsize, int columnsize)
{
int elements = rowsize*columnsize;
vector<int> x(elements);
int matrix[100][100];
for(int i = 0; i < rowsize; i++)
{
for(int j = 0; j < columnsize; j++)
{
srand((int)time(0));
matrix[i][j]= -10 + rand() % 21;
for(int n=0; n < elements; n++)
x[n]=matrix[i][j];
}
// Ive also tried this
for(int n=0; n < elements; n++)
{
for(int i = 0; i < rowsize; i++)
{
for(int j = 0; j < columnsize; j++)
{
x[n]=matrix[i][j];
}
}
}
}
return x;
}
Why do you want to store data into the matrix first and copy it into the vector afterwards? Use the vector from the start.
std::vector<int> rando(std::size_t rowsize, std::size_t columnsize)
{
std::vector<int> v(rowsize*columnsize);
std::mt19937 mt{std::random_device{}()};
std::uniform_int_distribution<int> rand_dist(-10, 10);
for (auto & e : v) e = rand_dist(mt);
return v;
}
If you want to transfer data from a matrix into a vector you must calculate the proper index or just increment a single variable as Thomas Matthews suggests.
constexpr std::size_t n = 100, m = 100;
int matrix[n][m];
// do stuff with matrix
std::vector<int> v(n*m);
for (std::size_t i=0; i<n; ++i)
{
for (std::size_t j=0; j<m; ++j)
{
v[i*m + j] = matrix[i][j];
}
}
THe general copy should loop through the 2 dimensions, and just increment the target index at each iteration (no third nested loop):
int n=0;
for(int i = 0; i < rowsize; i++)
{
for(int j = 0; j < columnsize; j++)
{
...
x[n++]=matrix[i][j]; // not in an additional for loop !!
}
} // end of initialisation of matrix
If your matrix is a 2D array (i.e. contiguous elements) you can also take the following shortcut using <algorithm>:
copy (reinterpret_cast<int*>(matrix), reinterpret_cast<int*>(matrix)+elements, x.begin());
Try this:
unsigned int destination_index = 0;
for(int i = 0; i < rowsize; i++)
{
for(int j = 0; j < columnsize; j++)
{
x[destination_index++]=matrix[i][j];
}
}
The destination index is incremented after each assignment to a new slot.
No need for a 3rd loop.
It is enough to use two loops.
For example
srand((int)time(0));
for(int i = 0; i < rowsize; i++)
{
for(int j = 0; j < columnsize; j++)
{
matrix[i][j]= -10 + rand() % 21;
x[i * columnsize + j] = matrix[i][j];
}
}
In general if you have a two-dimensional array and want to copy nRows and nCols of each row elements in a vector then you can use standard algorithm std::copy declared in header <algorithm>
For example
auto it = x.begin();
for ( int i = 0; i < nRows; i++ )
{
it = std::copy( matrix[i], matrix[i] + nCols, it );
}
I keep getting the error Heap Corruption Detected. I have read through several questions on here, but I can't quite find out what is causing this in my code. I am trying to create a 2d array that will hold a matrix that is read from a text file.
// Create a 2d matrix to hold the matrix (i = rows, j = columns)
matrix = new int*[cols];
for(int i = 0; i <= cols; i++) {
matrix[i] = new int[rows];
}
// Populate the matrix from the text file
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
inputFile >> matrix[i][j];
}
}
My destructor is:
for(int i = 0; i <= cols; i++) {
delete[] matrix[i];
}
delete[] matrix;
I've tried debugging, but that does do much help in this case. Any suggestions?
matrix = new int*[cols];
for(int i = 0; i <= cols; i++) {
matrix[i] = new int[rows];
}
For an array with cols elements, the index is from 0 to cols - 1 inclusively.
The heap corruption will be detected when
delete [] matrix;
Since matrix[cols] write a position out of array bound.
UPDATE
As #DanielKO (thank you buddy :p) pointed out in the comment
there is a mismatch, the "Populate the matrix..." loop makes "i"
iterate over "rows" when it should be iterating over "cols".
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
inputFile >> matrix[i][j];
When you allocated you went from 0 to cols in i. Now you're changing i to be rows.
EDIT: Below would honor your commented row/column rules and follow RAII:
std::vector<std::vector<int>> matrix(rows, std::vector<int>(cols));
for( int i=0; i<rows; ++i ) {
for( int j=0; j<cols; ++j ) {
inputFile >> matrix[i][j];
}
}
// no need for delete matrix cleaned up when leaving scope.
This is my program in C++, which accepts an 2D array a[m][n]. If an element a[i][j] is zero, then set all the ith row and jth column elements to zero.
This is code sample:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
class SetZero{
public:
static void setZero(int **, int , int);
};
void SetZero::setZero(int ** a, int m, int n){
int i, j, k;
int ** b = new int *[m]; //flags to identify whether set to zero or not.
for(i = 0; i < m; i++){
b[i] = new int[n];
for(j = 0; j < n; j++)
b[i][j] = 1;
}
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
if(a[i][j] == 0 && b[i][j]){//DUMP here. If I change it to (a+i)[j], then works.
for (k = 0; k < n; k++){
a[i][k] = 0;//but there is NO dump here. Weird!
b[i][k] = 0;
}
for(k = 0; k < m; k++){
a[k][j] = 0;
b[k][j] = 0;
}
j = n;//break. next row loop.
}
for(int i = 0; i < m; i++)
delete[] b[i];
delete[] b;
}
int main(){
int a[4][5];
srand(time(NULL));
for(int i = 0; i < 4; i++){//create an 2D array
for(int j = 0; j < 5; j++){
a[i][j] = rand() % 100;
cout << a[i][j] << " ";
}
cout << endl;
}
SetZero::setZero((int **)a, 4, 5);//type cast.
cout << endl;
for(int i = 0; i < 4; i++){//print result
for(int j = 0; j < 5; j++)
cout << a[i][j] << " ";
cout << endl;
}
return 0;
}
Environment: WIN8 Visual Studio 2012.
Edit:
The program can compile but cannot execute normally. It will stop when it reaches if(a[i][j] == 0 && b[i][j]){
The error message is:
Unhandled exception at 0x012875DD in CCLC.exe: 0xC0000005: Access
violation reading location 0x0000004B.
SetZero::setZero((int **)a, 4, 5)
a is not an array of pointers, it is simply a 2 dimensional array.
notice how the access violation is reading address 0x0000004B? that's 75, a number between 0 and 99 :) because you are treating a 2 dimensional array (which is just a one dimensional array with a neat way of accessing it) as an array of arrays, it is taking one of the values in your array (75) to be the address of a sub array, then trying to read the non existent array at address 75 (or 0x0000004B)
I suggest that you 'flatten' your arrays and work with them as one dimensional arrays, which I find simpler:
void SetZero::setZero(int * a, int m, int n){
int i, j, k;
int * b = new int [m*n]; //flags to identify whether set to zero or not.
for(i = 0; i < m; i++){
b[i] = new int[n];
for(j = 0; j < n; j++)
b[i*n+j] = 1;
}
for(i = 0; i < m; i++)
for(j = 0; j < n; j++)
if(a[i*n+j] == 0 && b[i*n+j]){//DUMP here. If I change it to (a+i)[j], then works.
for (k = 0; k < n; k++){
a[i*n+k] = 0;//but there is NO dump here. Weird!
b[i*n+k] = 0;
}
for(k = 0; k < m; k++){
a[k*n+j] = 0;
b[k*n+j] = 0;
}
j = n;//break. next row loop.
}
delete[] b;
}
int main(){
int a[4*5];
srand(time(NULL));
for(int i = 0; i < 4; i++){//create an 2D array
for(int j = 0; j < 5; j++){
a[i*5+j] = rand() % 100;
cout << a[i*5+j] << " ";
}
cout << endl;
}
SetZero::setZero(a, 4, 5);//type cast.
cout << endl;
for(int i = 0; i < 4; i++){//print result
for(int j = 0; j < 5; j++)
cout << a[i*5+j] << " ";
cout << endl;
}
return 0;
}
One suggestion about the SetZero(). There is a function called memset() which allows you to set all bytes to a specific value given a starting pointer and the range. This function could make your SetZero() function more cleaner:
void * memset ( void * ptr, int value, size_t num );
Fill block of memory. Sets the first num bytes of the block of memory pointed by ptr to the specified value (interpreted as an unsigned char).
Parameters
ptr: Pointer to the block of memory to fill.
value: Value to be set. The value is passed as an int, but the function fills the block of memory using the unsigned char conversion of this value.
num: Number of bytes to be set to the value, size_t is an unsigned integral type.
For example, the following code block from your program:
for (k = 0; k < n; k++){
a[i][k] = 0;//but there is NO dump here. Weird!
b[i][k] = 0;
}
can be achieved by memset in a cleaner way:
memset(a[i], 0, n * sizeof(int));
memset(b[i], 0, n * sizeof(int));
I have a float** array that contains num_rows rows and num_cols columns. I'd like to determine the number of occurrences of every number between 0-9 columnwise. To do this, I thought of using another 2D array of size [10][num_cols], so that for each column the number corresponding to an element is the number of occurrences of that number in the original table.
Example: if the original table contains 1 2 3 1 1 in the fifth column, then in the second column, the values should be like: 1-> 3, 2 -> 1, 3 -> 1.
I tried using the function as follows, but it gives me a pointer error. I tried using vectors but that too brings no luck.
int ** attribute_count(float * * input, int row_num, int col_num) {
int ** arr_2 = new int * [10];
int * arr = new int[10 * col_num];
int counter = 0;
for (int i = 0; i < 9; i++) {
for (int j = 0; j < col_num; j++) {
arr_2[i][j] = 0;
}
}
for (int i = 0; i < 9; i++) {
for (int j = 0; j < col_num; j++) {
int temp = input[i][j];
arr_2[temp][j]++;
}
}
return arr_2;
}
EDIT:
I tried your suggestions. The new code is:
int** attribute_count(float** input, int row_num, int col_num) {
int** arr_2 = new int* [10];
int* arr = new int[10 * col_num];
int counter = 0;
for (int i = 0; i < 11; i++) {
for (int j = 0; j < col_num; j++) {
arr_2[i] = new int[col_num];
}
}
for (int i = 0; i < 11; i++) {
for (int j = 0; j < col_num; j++) {
int temp = input[i][j];
arr_2[temp][j]++;
}
}
return arr_2;
}
This still gives me memory errors. The function is being called in the .cpp like this:
int** attr = attribute_count(training_data, 10, num_cols_train);
cout<<attr[5][1];
Any idea what I'm doing wrong even now?
I think your problem is in incorrect allocation of the 2D array. Try
int ** arr_2 = new int* [row_num];
for (int i = 0; i < row_num; i++)
arr_2[i] = new int[col_num];
You've only allocated one dimension of arr_2. You need to loop through and allocate an array of ints on each one to get the 2nd dimension.
EDIT: Also, what's up with arr? You allocate it, never use it, don't return it, and don't deallocate it. That's how we spell memory leak.
arr_2 is defined and allocated as an array of pointers to int, but you don't actually assign/allocate those pointers.
Here's a stab at correcting your code - however I'm not convinced you have rows and columns the right way around...
int ** attribute_count(float ** input, int row_num, int col_num)
{
int ** arr_2 = new int * [10];
for (int i = 0; i < 10; i++)
{
arr_2[i] = new int[col_num];
for(int j = 0 ; j < col_num ; j++)
{
arr_2[i][j] = 0;
}
}
for (int i = 0; i < row_num; i++)
{
for (int j = 0; j < col_num; j++)
{
int temp = input[i][j];
arr_2[temp][j]++;
}
}
return arr_2;
}