• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

C programming question

Bluga

Banned
As a follow up to this thread, how do i initialize and allocate a two dimentional array? I still can't figure it out. Thanks for any help.

According to FatAlbo's code:


MATRIX *make_a_Matrix(int row, int col)
{
int j;
MATRIX *toReturn = (MATRIX*) malloc(sizeof( MATRIX) ); <== why do we need to allocate MATRIX?

// allocate memory for the elements in the array
toReturn->vals = malloc( sizeof( double ) * row * col );doesn't malloc only allow one argument?

// default everything to 0
for( j = 0; j < ( row * col ); j++ )
{
toReturn->vals[j] = 0;
}

toReturn->Col = col; why do we need to return this?
toReturn->Row = row;

// return the pointer
return toReturn;
}
 
well...

the first one, because if you don't allocate a matrix, you have nothing to work with!

the second one, you are only passing one argument aren't you? i don't see a second one.

the third one, i suspect for convenience, and it doesn't hurt to have one more way of making sure everything is correct.
 
I will explain this code to you since I'm such a C genius(actually, I've never written a C program, but I can explain it 😱 ).

What you are trying to accomplish is to allocate memory for your MATRIX. Thus, you first create memory for the actual MATRIX itself. You do this by calling malloc, with the size of MATRIX(in bytes). malloc then returns a pointer, which you cast to a MATRIX pointer (by doing (MATRIX*) ). You set your toReturn MATRIX pointer to the pointer returned by malloc.

Then, you also have to allocate memory for the elements in MATRIX--all the rows and cols. You do this by calling malloc, passing the size of row * col (which are doubles) as an argument, and setting the pointer vals to this.

Third--you set each element in vals equal to 0.



<<
toReturn->Col = col; why do we need to return this?
>>



You don't return this. This simply says the same as:

(*toReturn).Col = col;

You're basically setting the Col and Row in the MATRIX that you return.

Finally, you return the pointer to the MATRIX you just created.
 
I do NOT recommend that you do work with dynamic 2D arrays since you do not seem to know how to deal with them. But if you want to know, then I've dug up some old code I have used in the past.

/* Suppose that you want a 2D array of type double
* Declare your array pointer as such:
*/
double **pData;



/* Now, how to allocate it? Like so: */


/* Dynamically Allocate memory for the matrix */
double **DynAllocateMatrix(int rows, int cols)
{
double **pData;

/* First allocate the row pointers */
pData = new double* [rows];

/* Now allocate the column memory */
for(int x=0;x<rows;x++)
pData[x] = new double[cols];

return pData;
}


Essentially, we allocate pointers for ROWS of the matrix, and then make them point to the columns.

To use the Allocation function:

