470,863 Members | 1,232 Online

# dynamically allocate a multidimensional array

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

A = number of rows
A = number of columns

The first element of the matrix is A

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; r++)
{
printf("\n");
for (c=1; c<A; 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; r++)
for (c=1; c<A; 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 = malloc(ar * ac * 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 * ac * sizeof(**A) );\n\n");
fflush(stdout);
getchar();
exit(EXIT_FAILURE);
}

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

A=ar;
A=ac;

return(A);
}

/* ------------------------------
Do : free the arrays when they are no longer needed
---------------------------- */
void f_mR(
double **A
)
{
free(A);
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; i++)
for (j=1; j<A; j++)

A[i][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);

getchar();

return 0;
}

Aug 10 '06 #1
2 3242 xhunga schrieb:
I have try a new version of my work.
I have put the sizes of the matrix into the matrix.

A = number of rows
A = number of columns
I would have expected symmetry:
A and A
>
The first element of the matrix is A

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 or A cannot hold all
possible row or column numbers, then you may run into
subtle trouble, especially for floating point types.
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; r++)
{
printf("\n");
for (c=1; c<A; 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++)
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.

<snip>
/* ----------------------------------------
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");

<snip>
}

/* ------------------------------
Do : free the arrays when they are no longer needed
---------------------------- */
void f_mR(
double **A
)
{
free(A);
I'd be more careful:
if (A)
free(A);
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 through
A.data[A.rows][A.cols], you can still save some memory compared
- Allocate an array "rows+1" of pointer to double for A, set A = NULL
- Allocate an array "rows*cols+1" of double for A and set
A[i] to point to A[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 and set
A[i] to point to A[(i-1)*rows*cols+1] for i>0.

Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.
Aug 10 '06 #2