The overarching theme of the following: an array element can be used all the places a variable of its type could be used.
As a variable:
int a[5] = {0, 0, 0, 0, 0};
As a parameter:
void foo(int a[5]); OR
void bar(int a[]);
Assigning to an array element:
a[0] = 5;
Assigning to an entire array:
CAN'T BE DONE.
Getting an array element's value:
x = a[0]
Getting an array's value:
CAN'T BE DONE. (What would it mean, anyway?)
Passing an element as a parameter:
baz(a[0]); (just like passing a variable of the element type)
Passing an entire array as a parameter:
bif(a);Note that arrays are (annoyingly) not like other variables when you pass them as parameters. The array is not copied; rather, you gain access to the original array elements directly. Therefore, what does the following do?
void bof(int array_param[], int length) { int index; for (index = 0; index < length; index++) array_param[index] = index; } int main(void) { int main_array[5] = {0, 0, 0, 0, 0}; bof(main_array, 5); }
#include <stdio.h> #define ROWS = 2; #define COLS = 3; int main(void) { int arr[ROWS][COLS] = { { 0, 1, 2 }, { 3, 4, 5 } }; int i, j; for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) printf("%d ", arr[i][j]); printf("\n"); } return 0; }prints the following:0 1 2 3 4 5
1. Write code that declares a 2-dimensional array of height and width 5, and initializes all the elements to zero.
There were two ways to do this; one by sticking to the strict definition of initialization, which means doing it in the declaration:
int my_array[5][5] = { {0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0} };
The other way was to set all the values to 0 in a nested loop:
int my_array[5][5];
int row, col;
for (row = 0; row < 5; row++)
for (col = 0; col < 5; col++)
my_array[row][col] = 0;
2. Write a function that, given an array, a start row, an end row, and an array width, sums all numbers between those two rows (inclusive).
int sum_rows(int a[][], int startrow, int endrow, int width) {
int sum = 0;
int row, col;
for (row = startrow; row <= endrow; row++)
for (col = 0; col < width; col++)
sum += a[row][col];
return sum;
}
Minor note: I changed the return type of this and the next exercise from the versions on the handout, because it doesn't make much sense to compute the sum and then do nothing with it.
3. Write a function that, given an array and a rectangle (upper-left coordinates and lower-right coordinates), sums all numbers in that rectangle.
int sum_rectangle(int a[][],
int top, int left,
int bottom, int right) {
int sum = 0;
int row, col;
for (row = top; row <= bottom; row++)
for (col = left; col <= right; col++)
sum += a[row][col];
}
To do at home: Write a function that, given an array and a rectangle, copies the values in that rectangle to another rectangular region in the array. The header should look like this:
void copy_rect(int a[][],
int top, int left, int bottom, int right,
int change_x, int change_y);
So, for example, given an array of integers on the left, copy_rect(array, 1, 1, 2, 3, 1, 2) will make it look like the one on the right:
1 1 1 1 1 1 1 1 1 1 1 1
1 0 0 0 1 1 1 0 0 0 1 1
1 0 0 0 1 1 ====> 1 0 0 0 1 1
1 1 1 1 1 1 1 1 0 0 0 1
1 1 1 1 1 1 1 1 0 0 0 1
There are a few different ways to do this. I'm going to introduce a little cleverness, rather than doing it the most obvious way, because I want you to think about how the code works. Another note: I'm writing this late at night and the copy_rect operation is notoriously tricky. If you test my code and find that it doesn't work, I apologize. (Hint: I am suggesting you test the code to make sure it works, in the hope that it will help you understand 2-d arrays better..)
void copy_rect(int a[][],
int top, int left, int bottom, int right,
int change_x, int change_y) {
/* First of all, notice that we're going to have to change the
starting corner depending on the values of change_x and
change_y. This is because we don't want to overwrite values
before they're copied in the case of overlapping start and end
regions. These next 6 variables allow you to keep track of
that. */
int x_start, x_end, x_step;
int y_start, y_end, y_step;
int row, col; /* Loop indexes */
/* Set vertical traversal method */
if (change_y > 0) {
/* If we're moving down, we need to start at the
bottom row. */
y_start = bottom;
y_end = top;
y_step = -1;
} else {
/* Otherwise, start at top. */
y_start = top;
y_end = bottom;
y_step = 1;
}
/* Set horizontal traversal method */
if (change_x > 0) {
/* If we're moving right, we need to start copying at the right. */
x_start = right;
x_end = left;
x_step = -1;
} else {
/* Otherwise, start at left */
x_start = left;
x_end = right;
x_step = 1;
}
/* Do traversal */
for (row = y_start; row <= y_end; row += y_step) {
for (col = x_start; col <= x_end; col += x_step) {
/* Can you explain in a sentence what the following line
does? Can you draw a picture of it? If not, you need
to study more about 2-d arrays. */
a[row+change_y][col+change_x] = a[row][col];
}
}
}
An array gives us a collection of uniform data, accessed by number. A struct, by contrast, gives us a collection of possibly nonuniform data, accessed by name:
/* Define structured type */
typedef struct {
int id;
double gpa;
} Student;
/* Declare variables of that type. */
Student alice, bob;
/* Use the structure "members" or "fields" anywhere you use
variables of the appropriate type. */
alice.id = 9523672898;
alice.gpa = 4.0;
printf("%d", alice.id);
scanf("%lf", &(bob.gpa)); /* Parenthesis not necessary, but aids clarity */
double avg_gpa = (alice.gpa + bob.gpa) / 2.0;
void initialize(Student * my_student) {
my_student->id = 0; /* same as (*my_student).id = 0; */
my_student->gpa = 4.0;
}
int main(void) {
initialize( &my_student );
}