I have a problem which includes pointers and two-dimensional arrays.
I've got a struct, which looks something like this:
typedef struct {
int row;
int col;
int **a;
} TEST;
Now I want to use an object of that type for other functions. But i'm having problems passing an two-dimensional array to an object of the type.
For example i tried this:
int main(int argc, char * argv[]){
//Just to fill an array with some integers
int rows = 3;
int cols = 3;
int a[rows][cols];
srand(time(NULL));
for (int x = 0; x < rows; x++){
for (int y = 0; y < cols; y++){
a[x][y] = rand() % 10 + 1;
}
}
TEST * t = (TEST *) calloc(1,sizeof(TEST));
t->row = rows;
t->col = cols;
t->a = a;
return 0;
}
How can I do this properly?
I'm thankful for any help.
If you need to allocate a TEST object dynamically then you can do this:
int main(int argc, char * argv[])
{
//Just to fill an array with some integers
int rows = 3;
int cols = 3;
TEST* t = new TEST;
t->row = rows;
t->col = cols;
t->a = new int*[rows];
for(int i = 0; i < rows; i++)
t->a[i] = new int[cols];
srand(time(NULL));
for (int x = 0; x < rows; x++){
for (int y = 0; y < cols; y++){
t->a[x][y] = rand() % 10 + 1;
}
}
return 0;
}
Related
So I got a function which creates me 2D array and fill it with test data.
Now I need to assign the pointer to an array
//Fill matrix with test data
int *testArrData(int m, int n){
int arr[n][m];
int* ptr;
ptr = &arr[0][0];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
*((ptr+i*n)+j) = rand()%10;
}
}
return (int *) arr;
}
int arr[m][n];
//Algorithm - transpose
for (int i = 0; i < m; i++){
for (int j = 0; j < n; j++){
arrT[j][i] = arr[i][j];
}
}
Is there any way of doing this?
There are at least four problems with the function.
//Fill matrix with test data
int *testArrData(int m, int n){
int arr[n][m];
int* ptr;
ptr = &arr[0][0];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
*((ptr+i*n)+j) = rand()%10;
}
}
return (int *) arr;
}
First of all you declared a variable length array
int arr[n][m];
Variable length arrays are not a standard C++ feature.
The second problem is that these for loops
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
*((ptr+i*n)+j) = rand()%10;
}
}
are incorrect. It seems you mean
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
*((ptr+i*m)+j) = rand()%10;
}
}
You are returning a pointer to a local array with automatic storage duration that will not be alive after exiting the function. So the returned pointer will be invalid.
And arrays do not have the assignment operator.
Instead use the vector std::vector<std::vector<int>>. For example
std::vector<std::vector<int>> testArrData(int m, int n){
std::vector<std::vector<int>> v( n, std::vector<int>( m ) );
for ( auto &row : v )
{
for ( auto &item : row )
{
item = rand() % 10;
}
}
return v;
}
This is how I would accomplish this. I agree with int ** because it is easy to understand if you dont know how to use vectors. Also, the rand() can cause trouble if you are using the result to index an array. Make sure to use abs(rand() % number) if you don't want negative numbers.
I've updated the answer due to some vital missing code.
// This method creates the overhead / an array of pointers for each matrix
typedef int* matrix_cells;
int **create_row_col_matrix(int num_rows, int num_cols, bool init_rnd)
{
num_rows = min(max(num_rows, 1), 1000); // ensure num_rows = 1 - 1000
num_cols = min(max(num_cols, 1), 1000); // ensure num_cols = 1 - 1000
int *matrix_total = new int[num_rows*num_cols];
// overhead: create an array that points to each row
int **martix_row_col = new matrix_cells[num_rows];
// initialize the row pointers
for (int a = 0; a < num_rows; ++a)
{
// initialize the array of row pointers
matrix_row_col[a] = &matrix_total[num_cols*a];
}
// assign the test data
if (init_rnd)
{
for (int run_y = 0; run_y < num_rows; ++run_y)
{
for (int run_x = 0; run_x < num_cols; ++run_x)
{
matrix_row_col[run_y][run_x] = abs(rand() % 10);
}
}
}
return matrix_row_col;
}
int src_x = 7, dst_x = 11;
int src_y = 11, dst_y = 7;
int **arr_src = create_row_col_matrix(src_y, src_x, true);
int **arr_dst = create_row_col_matrix(dst_y, dst_x, false);
for (int a = 0; a < dst_y; ++a)
{
for (int b = 0; b < dst_x; ++b)
{
arr_dst[a][b] = arr_src[b][a];
}
}
delete matrix_src[0]; // int *matrix_total = new int[src_y*src_x]
delete matrix_src; // int **matrix_row_col = new matrix_cell[src_y]
delete matrix_dst[0]; // int *matrix_total = new int[dst_y*dst_x]
delete matrix_dst; // int **matrix_row_col = new matrix_cell[dst_y]
// the overhead is matrix_src and matrix_dst which are arrays of row pointers
// the row pointers makes it convenient to address the cells as [rown][coln]
I figured out how to make this one work already but can't explain in details what is so different in these two codes here.
Incorrect code:
const int nRows = 2;
const int nCols = 2;
int * colSum (int [nRows][nCols]);
int * rowSum (int [nRows][nRows]);
int main() {
int my2Darray[nRows][nCols] = {{10, 20}, {30, 40}};
int totalsByColumn[nCols] = {};
*totalsByColumn = *(colSum(my2Darray));
for (int i = 0; i < nCols; i++) {
cout << totalsByColumn[i] << endl;
}
}
int * colSum (int arrayArg[nRows][nCols]) {
static int arr[nRows] = {};
for (int i = 0; i < nCols; i++) {
for (int rowcount = 0; rowcount < nRows; rowcount++) {
arr[i] += arrayArg[rowcount][i];
}
}
return arr;
}
I was getting 40 0 as the output.
Then I fixed it by doing this:
int main() {
int my2Darray[nRows][nCols] = {{10, 20}, {30, 40}};
int *totalsByColumn = colSum(my2Darray);
for (int i = 0; i < nCols; i++) {
cout << totalsByColumn[i] << endl;
}
}
Output is 40 60, just what I wanted.
Was I just decaying to the first element of totalsByColumn by using the dereference operator on my first block of code? I feel like there might be a quicker way of adding the columns and rows together and assigning them to arrays in the main function, but as long as it does what I want I'm okay with that for the moment.
Was I just decaying to the first element of totalsByColumn by using the dereference operator on my first block of code?
Yes.
I feel like there might be a quicker way of adding the columns and rows together
Certainly. Also ways that are thread safe unlike your solution. A simple way is to use an output iterator to write directly to the array where you want the results:
int* colSum (int arrayArg[][nCols], int out[]) {
for (int i = 0; i < nCols; i++) {
out[i] = 0;
for (int rowcount = 0; rowcount < nRows; rowcount++) {
out[i] += arrayArg[rowcount][i];
// ...
int totalsByColumn[nCols];
colSum(my2Darray, totalsByColumn);
I just create a simple function which takes the 2-D char array as an argument and then just print the values of that 2-D char array.
The function is given below
void final_output(char arr[][200]){
int i, j;
for(i = 0; i < r; i++){
for(j = 0; j < c; j++){
cout << arr[i][j];
}
}
}
And i call this function as
final_output(grid_2);
But i face an error
error: cannot convert 'char (*)[c]' to 'char (*)[200]' for argument '1' to 'void final_output(char (*)[200])'
final_output(grid_2);
I search for different methods to pass the 2-D array as an argument to a function but i try all of them and they give the same type of error. Please anyone help me out to remove this error. Actually i use this function in this problem of hackerrank.
It is a strange function but it works for me assuming you define r and c, and the grid2 is an char[][200].
void final_output(char arr[][200]) {
int i, j;
int r = 10;
int c = 200;
for (i = 0; i < r; i++) {
for (j = 0; j < c; j++) {
cout << arr[i][j];
}
}
}
int main(int argc, char* argv[])
{
char arr[10][200];
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 200; j++) {
arr[i][j] = 'a';
}
}
final_output(arr);
//it prints aaaaaaaa
}
I you want a method to be valid for any matrix since you need to use char**. I is more cumbersome because if you are using pointers, but it is more flexible.
void final_output(char** arr, int nrow, int ncol) {
for (int i = 0; i < nrow; i++) {
for (int j = 0; j < ncol; j++) {
cout << arr[i][j];
}
}
}
int main(int argc, char* argv[])
{
//construct the matrix (any size would work)
int nrow = 10;
int ncol = 20;
char** arr = new char* [nrow];
for (int i = 0; i < nrow; i++){arr[i] = new char[ncol];}
//assign values
for (int i = 0; i < nrow; i++) {
for (int j = 0; j < ncol; j++) {
arr[i][j] = 'a';
}
}
final_output(arr,nrow,ncol);
}
I'm currently reading Jumping into C++ by Alex Allain and am stuck on Chapter 14's Practice Problem number 1.
Write a function that builds a two-dimensional multiplication table with arbitrary sizes for two dimensions.
I'm having trouble actually assigning the times table to the array but all these nested loops are giving me a headache! I'm getting an output of "999999999".
My Code:
#include <iostream>
using namespace std;
int main()
{
int **p_p_tictactoe;
p_p_tictactoe = new int*[3];
for (int i = 0; i < 3; i++)
p_p_tictactoe[i] = new int[3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
p_p_tictactoe[i][j] = 1;
for (int y = 0; y < 4; y++)
{
for (int t = 0; t < 4; t++)
{
p_p_tictactoe[i][j] = y * t;
}
}
cout << p_p_tictactoe[i][j];
}
}
cin.get();
for (int i = 0; i < 3; i++)
delete[] p_p_tictactoe[i];
delete[] p_p_tictactoe;
}
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;
}