08 TwoDim Arrays
08 TwoDim Arrays
1
Two Dimensional Arrays
We have seen that an array variable can store a list of values.
Many applications require us to store a table of values.
Student 2 68 75 80 70 72
Student 3 88 74 85 76 80
Student 4 50 65 68 40 70
2
Two Dimensional Arrays
Subject 1 Subject 2 Subject 3 Subject 4 Subject 5
Student 1 75 82 90 65 76
Student 2 68 75 80 70 72
Student 3 88 74 85 76 80
Student 4 50 65 68 40 70
3
Declaring 2-D Arrays
General form:
type array_name[row_size][column_size];
Examples:
int marks[4][5];
float sales[12][25];
double matrix[100][100];
4
Declaring 2-D Arrays
int m[4][5];
5
Accessing Elements of a 2-D Array
Similar to that for 1-D array, but use two indices.
• First index indicates row, second index indicates column.
• Both the indices should be expressions which evaluate to integer values.
Examples:
x[m][n] = 0;
c[i][k] += a[i][j] * b[j][k];
val = sqrt( arr[j*3][k+1] );
6
How is a 2-D array stored in memory?
Starting from a given memory location (starting address of the array), the elements are stored
row-wise in consecutive memory locations.
• x: starting address of the array in memory
• c: number of columns
• k: number of bytes allocated per array element, e.g., sizeof(int)
a[0][0] a[0][1] a[0][2] a[0][3] a[1][0] a[1][1] a[1][2] a[1][3] a[2][0] a[2][1] a[2][2] a[2][3]
3221224480
int main() 3221224484
{ 3221224488
int a[3][5]; 3221224492
int i, j; 3221224496
3221224500
for (i=0; i<3;i++) 3221224504
{ 3221224508
for (j=0; j<5; j++) 3221224512
printf ("%u\n", &a[i][j]); 3221224516
printf ("\n");
3221224520
} 3221224524
return 0; 3221224528
} 3221224532
3221224536
8
How to read the elements of a 2-D array?
By reading them one element at a time
9
How to print the elements of a 2-D array?
10
Example: Matrix addition
int main()
{ for (p=0; p<m; p++)
int a[100][100], b[100][100], for (q=0; q<n; q++)
c[100][100], p, q, m, n; c[p][q] = a[p][q] + b[p][q];
12
Passing 2-d arrays to functions
13
Passing 2-D arrays to functions
For calculating the address of an element in a 2-D array, the function needs:
• The starting address of the array in memory (say, x) a[i][j] is located at memory
• Number of bytes per element (say, k) address x + (i * c + j) * k
• Number of columns in the array, i.e., the size of each row (say, c)
14
Example
void AddMatrix( int A[][100], int B[][100], int C[][100], int x, int y)
{
int i, j;
for (i=0; i<x; i++)
for (j=0; j<y; j++)
C[i][j] = A[i][j] + B[i][j];
}
16
Example: Matrix addition
int main()
{
void PrintMatrix (int A[][100], int x, int y) int a[100][100], b[100][100],
{ c[100][100], p, q, m, n;
int i, j;
printf (“\n”); scanf (“%d%d”, &m, &n);
for (i=0; i<x; i++)
{ ReadMatrix(a, m, n);
for (j=0; j<y; j++) ReadMatrix(b, m, n);
printf (“ %5d”, A[i][j]);
printf(“\n”); AddMatrix(a, b, c, m, n);
}
} PrintMatrix(c, m, n);
return 0;
}
17
Example: void add (int x[][25], int y[][25], int m,
int n, int z[][25])
{
#include <stdio.h> int p, q;
int main() { for (p=0; p<m; p++)
int a[15][25], b[15][25], c[15][25]; for (q=0; q<n; q++)
int m, n; z[p][q] = x[p][q] + y[p][q];
scanf (“%d %d”, &m, &n); }
for (p=0; p<m; p++)
for (q=0; q<n; q++)
scanf (“%d”, &a[p][q]); Note that the number of columns has to be
for (p=0; p<m; p++) fixed in the function definition.
for (q=0; q<n; q++)
• There is no difference between
scanf (“%d”, &b[p][q]);
add (a, b, m, n, c);
void add( int x[ ][25], … ) and
for (p=0; p<m; p++) { void add( int x[15][25], … )
for (q=0; q<n; q++) • Specifying the first dimension is not
printf(“%f ”, c[p][q]); necessary, but not a mistake.
printf(“\n”);
}
} 18
Example: Transpose of a matrix
19
Example: Transpose of a matrix
21
Dynamically allocating 2-d arrays
A brief discussion
22
You may recall …
We have discussed the issue of dynamically allocating space for 1-D arrays
• Using malloc()library function.
int *ptr;
23
How to dynamically allocate a 2-d array?
24
Fixed number of rows, but variable number of columns
Let us assume the number of rows is fixed to 3.
We can use an array of pointers of size 3, where the ith element of this array (a pointer) will point
to the ith row of the 2-d array.
int *r[3], i, c;
printf (”Enter nos. of columns of the 2-d array:”);
scanf(”%d”, &c); // each row will have c elements
for (i=0;i<3;i++)
r[i] = (int *) malloc(c * sizeof(int)); // allocate i-th row
25
Possible to have rows with different number of elements
r[0]
r[1]
r[2]
26
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *r[3], i, j, col;
for (i=0; i<3; ++i) { Output
col = 2 * (i+1);
r[i] = (int *) malloc (col*sizeof(int)); 0 1
for (j=0; j<col; ++j) 1 2 3 4
r[i][j] = i + j; 2 3 4 5 6 7
}
for (i=0; i<3; ++i) {
col = 2 * (i+1);
for (j=0; j<col; ++j)
printf("%d ", r[i][j]);
printf("\n");
}
return 0;
}
27
We have studied only 2-d arrays.
C allows arrays of higher dimensions as well.
28
Practice problems
1. Write a function that takes an n x n square matrix A as parameter (n < 100) and returns 1 if A
is an upper-triangular matrix, 0 otherwise.
2. Repeat 1 to check for lower-triangular matrix, diagonal matrix, identity matrix.
3. Consider a n x n matrix containing only 0 or 1. Write a function that takes such a matrix and
returns 1 if the number of 1’s in each row are the same and the number of 1’s in each column
are the same; it returns 0 otherwise.
4. Write a function that reads in an m x n matrix A and an n x p matrix B, and returns the
product of A and B in another matrix C. Pass appropriate parameters.
5. Write a function to find the transpose of a non-square matrix A in a matrix B.
6. Repeat the last exercise when the transpose of A is computed in A itself. Use no additional 2-
d arrays.
For each of the above, also write a main function that reads the matrices, calls the function, and
prints the results (a message, the result matrix etc.)
29
ADVANCED TOPICS
30
Generalization from one-dimensional arrays
Consider the statically allocated 1-d array:
int A[20];
int *p;
● What are the analogous pointers for 2-d arrays that you have seen earlier?
● How can these pointers be allocated and deallocated their own memory? 31
What are our 2-d arrays?
We have seen two types of 2-d arrays:
int A[10][20];
int *B[10];
As statically allocated arrays, both A and B suffer from the two standard disadvantages:
● Waste of space
● Inadequacy to handle larger than the allocated space
But
int *p[20];
int **q;
● The number of rows can be decided during the run of the program.
● The size of each row can also be decided individually during the run.
p is a single pointer, and can be allocated and deallocated memory in a single shot.
● Method 1:
p = (int (*)[20])malloc(10 * 20 * sizeof(int));
● Method 2:
p = (row *)malloc(10 * sizeof(row));
● Method 3:
p = (typeof(int [20]) *)malloc(10 * 20 * sizeof(typeof(int [20])));
free(p);
35
Dynamic memory for q
First, you allocate the required number of row headers, and then the rows individually.
Note: Free the individual rows before freeing the array of row headers.
36
Example: Vandermonde matrices
A Vandermonde matrix corresponding to n real-valued elements a0, a1, …, an-1 is defined as:
1 1 1 … 1
a0 a1 a2 … an-1
a0 2 a1 2 a2 2 … an-12
⋮ ⋮ ⋮ … ⋮
a0n-1 a1n-1 a2n-1 … an-1n-1
An application works with Vandermonde matrices for n ≤ 100. A static 2-d array would require a
total storage of 100 x 100 = 10,000 cells. This leads to waste if n is small.
We write a function genvdm(A,n) that obtains a0, a1, …, an-1 from the 1-d array A, and returns a
pointer to a dynamically allocated array of rows.
37
The row size must be fixed beforehand. But we can allocate exactly n rows to reduce wastage.
Dynamic memory for storing Vandermonde matrices
#include <stdio.h>
#include <stdlib.h>
#define MAXDIM 100
double (*genvdm ( double *A, int n )) [MAXDIM]
{
double (*p)[MAXDIM];
int i, j;
p = (double (*)[MAXDIM])malloc(n * MAXDIM * sizeof(double));
for (i=0; i<n; ++i) {
// i is an index in A, and a column in p. j is a row in p.
p[0][i] = 1;
for (j=1; j<n; ++j) p[j][i] = p[j-1][i] * A[i];
}
return p;
}
void prnvdm ( double M[][MAXDIM], int n )
{
int i, j;
for (i=0; i<n; ++i) {
for (j=0; j<n; ++j) printf("%10.5lf ", M[i][j]);
printf("\n");
} 38
}
Storage of Vandermonde matrices (continued)
int main ()
{
double A[MAXDIM], (*V)[MAXDIM];
int n, i;
An antisymmetric matrix is an n x n matrix with aij = –aji for all i, j. Since aii = –aii , the main diagonal
is filled by 0. Moreover, the entries below the main diagonal can be obtained from the entries above
the main diagonal.
0 5 3 –2 4
–5 0 –6 –1 0
–3 6 0 2 7
2 1 –2 0 1
–4 0 –7 –1 0
We can use a fully dynamic 2-d array to store only the elements above the main diagonal.
40
Compact storage of an antisymmetric matrix
The function genasm(n) returns a pointer to the “array” given n as input. Let us take aij = i –
j.
#include <stdio.h>
#include <stdlib.h>
43