09 TwoDim Arrays
09 TwoDim Arrays
1
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Declaring 2-D Arrays
int m[4][5];
5
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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]
7
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Array Addresses Output
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
How to read the elements of a 2-D array?
By reading them one element at a time
9
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
How to print the elements of a 2-D array?
10
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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];
11
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
A 2-D array is an array or 1-D arrays, and so a row pointer
#include <stdio.h>
int main ()
{
int i, j, A[4][5] = { { 7, 14, 3, 16, 6}, {11, 5, 9, 13, 18},
{ 2, 15, 20, 1, 19}, {10, 4, 12, 17, 8} };
for (i=0; i<4; ++i) {
for (j=0; j<5; ++j) printf("%p ", &A[i][j]);
printf("\n");
}
printf("sizeof(A) = %3lu, A = %p, A + 1 = %p\n", sizeof(A), A, A + 1);
printf("sizeof(*A) = %3lu, *A = %p, *A + 1 = %p\n", sizeof(*A), *A, *A + 1);
printf("sizeof(&A) = %3lu, &A = %p, &A + 1 = %p\n", sizeof(&A), &A, &A + 1);
return 0;
} Output
0x7ffc314fe100 0x7ffc314fe104 0x7ffc314fe108 0x7ffc314fe10c 0x7ffc314fe110
0x7ffc314fe114 0x7ffc314fe118 0x7ffc314fe11c 0x7ffc314fe120 0x7ffc314fe124
0x7ffc314fe128 0x7ffc314fe12c 0x7ffc314fe130 0x7ffc314fe134 0x7ffc314fe138
0x7ffc314fe13c 0x7ffc314fe140 0x7ffc314fe144 0x7ffc314fe148 0x7ffc314fe14c
sizeof(A) = 80, A = 0x7ffc314fe100, A + 1 = 0x7ffc314fe114
sizeof(*A) = 20, *A = 0x7ffc314fe100, *A + 1 = 0x7ffc314fe104
sizeof(&A) = 8, &A = 0x7ffc314fe100, &A + 1 = 0x7ffc314fe150
12
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Passing 2-d arrays to functions
13
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example
15
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example: Matrix addition with functions
void ReadMatrix (int A[][100], int x, int y)
{
int i, j;
for (i=0; i<x; i++)
for (j=0; j<y; j++)
scanf (“%d”, &A[i][j]);
}
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example:
#include <stdio.h> void add (int x[][25], int y[][25], int m,
int main() { int n, int z[][25])
int a[15][25], b[15][25], c[15][25]; {
int m, n; int p, q;
scanf (“%d %d”, &m, &n); for (p=0; p<m; p++)
for (p=0; p<m; p++) for (q=0; q<n; q++)
for (q=0; q<n; q++) z[p]q] = x[p][q] + y[p][q];
scanf (“%d”, &a[p][q]); }
for (p=0; p<m; p++)
for (q=0; q<n; q++)
Note that the number of columns has to be
scanf (“%d”, &b[p][q]);
fixed in the function definition.
add (a, b, m, n, c);
for (p=0; p<m; p++) { • There is no difference between
for (q=0; q<n; q++) void add( int x[ ][25], … ) and
printf(“%f ”, c[p][q]); void add( int x[15][25], … )
printf(“\n”);
• Specifying the first dimension is not
}
}
necessary, but not a mistake.
18
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example: Transpose of a matrix
19
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Example: Transpose of a matrix
20
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
The Correct Version
21
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Dynamically allocating 2-d arrays
A brief discussion
22
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
You may recall …
We have discussed the issue of dynamically allocating space for 1-D arrays
• Using malloc()library function.
int *ptr;
23
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
How to dynamically allocate a 2-d array?
24
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Fixed number of rows, but variable number of columns
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Possible to have rows with different number of elements
r[0]
r[1]
r[2]
26
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *r[3], i, j, col;
Output
for (i=0; i<3; ++i) {
col = 2 * (i+1); 0 1
r[i] = (int *) malloc (col*sizeof(int)); 1 2 3 4
for (j=0; j<col; ++j) 2 3 4 5 6 7
r[i][j] = i + j;
}
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
We have studied only 2-d arrays.
C allows arrays of higher dimensions as well.
28
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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.
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
ADVANCED TOPICS
30
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
32
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Dynamic version of A
int A[10][20];
But
int *p[20];
33
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Dynamic version of B
int B[10];
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.
Note: It is illegal to set q = A; or p = B; Expect segmentation fault if you do so (ignoring the warnings
issued by the compiler).
34
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Dynamic memory for p
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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 an
dynamically allocated array of rows.
The row size must be fixed beforehand. But we can allocate exactly n rows to reduce wastage.
37
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
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
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Storage of Vandermonde matrices (continued)
int main ()
{
double A[MAXDIM], (*V)[MAXDIM];
int n, i;
39
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Antisymmetric matrices
A symmetric matrix is an n x n matrix with aij = aji for all i, j.
An antisymmetric matrix is an n x n matrix with aij = –aji for all i, j. Since aii = –aii , the major
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 use a fully dynamic 2-d array to store only the elements above the main diagonal.
The function genasm(n) returns a pointer to this array given n as input. Here, we take aij = i – j.
40
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Compact storage of an antisymmetric matrix
#include <stdio.h>
#include <stdlib.h>
41
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Storage of antisymmetric matrices (continued)
void prnasm ( int *U[], int n )
{
int i, j;
for (i=0; i<n; ++i) { Exercise: Free the 2-d
for (j=0; j<i; ++j) printf("%3d ", -U[j][i-j-1]); memory allocated to U.
printf(" 0 ");
for (j=i+1; j<n; ++j) printf("%3d ", U[i][j-i-1]);
printf("\n");
} Output
}
Enter dimension (n): 5
int main () 0 -1 -2 -3 -4
{ 1 0 -1 -2 -3
int **U, n; 2 1 0 -1 -2
printf("Enter dimension (n): "); scanf("%d", &n); 3 2 1 0 -1
4 3 2 1 0
U = genasm(n);
prnasm(U,n);
exit(0);
}
42
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR
Four types of 2-d arrays
43
INDIAN INSTITUTE OF TECHNOLOGY KHARAGPUR