double **pData = DynAllocateMatrix(#ofrows, #ofcols);


To DELETE the Matrix:
void DeleteMatrix(double **pData, int rows, int cols)
{
/* Delete the cols */
for(int r=0;r<rows;r++)
delete pData[r];

/* Delete the rows */
delete pData;
}


To USE the Matrix:
double value = pData[row][col];

To set a value at a row, col, just do the opposite: pData[row][col] = value;


You have to deal with error checking, but I wouldn't bother unless you're runnin on a 16-bit system or allocating lots of memory.

Edit: Correction
 


<< I do NOT recommend that you do work with dynamic 2D arrays since you do not seem to know how to deal with them. But if you want to know, then I've dug up some old code I have used in the past. >>




Thanks for all the replies.

Here's my major problem:

For this problem, the user can specify arbitrary rows and columns of the matrix, for example 6x9, my major headache is why do i need to use dynamic allocation? I think i might be confused with "DECLRATION" and "ALLOCATION" of arrays

eg.

DECLARATION: A[row][col]

doesn't this allocate the array already?

why can't i put this in MATRIX function?

 


<<

Thanks for all the replies.

Here's my major problem:

For this problem, the user can specify arbitrary rows and columns of the matrix, for example 6x9, my major headache is why do i need to use dynamic allocation?
>>




Yes, but then you don't need dynamic *2D* arrays, you can do with only *1D* dynamic arrays (which are a lot simpler to deal with). Do you know what the difference is?
 


<< Yes, but then you don't need dynamic *2D* arrays, you can do with only *1D* dynamic arrays (which are a lot simpler to deal with). Do you know what the difference is? >>



I'm doing LU factorization so i guess i need 2D arrays.
 


<< I'm doing LU factorization so i guess i need 2D arrays. >>



I'm afraid that you don't understand. Would a small demonstration program help?
 
Here's the actual codes, we are asked to implement the functions, that's why i have to stuck with what is given below.

=============================================================================


#include <stdlib.h>
#include <stdio.h>

/* This header file contains the function prototypes;
you will have to provide the function(s) itself in
matrix.c.
*/

#include "matrix.h"

void print_matrix(MATRIX *mat);


#ifndef _MATRIX_H_
#define _MATRIX_H_

typedef struct Matrix {

int Col, Row; /* number of columns/rows */

double *vals; /* values of the matrix */

} MATRIX;

/* returns the value at ith row and jth column
We assume that the left-most element in the
top row is in the first row and the first column. */

double get_val(MATRIX *mat, int i, int j);

/* sets the value at (row)th row and (col)th column to be val
We assume that the left-most element in the
top row is in the first row and the first column. */

void set_val(MATRIX *mat, int row, int col, double val)



/* allocates the memory for a matrix with 'row' rows and 'col' columns */

MATRIX *make_a_Matrix(int row, int col) <=== My problem here



/* frees the memory */

void free_Matrix(MATRIX *mat);


/* finds the LU factorization of A.
returns 1 if A is factorizable; otherwise,
returns 0 */

int LU_factorize(MATRIX *A, MATRIX *L, MATRIX *U)

/* solves a LU factorized equation LUx=B;
accepts L, U and B as arguments; returns x, which is dynamically
allocated in the subroutine. NOTE: You can assume that L and U are proper lower/upper triangular
matrices and the equation LUx=B always has a solution. */

MATRIX *solve_eqn(MATRIX *L, MATRIX *U, MATRIX *B);


/* Do not add any more code here. You can add your own function
declarations at the beginning of the matrix.c file.
*/


#endif

/////////////////////////////////
//
////////////////////////////////
//
//
////////////////////////////////

int main()
{
MATRIX *A, *B, *X;
MATRIX *L, *U;
int row, col; //num of rows and columns for A
int i,j;
double temp;
char temp_str[257];


while(gets(temp_str)) {

sscanf(temp_str, "%d%d", &row, &col);

/* allocate the matrices */
A=make_a_Matrix(row, col); <== alllocation function
B=make_a_Matrix(row, 1);
L=make_a_Matrix(row,col);
U=make_a_Matrix(row,col);
/* X is not allocated here */

for (i=1; i<=row; i++)
for (j=1; j<=col; j++) {
gets(temp_str);
sscanf(temp_str, "%lg", &temp);
set_val(A, i, j, temp);
};

for (i=1; i<=row; i++) {
gets(temp_str);
sscanf(temp_str, "%lg", &temp);
set_val(B, i, 1, temp);
};

if (LU_factorize(A, L, U)==0) {
/* failed to LU factorize */
printf("Can't factorize\n");
} else {
/* solves the equation and prints out the values */
p
printf("U is:\n");
print_matrix(U);
X=solve_eqn(L, U, B);
printf("X is:\n");
print_matrix(X);

/* collects memory */
free_Matrix(X);
};

/* collects memory */
free_Matrix(A); free_Matrix(B);
free_Matrix(L); free_Matrix(U);
};

exit(0);

};

/* prints a matrix to stdout */
void print_matrix(MATRIX *mat)
{
int i,j;

/* does nothing if the pointer is NULL */
if (mat==NULL)
return;

for (i=1; i<=mat->Row; i++) {
for (j=1; j<=mat->Col; j++)
printf("%10.2f",get_val(mat, i, j));
printf("\n");
};

return;
};
 


<< Is this supposed to be in pure C (it's easier with C++)? >>



yes unfortunately i have to implement it in pure C.
 
For the skeleton then, FatAlbo's code will work. I've taken his code structure, and added some comments. Hope this helps:

(** Anyone know how to make the formatting stay as typed? **)

MATRIX *make_a_Matrix(int row, int col)
{
int counter;
MATRIX *pMatrix; /* This will point to the data structure we will return */

/* FIRST, we have to allocate the MATRIX data structure
* that holds the matrix information. Essentially, we
* allocate the bytes we need by computing the size
* of the structure
*/
pMatrix = (MATRIX *)malloc(sizeof(MATRIX));

if(!pMatrix)
{
/* Memory alloc. failed */
return NULL;
}

/* Within the MATRIX data structure we set the rows and cols
* so that we know how big the matrix is. This is because
* we do not know the size.
*/
pMatrix->Col = col;
pMatrix->Row = row;


/* Allocate the matrix. malloc() will allocate in BYTES. The
* number of bytes is equal to:
*
* bytes = bytes_per_double_number * number_of_cols * number_of_rows
*/
pMatrix->vals = (double*)malloc(sizeof(double) * row * col);
if(!pMatrix->vals)
{
/* Memory alloc. failed */
free(pMatrix);
return NULL;
}

/* Initialize our array with 0's */
for(counter = 0; counter < (row * col); counter++)
{
pMatrix->vals[counter] = 0.0;
}

/* Everything OK */
return pMatrix;
}
 
In case NULL is not defined, you can add this:

/* In-case NULL is not defined, it's just a zero */
#ifndef NULL
#define NULL 0
#endif

 
Hi Thank you very much for you help.

I still don't understand this part:


/* Allocate the matrix. malloc() will allocate in BYTES. The
* number of bytes is equal to:
*
* bytes = bytes_per_double_number * number_of_cols * number_of_rows
*/
pMatrix->vals = (double*)malloc(sizeof(double) * row * col);

why there's "*" sign in front of row and col? and doesn't pMatrix->vals assigns a pointer to val? why is it used in allocating the matrix?

As for this :

/* Initialize our array with 0's */
for(counter = 0; counter < (row * col); counter++)
{
pMatrix->vals[counter] = 0.0;
}

could i use:

for(k = 0; k < row; i++)
for(j = 0; j < col; j++)
{
pMatrix [k][j] = 0.0;
}


Thanks again.
 
Back
Top