dynamically allocate a multidimensional array

X

xhunga

I have try a new version of my work.
I have put the sizes of the matrix into the matrix.

A[0][0] = number of rows
A[0][1] = number of columns

The first element of the matrix is A[1][1]
instead of A[0][0].

You can not use the row 0, and the column 0.

I have try with the matrix 1x1, it seems correct.

I have write the add_mR() and mul_mR() with
this type of matrices, it seems correct.

Is it a good idea ?

You can see the code below.

Thank

/* http://groups.yahoo.com/group/mathc/ */
/* ---------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
/* ---------------------------------------- */
#define C1 1
/* -----------------------------------------
Do : print matrix A.
----------------------------------------- */
void p_mR(
double **A
)
{
int r;
int c;

for (r=1; r<A[0][0]; r++)
{
printf("\n");
for (c=1; c<A[0][1]; c++)

printf(" %5.0f ", A[r][c]);
}
printf("\n");
}

/* -----------------------------------------
Do : copy A into B.
------------------------------------------- */
void c_mR(
double **A,
double **B
)
{
int r;
int c;

for (r=1; r<A[0][0]; r++)
for (c=1; c<A[0][1]; c++)

B[r][c] = A[r][c];
}

/* ----------------------------------------
Do : Dynamically allocate a multidimensional array.

(see : FAQ of the comp.lang.c group)

You can keep the array's contents contiguous,

r1 r2 ... rn
xxxx|xxxx|...|xxxx
------------------------------------------- */
double **i_mR(
int r,
int c
)
{
double **A;
int ar;
int ac;
int i;

if(r<1||c<1)
{
printf(" The size of the matrix must be positives
integers.\n\n");
printf(" double **i_mR(); \n\n");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}

ar = r + C1;
ac = c + C1;

A = malloc(ar * sizeof(*A));
if(!A)
{
printf(" I was unable to allocate the memory you
requested.\n\n");
printf(" double **i_mR(); \n\n");
printf(" **A = malloc(ar * sizeof(*A));\n\n");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}

A[0] = malloc(ar * ac * sizeof(**A) );
if(!A[0])
{
printf(" I was unable to allocate the memory you
requested.\n\n");
printf(" double **i_mR();\n\n");
printf(" A[0] = malloc(ar * ac * sizeof(**A) );\n\n");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}

for(i=1; i<ar; i++) A = A[0]+i*ac;

A[0][0]=ar;
A[0][1]=ac;

return(A);
}

/* ------------------------------
Do : free the arrays when they are no longer needed
---------------------------- */
void f_mR(
double **A
)
{
free(A[0]);
free(A);
}

/* --------------------------------- MAIN */
int main()
{
int i;
int j;
int n;
int r;
int c;

double **A;
double **B;
/*------------------------- INITIALISATION */
r = 3;
c = 5;

A = i_mR(r,c);
B = i_mR(r,c);
/*-------------------------------- PROGRAM */

for (i=1,n=1; i<A[0][0]; i++)
for (j=1; j<A[0][1]; j++)

A[j]=n++;

printf(" A : \n");
p_mR(A);

printf("\n");
c_mR(A,B);

printf(" B : \n");
p_mR(B);

f_mR(A);
f_mR(B);

printf("\n Press Return to continue");
getchar();

return 0;
}
 
M

Michael Mair

xhunga said:
I have try a new version of my work.
I have put the sizes of the matrix into the matrix.

A[0][0] = number of rows
A[0][1] = number of columns

I would have expected symmetry:
A[1][0] and A[0][1]
The first element of the matrix is A[1][1]
instead of A[0][0].

You can not use the row 0, and the column 0.

There are some problems with this kind of approach:
- Obviously, you waste a row and a column for every
matrix -- for no real advantage.
If you want to have 1 based indexing, then there are
other ways to get it.
- If the type of A[0][0] or A[0][1] cannot hold all
possible row or column numbers, then you may run into
subtle trouble, especially for floating point types.
- If someone forgets about the 1-basedness, your row
and column numbers can be corrupted.
I have try with the matrix 1x1, it seems correct.

I have write the add_mR() and mul_mR() with
this type of matrices, it seems correct.

Is it a good idea ?

Not necessarily.
/* ---------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
/* ---------------------------------------- */
#define C1 1
/* -----------------------------------------
Do : print matrix A.
----------------------------------------- */
void p_mR(
double **A
)

Why not call the function printMatrix() (or prtMat(), if the six
character limit is hard for you)?
It is good to have a comment for the function but if the
comment is necessary because the function name is too cryptic,
then something is wrong...
{
int r;
int c;

for (r=1; r<A[0][0]; r++)
{
printf("\n");
for (c=1; c<A[0][1]; c++)

printf(" %5.0f ", A[r][c]);

%g often is superior to %f for large or small values.

Note: For one based iteration, one usually expects
for (c = 1; c <= columns; c++)
instead of
for (c = 1; c < columnsPlusOne; c++)
printf("\n");
}

/* -----------------------------------------
Do : copy A into B.
------------------------------------------- */
void c_mR(
double **A,
double **B
)

Once again:
copyMatrix (double **Source, double ** Destination)

In addition, you forgot to make sure that row and column
numbers are identical. I'd rather return an int indicating
whether the operation was successful or not.

/* ----------------------------------------
Do : Dynamically allocate a multidimensional array.

(see : FAQ of the comp.lang.c group)

You can keep the array's contents contiguous,

r1 r2 ... rn
xxxx|xxxx|...|xxxx

Actually, in your case this is wrong:
rc0000|0xxxxx|0xxxxx|....|0xxxxx
would be more apt.
------------------------------------------- */
double **i_mR(
int r,
int c
)
{
double **A;
int ar;
int ac;
int i;

if(r<1||c<1)
{
printf(" The size of the matrix must be positives
integers.\n\n");
printf(" double **i_mR(); \n\n");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}

Your indentation is strange, to say the least. In this case,
it gives me an unnecessary line break within a string.
I'd rather write to stderr and use string literal concatenation:
fprintf(stderr,
" The row and column number of the matrix"
" must be positive integers.\n"
"\n"
" double **i_mR(); \n"
"\n");

}

/* ------------------------------
Do : free the arrays when they are no longer needed
---------------------------- */
void f_mR(
double **A
)
{
free(A[0]);

I'd be more careful:
if (A)
free(A[0]);
Freeing a null pointer is allowed, taking the value is not.
free(A);
}

/* --------------------------------- MAIN */
int main()

Make it explicit:
int main (void)
<snip>

Notes:
A matrix type
struct matrix {
size_t rows;
size_t cols;
double **data;
}
is the clearest way of expressing what you want.
If you want to say "1" to "rows"/"cols", you can use access
macros providing the necessary offset.
If you really want to access A.data[1][1] through
A.data[A.rows][A.cols], you can still save some memory compared
to your solution:
- Allocate an array "rows+1" of pointer to double for A, set A[0] = NULL
- Allocate an array "rows*cols+1" of double for A[1] and set
A to point to A[1][i*rows*cols].
- This wastes only sizeof (double) + sizeof (double*) bytes

If you want to stay with one double** instead of "struct matrix",
then
- Allocate an array "rows+1" of pointer to double for A
- Allocate an array "rows*cols+2" of double for A[0] and set
A to point to A[0][(i-1)*rows*cols+1] for i>0.

Cheers
Michael
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top